2011-12-21 14 views
6

System: Windows 7 32bit
Język: C++Dlaczego funkcja RegQueryValueEx() zwraca ERROR_FILE_NOT_FOUND podczas próby odczytu z klucza rejestru?

Próbowałem dostęp zarejestrować HKEY_LOCAL_MACHINE\\HARDWARE\\DEVICEMAP\\Scsi\\Scsi Port 0, kluczową Driver (typ REG_SZ) - nie ma problemu.

To samo dla odczytu z HKEY_LOCAL_MACHINE\\HARDWARE\\DEVICEMAP\\SERIALCOMM, wszystkie klucze (typy REG_SZ) mają ukośniki, na przykład \Device\Serial0.

Czytając takie klucze zawsze zwraca 2 (Nie ma takiego pliku) z poniższym przykładzie kodu:

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 --- 

Jaki jest właściwy sposób odczytać wartości klucza z ukośniki w nazwie?


Powyżej został poprawnie odebrany przez Cody Gray. Poniżej kolejny numer.


Im dostawanie ten sam problem, gdy Im przy zmiennej zamiast ciągu tekstowego.
Iv uważane obu podejść z pojedynczych i podwójnych ukośników:

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! 

próbowałem wszystkie odmiany z "\ Device ..", "/ Device", "\ Device", itp

+3

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

+0

@Werner, nie, funkcja 'RegQueryValueEx' only * * zapytuje o wartość klucza rejestru. Wartości to pary nazwa/dane przechowywane w kluczach. Dlatego nie można przekazać jej zagnieżdżonej ścieżki kluczy, ponieważ opisy nie zawierają ścieżek. Trzeba przyznać, że terminologia jest dość myląca, Raymond Chen próbował ją wyjaśnić [tutaj] (http://blogs.msdn.com/b/oldnewthing/archive/2009/02/04/9394113.aspx). –

Odpowiedz

7

Masz ucieczka ukośników, tak jak miało to miejsce w pierwszej linii ...

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 

Jeśli nie, funkcja RegQueryValueEx nie może odnaleźć określonego klucza i zwraca ERROR_FILE_NOT_FOUND (== 2).


Ale jest inny problem. Powinieneś być deklarowania tablicy bufora jak typ wchar_t (lub TCHAR), zamiast char:

TCHAR buf[255] = {0}; 

przeciwnym razie funkcja RegQueryValueEx będzie próbować wypełnić tablicę z ciągiem Unicode czytać z określonego klucza rejestru, i dostaniesz coś nieczytelnego.

+0

buf należy zadeklarować jako TCHAR, a nie jako wchar_t. ReqQueryValueEx nie dba o deklarację buf, zwrócona wartość zależy od tego, czy wywołana jest RegQueryValueExA, czy RegQueryValueExW. –

+0

@Werner: Tak, to prawda techniczna.Ale aplikacje Windows nie zostały skompilowane jako ANSI (nie-Unicode) od ponad 10 lat. Wiele osób nie chce już korzystać z makr i trudno ich za to winić. –

+0

Twoja odpowiedź jest raczej zoptymalizowana, aby dać OP trudny czas. Składnia C++ 11, WMI jest dość nieprzyjazny w C++, porty szeregowe nie są urządzeniami typu plug-and-play. –

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(); 
     } 

    } 
} 

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

+1

nie używamy .NET – killdaclick

Powiązane problemy