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.