2011-12-21 33 views
6

hệ thống: Windows 7 32bit
Ngôn ngữ: C++Tại sao hàm RegQueryValueEx() trả về ERROR_FILE_NOT_FOUND trong khi cố gắng đọc từ khóa đăng ký?

Tôi đã cố gắng để truy cập đăng ký HKEY_LOCAL_MACHINE\\HARDWARE\\DEVICEMAP\\Scsi\\Scsi Port 0, phím Driver (loại REG_SZ) - không có vấn đề.

Điều tương tự để đọc từ HKEY_LOCAL_MACHINE\\HARDWARE\\DEVICEMAP\\SERIALCOMM, tất cả các phím (loại REG_SZ) có dấu gạch chéo, ví dụ: \Device\Serial0.

Trong khi đọc các phím như vậy nó luôn luôn trả 2 (không có tập tin như vậy) với mã sau đây ví dụ:

HKEY hKey = 0; 
DWORD dwType = REG_SZ; 
char buf[255] = {0}; 
DWORD dwBufSize = sizeof(buf); 

if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("HARDWARE\\DEVICEMAP\\SERIALCOMM"), 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS) 
{ 
    auto ret = RegQueryValueEx(hKey, TEXT("\Device\Serial0"), 0, &dwType, (LPBYTE)buf, &dwBufSize); 
    // ret always == 2 for key with slashes 
--- CUT --- 

cách thích hợp để đọc các giá trị quan trọng với dấu gạch chéo tên là gì?


Ở trên đã được Cody Gray trả lời đúng.
Bên dưới một vấn đề khác.


Tôi gặp vấn đề tương tự khi sử dụng biến thay vì chuỗi văn bản.
Iv coi cả hai phương pháp tiếp cận với đơn và đôi slashes:

HKEY hKey = 0; 
DWORD keyType = REG_SZ; 
TCHAR buf[255] = {0}; 
DWORD bufSize = sizeof(buf); 

QSettings winReg("HKEY_LOCAL_MACHINE\\HARDWARE\\DEVICEMAP\\SERIALCOMM", QSettings::NativeFormat); 
auto comsKey = winReg.allKeys(); 

FOREACH(auto com, comsKey) 
{ 
    // FOREACH - boost macro 
    // comsKey = QList<QString> (list of key names) [from Qt framework] 
    // com = QString (single key name) [from Qt framework] 
    if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("HARDWARE\\DEVICEMAP\\SERIALCOMM"), 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS) 
    { 
    wchar_t* keyw = new wchar_t(); 
    //com.replace("/", "\\\\"); <- checked both variants commented and not commented; com == /Device/Serial0 so im converting to \\Device\\Serial0 
    int size = com.size(); 
    mbstowcs(keyw, com.toStdString().data(), size); 
    //auto ret = RegQueryValueEx(hKey, TEXT("\\Device\\Serial0"), 0, &keyType, (LPBYTE)buf, &bufSize); // <- this works! 
    auto ret = RegQueryValueExW(hKey, (LPCWSTR)&keyw, 0, &keyType, (LPBYTE)buf, &bufSize); // <- this one not works! 

Tôi đã thử tất cả các biến thể với "\ Device ..", "/ Device", "\ Device", vv

+3

TEXT ("\\ \\ Device Serial0")? –

+0

@Werner, không, chức năng 'RegQueryValueEx' * chỉ * truy vấn giá trị của khóa đăng ký. Giá trị là các cặp tên/dữ liệu được lưu trữ trong các khóa. Vì vậy, bạn không thể vượt qua nó một đường dẫn lồng nhau của các phím như bạn mô tả bởi vì các giá trị không có đường dẫn. Phải thừa nhận rằng, thuật ngữ khá khó hiểu, Raymond Chen đã cố gắng giải thích nó [ở đây] (http://blogs.msdn.com/b/oldnewthing/archive/2009/02/04/9394113.aspx). –

Trả lời

7

Bạn có để thoát khỏi dấu gạch chéo, giống như bạn đã làm trong dòng đầu tiên ...

if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("HARDWARE\\DEVICEMAP\\SERIALCOMM"), 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS) 
{ 
    auto ret = RegQueryValueEx(hKey, TEXT("\\Device\\Serial0"), 0, &dwType, (LPBYTE)buf, &dwBufSize); 
    // ret always == 2 for key with slashes 

Nếu bạn không, các RegQueryValueEx chức năng có thể không tìm thấy chìa khóa chỉ định, và nó trả ERROR_FILE_NOT_FOUND (== 2).


Nhưng còn một vấn đề khác. Bạn nên khai báo mảng đệm as type wchar_t (hoặc TCHAR), chứ không phải là char:

TCHAR buf[255] = {0}; 

Nếu không, RegQueryValueEx chức năng sẽ cố gắng để điền vào mảng với một chuỗi Unicode đọc từ khóa registry chỉ định, và bạn sẽ nhận được một cái gì đó không đọc được.

+0

buf phải được khai báo là TCHAR, không phải là wchar_t. ReqQueryValueEx không quan tâm về cách buf được khai báo, giá trị trả về phụ thuộc vào việc RegQueryValueExA hoặc RegQueryValueExW được gọi. –

+0

@Werner: Vâng, đó là sự thật về mặt kỹ thuật.Nhưng các ứng dụng Windows chưa được biên dịch như ANSI (không phải Unicode) trong hơn 10 năm. Rất nhiều người không quan tâm đến việc sử dụng các macro nữa, và thật khó để đổ lỗi cho họ. –

+0

Câu trả lời của bạn được tối ưu hóa để cung cấp cho OP một thời gian khó khăn. Cú pháp C++ 11, WMI khá không thân thiện với C++, các cổng nối tiếp không phải là các thiết bị cắm và chạy. –

0
using System; 
using System.IO.Ports; 

namespace SerialPortExample 
{ 
    class SerialPortExample 
    { 
     public static void Main() 
     { 
      // Get a list of serial port names. 
      string[] ports = SerialPort.GetPortNames(); 

      Console.WriteLine("The following serial ports were found:"); 

      // Display each port name to the console. 
      foreach(string port in ports) 
      { 
       Console.WriteLine(port); 
      } 

      Console.ReadLine(); 
     } 

    } 
} 

Xem http://msdn.microsoft.com/en-us/library/system.io.ports.serialport.getportnames(v=vs.110).aspx

+1

chúng tôi không sử dụng .NET – killdaclick

Các vấn đề liên quan