2011-10-05 125 views
7

我打开一个串口使用CreateFile()。我有一个测试用例(太复杂,无法重新分配),导致CreateFile()返回INVALID_HANDLE_VALUEGetLastError()返回ERROR_SUCCESS。从外观上看,只有当一个线程在另一个端口关闭的同时打开端口时,才会出现此错误。打开端口的线程遍历这个问题。CreateFile()返回INVALID_HANDLE_VALUE,但GetLastError()是ERROR_SUCCESS

我不知道这是否有所作为,但后来在代码中我使用CreateIoCompletionPort将端口与CompletionPort相关联。

这里是我的代码:

HANDLE port = CreateFile(L"\\\\.\\COM1", 
         GENERIC_READ | GENERIC_WRITE, 
         0,     // must be opened with exclusive-access 
         0,     // default security attributes 
         OPEN_EXISTING,  // must use OPEN_EXISTING 
         FILE_FLAG_OVERLAPPED, // overlapped I/O 
         0);     // hTemplate must be NULL for comm devices 
if (port == INVALID_HANDLE_VALUE) 
{ 
    DWORD errorCode = GetLastError(); 
    cerr << L"CreateFile() failed with error: " << errorCode << endl; 
} 

我敢肯定这样的事情不应该发生的。我做错了什么?我如何让API返回正确的结果?


更多详情JPeripheral

下面是实际的(unsanitized)源代码:

JLong SerialChannel::nativeOpen(String name) 
{ 
    cerr << "nativeOpen(" << name << ")" << endl; 
    wstring nameWstring = name; 
    HANDLE port = CreateFile((L"\\\\.\\" + nameWstring).c_str(), 
     GENERIC_READ | GENERIC_WRITE, 
     0,           // must be opened with exclusive-access 
     0,           // default security attributes 
     OPEN_EXISTING,     // must use OPEN_EXISTING 
     FILE_FLAG_OVERLAPPED,  // overlapped I/O 
     0);           // hTemplate must be NULL for comm devices 
    cerr << "nativeOpen.afterCreateFile(" << name << ")" << endl; 
    cerr << "port: " << port << ", errorCode: " << GetLastError() << endl; 
    if (port == INVALID_HANDLE_VALUE) 
    { 
     DWORD errorCode = GetLastError(); 

     switch (errorCode) 
     { 
      case ERROR_FILE_NOT_FOUND: 
       throw PeripheralNotFoundException(jace::java_new<PeripheralNotFoundException>(name, Throwable())); 
      case ERROR_ACCESS_DENIED: 
      case ERROR_SHARING_VIOLATION: 
       throw PeripheralInUseException(jace::java_new<PeripheralInUseException>(name, Throwable())); 
      default: 
      { 
       throw IOException(jace::java_new<IOException>(L"CreateFile() failed with error: " + 
        getErrorMessage(GetLastError()))); 
      } 
     } 
    } 

    // Associate the file handle with the existing completion port 
    HANDLE completionPort = CreateIoCompletionPort(port, ::jperipheral::worker->completionPort, Task::COMPLETION, 0); 
    if (completionPort==0) 
    { 
     throw AssertionError(jace::java_new<AssertionError>(L"CreateIoCompletionPort() failed with error: " + 
      getErrorMessage(GetLastError()))); 
    } 
    cerr << "nativeOpen.afterCompletionPort(" << name << ")" << endl; 

    // Bind the native serial port to Java serial port 
    SerialPortContext* result = new SerialPortContext(port); 
    cerr << "nativeOpen.afterContext(" << name << ")" << endl; 
    return reinterpret_cast<intptr_t>(result); 
} 

此代码是从一个串行端口库我已经开发采取这里是我得到的实际输出:

nativeOpen(COM1) 
nativeOpen.afterCreateFile(COM1) 
port: 00000374, errorCode: 0 
nativeOpen.afterCompletionPort(COM1) 
nativeOpen.afterContext(COM1) 
[...] 
nativeOpen(COM1) 
nativeOpen.afterCreateFile(COM1) 
port: FFFFFFFF, errorCode: 0 
java.io.IOException: CreateFile() failed with error: The operation completed successfully. 
+0

这些行是您在测试中使用的确切行吗?任何简化(甚至显然无害)都可能隐藏问题的根源。 –

+0

您访问的硬件是什么? – Gabe

+0

@Gabe:我正在访问我们内部开发的嵌入式设备。它有一个标准的DB9串行端口连接,我已连接到我的PC(这里没有USB-RS232适配器)。 – Gili

回答

8
HANDLE port = CreateFile(...); 
cerr << "nativeOpen.afterCreateFile(" << name << ")" << endl; 
cerr << "port: " << port << ", errorCode: " << GetLastError() << endl; 
if (port == INVALID_HANDLE_VALUE) 
{ 
    DWORD errorCode = GetLastError(); 

对cerr的输出调用winapi调用。这将重置由GetLastError()返回的线程错误值。修复:

HANDLE port = CreateFile(...); 
int err = GetLastError(); 
// etc, use err instead... 
+0

我不相信。有这个问题的原始代码不包含任何'cerr'指令。我最近只添加了这个。你看到上面的代码有错吗(减去'cerr')? – Gili

+1

您显示的输出跟踪只能由*确实*弄乱GetLastError值的代码生成。我不怀疑它可能会失败,打开COM端口失败的原因很多。 –

+0

你是对的。原始代码调用'throw IOException(jace :: java_new (L“CreateFile()failed with error:”+ getErrorMessage(GetLastError()))'。注意在失败点和读取GetLastError ()'。更快的读取数值解决了这个问题。谢谢! – Gili

相关问题