Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Varios (https://www.clubdelphi.com/foros/forumdisplay.php?f=11)
-   -   ayudita registro de windows (https://www.clubdelphi.com/foros/showthread.php?t=82266)

martonbarbosa 15-02-2013 22:13:39

ayudita registro de windows
 
hola a todos!

ando necesitando una ayudita en delphi

basicamente, quiero poder realidar una busqueda especifica en el registro de windows!

yo actualmente entro a: HKLM_HARDWARE_DEVICEMAP_Scsi

y listo las demas cadenas (Scsi Port 0, 1,2, etc) en un listbox.

Bueno lo que quiero es, que una ves entre ahi, busque una cadena especifica y poder imprimirla en un edit...
especificamente, quiero poder buscar ahi, la cadena "Identifier" y el valor de esa cadena pasarla a un edit...

esa cadena "Identifier" se encuentra en ( en mi caso): HKLM\HARDWARE\DEVICEMAP\Scsi\Scsi Port 2\Scsi Bus 0\Target Id 0\Logical Unit Id 0\

si alguien tiene algna idea, agradesco su ayudita!

Salu2

4n71chr157

ecfisa 16-02-2013 02:23:24

Hola martonbarbosa.

No estoy seguro de haber entendido lo que buscas... Según creo interpretar, deseas obtener el valor de determinada clave.

Código Delphi [-]
function GetKeyValue(const aRootKey: HKEY; const aKey, aName: string): string;
var
  rd: TRegDataInfo;
  size: Cardinal;
  st: string;
begin
  with TRegistry.Create do
  try
    RootKey:= aRootKey;
    st := '';
    if OpenKey(aKey, False) then
    begin
      if GetDataInfo(aName, rd) then
        case rd.RegData of
          rdUnknown: Result := '';
          rdInteger: Result := IntToStr(ReadInteger(aName));
          rdString , rdExpandString: Result := ReadString(aName);
          rdBinary : begin
                       size:= GetDataSize(aName);
                       SetLength(st, size);
                       ReadBinaryData(aName, PChar(st)^, size);
                       Result:= st;
                     end;
        end;
      CloseKey;
    end
  finally
    Free;
  end;
end;

Ejemplo de llamada:
Código Delphi [-]
{ Mostrar la clave de producto de Windows en un Edit }
procedure TForm1.Button1Click(Sender: TObject);
begin
  Edit1.Text:= GetKeyValue(HKEY_LOCAL_MACHINE,
                          'SOFTWARE\Microsoft\Windows NT\CurrentVersion',
                          'ProductId');
end;
En el caso de un tipo rdBinary al convertirlo a string, con seguridad obtendrás caracteres ilegibles.
Saludos.

martonbarbosa 18-02-2013 22:33:12

interesante... lo voy a poner a prueba...
aunque no estoy seguro...

Porque segun veo, de esa manera puedo obtener el valor de una cadena especificada...

cuando tenga un tiempito, lo pruebo y veo de que manera lo puedo adaptar a mis necesidades...

A simple vista... y segun lo que yo necesito, voy a tener que meter un for ahi, para poder recorrer distintas claves...

Te subo una pic, asi ves lo que yo necesito hacer... creo que el ejemplo es funcional, siempre y cuando pueda recorrer todas las claves que yo necesito, y en ese recorrido busque una palabra especifica...



Bueno no me dejo subir la pic...
Yo necesito recorrer todo eso y de "Logical Unit Id 0" sacar un valor especifico...
no se si me entendes... es medio complicado explicar lo que necesito...

Desde ya muchisimas gracias por responder.
M@rton

martonbarbosa 18-02-2013 23:56:28

Hola Ecfisa, probe tu ejemplo.... va como piña mira...


Código Delphi [-]
function GetKeyValue(const aRootKey: HKEY; const aKey, aName: string): string;
var
  rd: TRegDataInfo;
  size: Cardinal;
  st: string;
begin
  with TRegistry.Create do
  try
    RootKey:= aRootKey;
    st := '';
    if OpenKey(aKey, False) then
    begin
      if GetDataInfo(aName, rd) then
        case rd.RegData of
          rdUnknown: Result := '';
          rdInteger: Result := IntToStr(ReadInteger(aName));
          rdString , rdExpandString: Result := ReadString(aName);
          rdBinary : begin
                       size:= GetDataSize(aName);
                       SetLength(st, size);
                       ReadBinaryData(aName, PChar(st)^, size);
                       Result:= st;
                     end;
        end;
      CloseKey;
    end
  finally
    Free;
  end;
end;

LLAMADA

Código Delphi [-]
procedure TForm1.Button2Click(Sender: TObject);
begin
 Edit1.Text:= GetKeyValue(HKEY_LOCAL_MACHINE,
                          'HARDWARE\DEVICEMAP\Scsi\Scsi Port 2\Scsi Bus 0\Target Id 1\Logical Unit Id 0\',
                          'Identifier');
end;

Ahora... mi duda, como puedo hacer que los numeros contenidos en esta linea: "'HARDWARE\DEVICEMAP\Scsi\Scsi Port 2\Scsi Bus 0\Target Id 1\Logical Unit Id 0\'" aumenten solos... digamos que recorra el registro 1 a 1 hasta encontrar el valor "Identifier"??? se entiende???

Ejemplo:
'HARDWARE\DEVICEMAP\Scsi\Scsi Port 0\Scsi Bus 0\Target Id 0\Logical Unit Id 0\'
'HARDWARE\DEVICEMAP\Scsi\Scsi Port 1\Scsi Bus 1\Target Id 1\Logical Unit Id 1\'
etc, hasta que encuentre el valor "identifier"

creo que ahora quedo mas claro!

Atte: M@rton

martonbarbosa 26-02-2013 01:20:32

alguien???

alguna ayudita?

a alguien se le ocurre como hacer eso?

ecfisa 26-02-2013 06:07:21

Cita:

Empezado por martonbarbosa (Mensaje 455192)
Ahora... mi duda, como puedo hacer que los numeros contenidos en esta linea: "'HARDWARE\DEVICEMAP\Scsi\Scsi Port 2\Scsi Bus 0\Target Id 1\Logical Unit Id 0\'" aumenten solos... digamos que recorra el registro 1 a 1 hasta encontrar el valor "Identifier"??? se entiende???

Ejemplo:
'HARDWARE\DEVICEMAP\Scsi\Scsi Port 0\Scsi Bus 0\Target Id 0\Logical Unit Id 0\'
'HARDWARE\DEVICEMAP\Scsi\Scsi Port 1\Scsi Bus 1\Target Id 1\Logical Unit Id 1\'
etc, hasta que encuentre el valor "identifier"

Hola.

Por lo que entiendo de tu mensaje, el valor a buscar se encuentra en los nodos hijos de la clave a buscar ('DEVICEMAP\Scsi\Scsi Port 0\Scsi Bus 0\Target Id 0'.

Entonces podrías hacer:
Código Delphi [-]
function SearchValueName(const RKEY: HKEY; const SUBKEY, Searched: string): string;
var
  rd     : TRegDataInfo;
  st     : string;
  i,sz   : Integer;
  KNames,
  VNames : TStrings;
begin
  KNames := TStringList.Create;
  VNames := TStringList.Create;
  with TRegistry.Create do
  try
    RootKey := RKEY;
    if OpenKeyReadOnly(SUBKEY) then
    begin
      GetKeyNames(KNames);
      for i:= 0 to KNames.Count - 1 do
      begin
        CloseKey;
        OpenKeyReadOnly(SUBKEY + '\' + KNames[i]);
        GetValueNames(VNames);
        if VNames.IndexOf(Searched) <> -1 then
        begin
          GetDataInfo(Searched, rd);
          case rd.RegData of
            rdUnknown: Result := '';
            rdInteger: Result := IntToStr(ReadInteger(Searched));
            rdString , rdExpandString: Result := ReadString(Searched);
            rdBinary : begin
                         sz := GetDataSize(Searched);
                         SetLength(st, sz);
                         ReadBinaryData(Searched, PChar(st)^, sz);
                         Result := st;
                       end
          end
        end
      end
    end
  finally
    KNames.Free;
    VNames.Free;
  end;
end;
La función busca el nombre buscado (Searched) en los nodos hijos del argumento enviado en el parámetro SUBKEY. Si lo encuentra lee el valor y lo devuelve como string, en caso contrario devuelve cadena vacía

Llamada ejemplo:
Código Delphi [-]
procedure TForm1.Button1Click(Sender: TObject);
begin
  ShowMessage(SearchValueName(HKEY_LOCAL_MACHINE,
                'SOFTWARE\Microsoft\Windows NT\CurrentVersion',
                'MicrosoftRedirectionURL'));
end;

En tu caso creo que sería:
Código Delphi [-]
  SearchValueName(HKEY_LOCAL_MACHINE,
                  'HARDWARE\DEVICEMAP\Scsi\Scsi Port 0\Scsi Bus 0\Target Id 0',
                  'Identifier');

Saludos.

nlsgarcia 26-02-2013 10:36:57

martonbarbosa,

Cita:

Empezado por martonbarbosa
...como puedo hacer que los numeros contenidos en esta linea...aumenten solos... hasta encontrar el valor "Identifier"...

Revisa este código basado en el código del Msg #2:
Código Delphi [-]
procedure TForm1.Button1Click(Sender: TObject);
var
   i, j, k, l : Integer;
   Reg : TRegistry;
   s : string;

begin

   try

      ListBox1.Clear;

      Reg := TRegistry.Create;

      Reg.RootKey := HKEY_LOCAL_MACHINE;

      if Reg.OpenKey('HARDWARE\DEVICEMAP\Scsi',False) then
      begin

         for i := 0 to 255 do
         begin
            Reg.CloseKey;
            if Reg.OpenKey('HARDWARE\DEVICEMAP\Scsi\Scsi Port ' + IntToStr(i),False)
            then
               for j := 0 to 255 do
               begin
                  Reg.CloseKey;
                  if Reg.OpenKey('HARDWARE\DEVICEMAP\Scsi\Scsi Port ' + IntToStr(i)
                                 + '\Scsi Bus ' + IntToStr(j),False)
                  then
                     for k := 0 to 255 do
                     begin
                        Reg.CloseKey;
                        if Reg.OpenKey('HARDWARE\DEVICEMAP\Scsi\Scsi Port ' + IntToStr(i)
                                       + '\Scsi Bus ' + IntToStr(j)
                                       + '\Target Id ' + IntToStr(k),False)
                        then
                           for l := 0 to 255 do
                           begin
                              Reg.CloseKey;
                              if Reg.OpenKey('HARDWARE\DEVICEMAP\Scsi\Scsi Port ' + IntToStr(i)
                                             + '\Scsi Bus ' + IntToStr(j)
                                             + '\Target Id ' + IntToStr(k)
                                             + '\Logical Unit Id ' + IntToStr(l), False)
                              then
                                 begin
                                    s := 'HARDWARE\DEVICEMAP\Scsi\Scsi Port ' + IntToStr(i)
                                         + '\Scsi Bus ' + IntToStr(j)
                                         + '\Target Id ' + IntToStr(k)
                                         + '\Logical Unit Id ' + IntToStr(l);

                                    s := s  + '\Identifier = '
                                         + GetKeyValue(HKEY_LOCAL_MACHINE, s, 'Identifier');

                                    ListBox1.Items.Add(s);
                                   
                                 end;
                           end;
                     end;
               end;
         end;
      end;

   finally
      Reg.Free;
   end;

end;
El código anterior leerá la clave HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\Scsi del Registro de Windows y obtendrá el valor Identifier de todas las subclaves predeterminadas que lo contienen almacenando el resultado en un control TListBox hasta 256 niveles por cada subclave leida.

El resultado del código anterior en una Máquina Virtual con Windows XP Professional x32 es el siguiente:



Espero sea útil :)

Nelson.

martonbarbosa 26-02-2013 16:09:31

Hola
Antes que nada, Gracias ecfisa y nlsgarcia!!!

Ni bien llegue a mi casa, pongo a prueba ambos ejemplos y les comento... a simple vista el codigo que ando buscando es el que propone nlsgarcia!

Pero bueno, lo pruebo y les comento!!!

Muchisimas gracias a los 2!

Salu2

M@rton

martonbarbosa 27-02-2013 21:51:45

Hola

nlsgarcia...

tu codigo me tiro un error en la siguiente linea ¬¬

"GetKeyValue(HKEY_LOCAL_MACHINE, s, 'Identifier');"

me dice: Undeclarated identifier = GetKeyValue...

raro che...

y con respeto a tu codigo ecfisa, anda... pero el tema es que yo tengo que escribir a mano la ruta entera...
lo que ando buscando es mas o menos lo que hizo nlsgarcia... o quiero recorrer todo y traer todos los identifier encontrados en HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\Scsi...

Desde ya muchisimas gracias.
M@rton

nlsgarcia 27-02-2013 22:37:44

martonbarbosa,

Cita:

Empezado por martonbarbosa
...tu codigo me tiro un error en la siguiente linea...

El código del Msg #7 está disponible en el siguiente link: http://terawiki.clubdelphi.com/Delph...Registry-1.rar

Este código fue probado en tres Máquinas Virtuales con Windows XP Professional x32, Windows 7 Professional x32 y x64 y una Máquina Física con Windows 7 Professional x32 y en todos los casos funcionó correctamente.

Espero sea útil :)

Nelson.

martonbarbosa 27-02-2013 22:42:27

nlsgarcia! disculpame...

es que me olvide de incluir la funcion GetKeyValue...

Código Delphi [-]
function GetKeyValue(const aRootKey: HKEY; const aKey, aName: string): string;
var
   rd: TRegDataInfo;
   size: Cardinal;
   st: string;

begin
   with TRegistry.Create do
   try

      RootKey:= aRootKey;

      st := '';

      if OpenKey(aKey, False) then
      begin
         if GetDataInfo(aName, rd) then
         case rd.RegData of
            rdUnknown : Result := '';
            rdInteger : Result := IntToStr(ReadInteger(aName));
            rdString , rdExpandString : Result := ReadString(aName);
            rdBinary : begin
                          size:= GetDataSize(aName);
                          SetLength(st, size);
                          ReadBinaryData(aName, PChar(st)^, size);
                          Result:= st;
                       end;
         end;
         CloseKey;
      end

   finally
      Free;
   end;
end;

ahora si anda... jajaja bueno muchisimas gracias!

ahora solo me queda adaptarlo a mis necesidades!

Desde ya muchisimas gracias.
los mantengo al tanto!

Salu2
M@rton

ecfisa 28-02-2013 04:42:37

Hola Marton.
Cita:

Empezado por martonbarbosa (Mensaje 455699)
y con respeto a tu codigo ecfisa, anda... pero el tema es que yo tengo que escribir a mano la ruta entera...

Si, eso es lo que había entendido que deseabas hacer... :o

Aunque nlsgarcia ya te dió una muy buena solución, otra opción para lograrlo es:
Código Delphi [-]
uses Registry;

procedure TForm1.FindValueName(aRootKey: HKEY; aKeyName, aValueName: string;
  StResult: TStrings);
var
  Registry: TRegistry;
  RegDataType: TRegDataType;
  SKeys: TStringList;
  SValues: TStringList;
  i, size: integer;
  st: string;
begin
  with TRegistry.Create do
  try
    RootKey := aRootKey;
    if OpenKeyReadOnly(aKeyName) then
    begin
      SValues := TStringList.Create;
      try
        GetValueNames(SValues);
        for i := 0 to SValues.count - 1 do
        begin
          RegDataType :=  GetDataType(SValues[i]);
          case RegDataType of
            rdUnknown : st := 'Desconocido';
            rdInteger : st := IntToStr(ReadInteger(SValues[i]));
            rdString , rdExpandString : st := ReadString(SValues[i]);
            rdBinary  : begin
                          size:= GetDataSize(SValues[i]);
                          SetLength(st, size);
                          ReadBinaryData(SValues[i], PChar(st)^, size);
                        end;
          end;
          if SValues[i] = aValueName  then
            StResult.Add(aKeyName + '\' + SValues[i] + ' = ' + st)
        end;
      finally
        SValues.Free
      end;
    end;
    SKeys := TStringList.Create;
    try
      GetKeyNames(SKeys);
      for i := 0 to SKeys.count - 1 do
        FindValueName(aRootKey, aKeyName + '\' + SKeys[i], aValueName, StResult);
    finally
      SKeys.Free;
    end;
  finally
    Free;
  end;
end;

Llamada ejemplo:
Código Delphi [-]
procedure TForm1.Button1Click(Sender: TObject);
begin
  FindValueName(HKEY_LOCAL_MACHINE,
               'HARDWARE\DESCRIPTION\System',
               'Identifier',
               ListBox1.Items);
end;
Al parámetro aKeyName podés especificarle cualquier ruta. Lógicamente cuando más próxima al valor la especifiques más rápidamente realizará la búsqueda, pero será menos amplia.

Con una pequeña modificación también podes buscar en el registro completo:
Código Delphi [-]
procedure TForm1.Button1Click(Sender: TObject);
const
  HKEYCONST : array[0..6] of HKEY = (HKEY_CLASSES_ROOT, HKEY_CURRENT_USER,
    HKEY_LOCAL_MACHINE, HKEY_USERS, HKEY_PERFORMANCE_DATA,HKEY_CURRENT_CONFIG,
    HKEY_DYN_DATA);
var
  i: Integer;
begin
  for i:= Low(HKEYCONST) to High(HKEYCONST) do
    FindValueName(HKEYCONST[i],
                  '',
                  'Profile',
                  ListBox1.Items);
end;
Pero debes armarte de paciencia... :)

Saludos.

nlsgarcia 28-02-2013 06:44:10

ecfisa,

Excelente código ^\||/ :)

Quizás esta variante mejore un poco el tiempo:
Código Delphi [-]
for i := 0 to SValues.count - 1 do
   if SValues[i] = aValueName  then
   begin
      RegDataType :=  GetDataType(SValues[i]);
      case RegDataType of
         rdUnknown : st := 'Desconocido';
         rdInteger : st := IntToStr(ReadInteger(SValues[i]));
         rdString , rdExpandString : st := ReadString(SValues[i]);
         rdBinary  : begin
                        size:= GetDataSize(SValues[i]);
                        SetLength(st, size);
                        ReadBinaryData(SValues[i], PChar(st)^, size);
                     end;
      end;
      StResult.Add(aKeyName + '\' + SValues[i] + ' = ' + st)
   end;
Sin embargo me queda la duda de como un programa como O&O RegEditor hace las búsquedas de forma tan rápida en el Registro de Windows.

Espero sea útil :)

Nelson.

ecfisa 28-02-2013 07:20:36

Cita:

Empezado por nlsgarcia (Mensaje 455715)
Sin embargo me queda la duda de como un programa como O&O RegEditor hace las búsquedas de forma tan rápida en el Registro de Windows.

Somos dos :confused:

Saludos. :)

Casimiro Noteví 28-02-2013 11:46:36

No conozco ese programa, pero lo mismo lee todo el registro y lo almacena en una tabla de sqlite, por ejemplo, luego trabaja con esa tabla, por lo que la búsqueda (campos indexados) es instantánea.
Por decir algo :)

martonbarbosa 28-02-2013 13:32:01

gracias loco! ni bien llegue a casa pruebo los nuevos codigos...

ayer estuve viendo y adaptando el codigo de nlsgarcia a mis necesidades... y va como piña...


Salu2

M@rton

ecfisa 28-02-2013 17:20:17

Cita:

Empezado por Casimiro Notevi (Mensaje 455727)
No conozco ese programa, pero lo mismo lee todo el registro y lo almacena en una tabla de sqlite, por ejemplo, luego trabaja con esa tabla, por lo que la búsqueda (campos indexados) es instantánea.
Por decir algo :)

Es muy probable que así sea ;).

Supongo que tendrá monitoreados los posibles cambios del registro para reducir la carga de la aplicación. El regedit tarda un tiempo parecido al código recursivo del mensaje #12 en realizar las búsquedas.

Como dato adicional, es muy sencillo implementarle una búsqueda de contenido parcial, sólo hay que modificar el condicional:
Código Delphi [-]
   ...
   if Copy(SValues[i], 1, Length(aValueName)) = aValueName  then
   begin
     ...

Saludos.

Edito: Casi me olvido... Nelson: Sin ninguna duda el código es más óptimo con la modificación que sugeriste. Pero lamentablemente la ganancia de tiempo es casi imperceptible. (Tal vez la mejora venga implementando algo como lo que comenta Casimiro)


La franja horaria es GMT +2. Ahora son las 13:27:59.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2026, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi