2011-12-21 5 views
6

Sistema: Windows 7 32bit
Lingua: C++Perché la funzione RegQueryValueEx() restituisce ERROR_FILE_NOT_FOUND durante il tentativo di leggere da una chiave del Registro di sistema?

ho cercato di accedere al registro HKEY_LOCAL_MACHINE\\HARDWARE\\DEVICEMAP\\Scsi\\Scsi Port 0, chiave Driver (tipo REG_SZ) - nessun problema.

Lo stesso per la lettura da HKEY_LOCAL_MACHINE\\HARDWARE\\DEVICEMAP\\SERIALCOMM, tutte le chiavi (tipo REG_SZ) hanno barre, ad esempio \Device\Serial0.

Durante la lettura di tali chiavi ritorna sempre 2 (senza tale file) con il seguente codice di esempio:

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

Qual è il modo corretto di leggere i valori chiave con tagli in nome?


Sopra è stato correttamente risposto da Cody Gray.
Sotto un altro numero.


Im ottenendo lo stesso problema quando Im usando variabile anziché una stringa di testo.
Iv considerato sia avvicina con barre singole e doppie:

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! 

ho provato tutte le varianti con "\ Device ..", "/ Dispositivo", "\ Device", ecc

+3

testo ("\\ dispositivo \\ Serial0")? –

+0

@Werner, no, la funzione 'RegQueryValueEx' * solo * richiede il valore di una chiave di registro. I valori sono le coppie nome/dati memorizzate all'interno delle chiavi. Quindi non puoi passare un percorso nidificato di chiavi come descrivi perché i valori non hanno percorsi. Certo, la terminologia è abbastanza confusa, Raymond Chen ha tentato di spiegarlo [qui] (http://blogs.msdn.com/b/oldnewthing/archive/2009/02/04/9394113.aspx). –

risposta

7

Hai per sfuggire ai tagli, proprio come hai fatto nella prima riga ...

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 

Se non, la funzione RegQueryValueEx non riesce a trovare la chiave specificata e restituisce ERROR_FILE_NOT_FOUND (== 2).


Ma c'è un altro problema. Si dovrebbe essere dichiara la matrice buffer come tipo wchar_t (o TCHAR), piuttosto che char:

TCHAR buf[255] = {0}; 

caso contrario, la funzione RegQueryValueEx sta per tentare di riempire la matrice con una stringa Unicode letto dalla chiave di registro specificata, e otterrai qualcosa di illeggibile.

+0

buf deve essere dichiarato come TCHAR, non come wchar_t. ReqQueryValueEx non si cura di come viene dichiarato buf, il valore restituito dipende dal fatto che RegQueryValueExA o RegQueryValueExW vengano chiamati. –

+0

@Werner: Sì, è tecnicamente vero.Ma le applicazioni Windows non sono state compilate come ANSI (non Unicode) per oltre 10 anni. A molte persone non interessa più usare i macro, ed è difficile dare la colpa a loro. –

+0

La tua risposta è piuttosto ottimizzata per rendere l'OP un momento difficile. Sintassi C++ 11, WMI è piuttosto ostile in C++, le porte seriali non sono dispositivi 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(); 
     } 

    } 
} 

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

+1

non stiamo usando .NET – killdaclick

Problemi correlati