2011-12-21 12 views
6

Sistema Operativo: Windows 7 de 32 bits
Idioma: C++¿Por qué la función RegQueryValueEx() devuelve ERROR_FILE_NOT_FOUND mientras intenta leer desde una clave de registro?

he tratado de acceder a Registro HKEY_LOCAL_MACHINE\\HARDWARE\\DEVICEMAP\\Scsi\\Scsi Port 0, Driver clave (tipo REG_SZ) - no hay problema.

Lo mismo para leer desde HKEY_LOCAL_MACHINE\\HARDWARE\\DEVICEMAP\\SERIALCOMM, todas las teclas (tipos REG_SZ) tienen barras inclinadas, por ejemplo \Device\Serial0.

Durante la lectura de dichas claves siempre devuelve 2 (No existe el fichero) con el siguiente código de ejemplo:

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

¿Cuál es la forma correcta de leer valores clave con barras en llamas?


Above ha sido respondida correctamente por Cody Gray.
Debajo de otro problema.


Im que consigue el mismo problema cuando estoy usando variable en lugar de una cadena de texto.
Iv considera tanto se acerca con barras individuales y dobles:

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! 

He intentado todas las variantes con "\ Device ..", "/ dispositivo", "\ Device", etc.

+3

TEXTO ("\\ \\ Dispositivo Serial0")? –

+0

@Werner, no, la función 'RegQueryValueEx' solo * consulta el valor de una clave de registro. Los valores son los pares nombre/datos almacenados dentro de las claves. Por lo tanto, no puede pasarle una ruta anidada de claves como describe porque los valores no tienen rutas. Es cierto que la terminología es bastante confusa, Raymond Chen intentó explicarlo [aquí] (http://blogs.msdn.com/b/oldnewthing/archive/2009/02/04/9394113.aspx). –

Respuesta

7

Tienes para escapar de las barras, al igual que lo hizo en la primera línea ...

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 

Si no, la función RegQueryValueEx no puede encontrar la clave especificada y devuelve ERROR_FILE_NOT_FOUND (== 2).


Pero hay otro problema. Usted debe estar declarando la matriz del separador tipo wchar_t (o TCHAR), en lugar de char:

TCHAR buf[255] = {0}; 

De lo contrario, la función RegQueryValueEx va a intentar llenar la matriz con una cadena Unicode leer la clave de registro especificada, y obtendrás algo ilegible.

+0

buf debe declararse como TCHAR, no como wchar_t. ReqQueryValueEx no se preocupa de cómo se declara buf, el valor devuelto depende de si se llama a RegQueryValueExA o RegQueryValueExW. –

+0

@Werner: Sí, eso es técnicamente cierto.Pero las aplicaciones de Windows no se han compilado como ANSI (no Unicode) durante más de 10 años. Mucha gente ya no quiere usar las macros, y es difícil culparlas. –

+0

Su respuesta está optimizada para que el OP tenga dificultades. Sintaxis C++ 11, WMI es bastante antipático en C++, los puertos serie no son dispositivos 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(); 
     } 

    } 
} 

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

+1

no estamos usando .NET – killdaclick

Cuestiones relacionadas