Hyper-V Serial Ports and Windows 2008

Unlike many other virtualization solutions, it’s not particularly easy to connect a Windows 2008 Hyper-V guest to its host serial ports.  Perversely, there are settings to connect the guest COM ports to “named pipes,” but there’s no way on the host to connect COM ports to named pipes.  (It appears that this option is used primarily for debugging programs, rather than for using actual serial ports — it doesn’t appear to have been intended to be used to provide actual serial port access from the guest.)

The Hyper-V Deployment guide contains little more than this:

“Note:  No access to a physical COM port is available from a virtual machine.”

What follows is a recipe to access the physical COM ports on the host from a guest using com0com, and its related utilities.  The idea is to make a COM port on the host available via TCP/IP, and then attach to it via the guest, then make this process automatic.

First, on the guest, you’ll need an appropriate version of hub4com, and the batch file bundled with it, com2tcp-rfc2217.bat.  Naturally, I’m running 64-bit Windows 2008, and there doesn’t appear to be a version compiled for 64-bit Windows, so I had to compile my own.  This can be kind of a pain, especially if you’re using Visual Studio Express, so you’re welcome to download my 64-bit hub2com binaries here.

My device is on COM3, and I can make it available on port 7000 using the following command line:

com2tcp-rfc2217 COM3 7000

This gives me a DOS Window that shows me what’s going on — this is handy for debugging, but hardly something I want to leave on my screen all the time.  The simplest solution is to create a launcher script:

Set objShell = CreateObject ("WScript.Shell")
objShell.Run "cmd /K CD C:\Program Files (x86)\com0com & com2tcp-rfc2217 COM3 7000", 0, false

This script effectively hides the program so that it can run in the background, so all that remains is to have it launch when the system starts.  That’s best accomplished using the registry to create a new “Expandable String Value” under “HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run”.  It doesn’t matter what the Name of the String Value is, but the Data should be the command line necessary to launch the script:

%WinDir%\system32\wscript "C:\Program Files (x86)\com0com\com3-listen.vbs"

When done this way, the port is made available whether or not anybody is actually logged into the machine.

The guest is only slightly trickier, requiring both com0com and hub2com binaries to be installed.  Since my guest is 32-bit Windows XP, I could use the precompiled “i386” binaries directly from the c0m0com sourceforge page.

The com0com installer wants to create a null modem pair from “cnca0” to “cncb0.”  You’ll need this pair of virtual devices, and you’ll want to turn on “baud rate emulation,” and rename one end like a regular COM port.    This can be accomplished from the com0com command line setup:

install EmuBR=yes EmuBR=yes
change CNCA0 PortName=COM3

Once the virtual port pair is available, one end can be connected to the host, using the hub2com batch file com2tcp-rfc2217:

com2tcp-rfc2217 \\.\CNCB0 host-hostname 7000

As before, this opens a DOS Window where you can see what’s going on.  At this point, COM3 on the guest is communicating directly with COM3 on the host.  As before, a small launcher script is created to hide this window:

Set objShell = CreateObject ("WScript.Shell")
objShell.Run "cmd /K CD C:\Program Files\com0com & com2tcp-rfc2217 \\.\CNCB0 skypiea 7000", 0, false

And, as before, a registry string is added to the guest to launch this automatically in its own “HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run” key.

%WinDir%\system32\wscript "C:\Program Files\com0com\com3-client.vbs"

Simple, eh?  Well, perhaps not, but once it’s set up, the guest Hyper-V machine can communicate via COM3.  Additional ports can be added in the same way.

Share
Tagged , , , , . Bookmark the permalink.

58 Responses to Hyper-V Serial Ports and Windows 2008

  1. netmatrix says:

    Hi Queued

    Thank you for the post, i am trying to connect a windows 2000 server guest to com1 on Hyper-v 2008 R2 SP1 host.

    Having trouble getting the last step in the process.

    Appreciate your help.

    Thanks in advance!

    PS: I did a net helpmsg of the error code 10061 in windows and it translates to “No connection could be made because the target machine actively refused it”.
    ========================
    D:\Utilities\hub4com-2.0.1.0-386>com2tcp-rfc2217 \\.\CNCB0 pbl-ap01 6000

    D:\Utilities\hub4com-2.0.1.0-386>”hub4com” –create-filter=escparse,com,parse
    –create-filter=pinmap,com,pinmap:”–rts=cts –dtr=dsr” –create-filter=linectl
    ,com,lc:”–br=local –lc=local” –add-filters=0:com –create-filter=telnet,tcp,t
    elnet:” –comport=client” –create-filter=pinmap,tcp,pinmap:”–rts=cts –dtr=d
    sr –break=break” –create-filter=linectl,tcp,lc:”–br=remote –lc=remote” –add
    -filters=1:tcp –octs=off “\\.\CNCB0” –use-driver=tcp “*pbl-ap01:6000”
    Open(“\\.\CNCB0”, baud=19200, data=8, parity=no, stop=1, octs=off, odsr=off, ox=
    off, ix=off, idsr=off, ito=0) – OK
    Route data CNCB0(0) –> TCP(1)
    Route data TCP(1) –> CNCB0(0)
    Route flow control CNCB0(0) –> TCP(1)
    Route flow control TCP(1) –> CNCB0(0)
    Filters:
    _________
    \->{parse.IN}—————–>
    CNCB0(0) | /
    _________/<—–{pinmap.OUT}<-{lc.OUT}{telnet.IN}——————————>
    TCP(1) | /
    _______/<—–{telnet.OUT}<-{pinmap.OUT}<-{lc.OUT}<-

    Socket(0.0.0.0:0) = 2f8
    TCP(1): Connect(2f8, 192.168.22.210:6000) …
    Started CNCB0(0)
    Started TCP(1)
    Connect(2f8) TCP(1) ERROR Unknown error (10061)
    TCP(1): Close(2f8) – OK
    Socket(0.0.0.0:0) = 2f8
    TCP(1): Connect(2f8, 192.168.22.210:6000) …
    Connect(2f8) TCP(1) ERROR Unknown error (10061)

  2. queued says:

    That error (10061) is pretty generic, but it’s almost always because the server side isn’t listening (or is listening to a different port) or the firewall isn’t allowing traffic to that port.

  3. Jared Kells says:

    I wrote this tool to achieve the same thing without installing any drivers on your host machine. https://github.com/jkells/serial-pipe

    It just connects a named pipe to a real serial port. HyperV supports virtual serial ports connected to named pipes. This solution works with any guest operating system. I’m using it for an Ubuntu VM on HyperV.

  4. James Watt says:

    I believe that where you wrote, “First, on the guest, you’ll need an appropriate version of hub4com…” you actually meant to say “on the host” because you’re talking about things related to a 64 bit Server OS.

    And then later, you say, “The guest is only slightly trickier, requiring both com0com and hub2com binaries to be installed. Since my guest is 32-bit Windows XP…” which further concludes what I already suspect.

    I’m going to go ahead and give this a shot and assume the first steps are for my host. Thanks for your help!

  5. filipe says:

    is possible to use it for this USB hardlock?

  6. Alex says:

    on running the com2tcp-rfc2217.bat for the server it shows connection baud rate as 19200. But this is too high for the hardware I’m connecting to.

    Is there a place within the script that I can force 9600 and ensure the script is connecting with the other correct options?

    Parity: non, Data Bits: 8, Stop Bits: 1, and Flow control: Hardware (RTS/CTS)??

    Many Thanks

  7. Tomas Crespo says:

    I think in your recipie your are speaking about “the guest” twice, but one time it has to be “the host”, isn’t it?

  8. Pete says:

    I’ve come across this thread a bit late and the links to https://github.com/jkells/serial-pipe and your 64-bit hub2com binaries no longer appear to work.
    Are they still available please?

    Many thanks

Leave a Reply

Your email address will not be published. Required fields are marked *

By submitting this form, you accept the Mollom privacy policy.

This site uses Akismet to reduce spam. Learn how your comment data is processed.