開啟串列埠號大於9的串列埠,CreateFile返回失敗!
近日,從網路上移植如下程式碼用於列舉計算機有效串列埠號。
void EnumCom() { CString strCOM; BOOL bResult; HANDLE hCom; int i; DWORD dwError; m_uiCom.RemoveAll(); for (i = 1; i <= 255; i ++) { //形成串列埠名稱 strCOM.Format(_T("COM%d"), i); bResult = FALSE; //嘗試開啟串列埠 hCom = CreateFile(strCOM, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0); if (hCom == INVALID_HANDLE_VALUE) { dwError = GetLastError(); if (dwError == ERROR_ACCESS_DENIED) { bResult = TRUE; m_uiCom.Add(i); } } else { bResult = TRUE; m_uiCom.Add(i); CloseHandle(hCom); } } }
除錯時發現開啟串列埠大於9的串列埠開啟失敗,GetLastError()函式返回2。
檢視MSDN中System Error Codes頁面,錯誤程式碼2是這麼描述的,如下圖。
仔細研究MSDN中CreateFile函式的說明,發現有如下一段話。
Win32 Device Namespaces
The "\\.\" prefix will access the Win32 device namespace instead of the Win32 file namespace. This is how access to physical disks and volumes is accomplished directly, without going through the file system, if the API supports this type of access. You can access many devices other than disks this way (using the
For example, if you want to open the system's serial communications port 1, you can use "COM1" in the call to the CreateFile function. This works because COM1-COM9 are part of the reserved names in the NT namespace, although using the "\\.\" prefix will also work with these device names. By comparison, if you have a 100 port serial expansion board installed and want to open COM56, you cannot open it using "COM56" because there is no predefined NT namespace for COM56. You will need to open it using "\\.\COM56" because "\\.\" goes directly to the device namespace without attempting to locate a predefined alias.
Another example of using the Win32 device namespace is using the CreateFile function with "\\.\PhysicalDisk X" (where X is a valid integer value) or "\\.\CdRom X". This allows you to access those devices directly, bypassing the file system. This works because these device names are created by the system as these devices are enumerated, and some drivers will also create other aliases in the system. For example, the device driver that implements the name "C:\" has its own namespace that also happens to be the file system.
APIs that go through the CreateFile function generally work with the "\\.\" prefix because CreateFile is the function used to open both files and devices, depending on the parameters you use.
If you're working with Windows API functions, you should use the "\\.\" prefix to access devices only and not files.
Most APIs won't support "\\.\"; only those that are designed to work with the device namespace will recognize it. Always check the reference topic for each API to be sure.
翻譯成中文簡單講就是:如果需要開啟串列埠大於9的串列埠,需要在“COM10”前加上“\\.\”的字首。因此,上述程式碼改為如下。
strCOM.Format(_T("\\\\.\\COM%d"), i);
綜上所述,仔細閱讀MSDN還是很重要的!!!