Ir para conteúdo
Fórum Script Brasil
  • 0

Regedit


Paulo Nobre

Pergunta

Abrir o regedit não é o problema.

ShellExecute (0,'open',C:\Windows\System32\Regedt32.exe,nil,nil,SW_SHOWNORMAL);
Abrir numa determinada chave também não é o problema.
reg.RootKey:= HKEY_CURRENT_USER;
reg.OpenKey('\Software\Microsoft\Windows\CurrentVersion\Applets\Regedit',False);
reg.WriteString('LastKey','Coloque aqui o caminho que deseja mostrar quando abrir o regedit');
Coloque o código acima e em seguida o shellexecute que o regedit abrirá no caminho especificado. E a dúvida? A dúvida é o seguinte: Quero abrir o regedit numa chave com foco numa string de uma chave. Suponha a chave HKEY_LOCAL_MACHINE\SOFTWARE\Borland\BLW32 Nesta chave existe a string 'BLAPIPATH'. Quero abrir o regedit nesta chave(isto consigo com o descrito acima), só que com foco na string 'BLAPIPATH'.Isto não consigo Colocando
HKEY_LOCAL_MACHINE\SOFTWARE\Borland\BLW32\BLAPIPATH.

Nada acontece.

Alguém tem alguma idéia?

Link para o comentário
Compartilhar em outros sites

22 respostass a esta questão

Posts Recomendados

  • 0

Olá Paulo, dando uma olhada nesse exemplo:

1-Acha a janela do Regedit pelo FindWindow.

2-Acha a janela esquerda do Treeview pelo FindWindowEx.

3-Simula o pressionamento da seta esquerda(<-) 30 vezes pelo SendMessage para ir no início.

4-Vai até a chave desejada pelo SendMessage com WM_Char ou VK_Right.

5-Acha e foca a janela do Listview da direita.

6-Foca o valor desejado pelo SendMessage com WM_Char.

Ou seja, não precisa atualizar o valor de LastKey porque no primeiro passo ele fecha todas a chaves indo para My Computer.

Link para o comentário
Compartilhar em outros sites

  • 0

Olá, s3c, obrigado pela tradução.

Parece que é bem trabalhoso, né?

A idéia parece que é bem inteligente!!

Não é a toa que poucos programas usam isto.

Se um dia você tiver tempo e quiser, e puder escreve o código prá mim.

Link para o comentário
Compartilhar em outros sites

  • 0

Qualquer exemplo serviria.

Fazendo com um acho que serviria para qualquer outro, não?

Por exemplo:

HKEY_LOCAL_MACHINE\SOFTWARE\Borland\BLW32\BLAPIPATH

A minha idéia para implementar o código seria o usuário clicar num caminho num listbox, que contém caminhos do regedit e ao clicar num botão ele abrir o regedit na chave e numa string ou outro tipo de valor qualquer.

O código acima seria um exemplo.

Mas tendo o código para abrir com foco na string, a parte do listbox acho que seria fácil.

Link para o comentário
Compartilhar em outros sites

  • 0

Após abrir o Regedit:

var h1,h2:THandle; sKey,sValue:String; i:Integer;
begin
  sKey   := '\HKEY_LOCAL_MACHINE\SOFTWARE\Borland\BLW32';
  sValue := 'BLAPIPATH';
  h1 := FindWindow('RegEdit_RegEdit', nil);
  h2 := FindWindowEx(h1, 0, 'SysTreeView32', nil);
  SetForegroundWindow(H2);
  Windows.SetFocus(H2);
  for i := 1 to 30 do
    SendMessage(H2, WM_KeyDown, VK_Left, 0);
  for i := 1 to Length(sKey) do
    if sKey[i] = '\' then
      SendMessage(H2, WM_KeyDown, VK_Right, 0)
    else
      SendMessage(H2, WM_Char, Ord(sKey[i]), 0);
  Sleep(100);
  h2 := FindWindowEx(h1, 0, 'SysListView32', nil);
  SetForegroundWindow(h2);
  Windows.SetFocus(h2);
  SendMessage(h2, WM_KeyDown, VK_Home, 0);
  for i := 1 to Length(sValue) do
    SendMessage(h2, WM_Char, Ord(sValue[i]), 0);
end;

Link para o comentário
Compartilhar em outros sites

  • 0

Coloquei a procedure que você criou no evento OnClick de um botão.

Se abro o regedit manualmente e depois clico no botão o código é executado corretamente.

Se abro o regedit via código não funciona.

Tentei:

1)Colocar logo depois do begin no seu código

ShellExecute (0,'open',C:\Windows\System32\Regedt32.exe,nil,nil,SW_SHOWNORMAL);
Não funcionou. 2) Limpar a chave antes de chamar o regedit:(logo depois do begin do seu código)
reg.RootKey:= HKEY_CURRENT_USER;
reg.OpenKey('\Software\Microsoft\Windows\CurrentVersion\Applets\Regedit',False);
reg.WriteString('LastKey','Meu Computador');
ShellExecute (0,'open',C:\Windows\System32\Regedt32.exe,nil,nil,SW_SHOWNORMAL);

Não funcionou.

O que pode estar havendo?

Link para o comentário
Compartilhar em outros sites

  • 0

Não entendi o post sugerido pelo GrayMalkin, mas me lembrei ter lido que era necessário um tempo

para atualizar o listView e lá tinha

// have to wait for Regedit to update the listview
Sleep(1000); 
Aí na pura intuição coloquei sleep(1000) entre
ShellExecute (0,'open',C:\Windows\System32\Regedt32.exe,nil,nil,SW_SHOWNORMAL);

e o seu código e funcionou.

Não sei se esta é a melhor maneira mas, funcionou.

Inclusive o efeito é interessante pois você vê o programa ir abrindo as chaves até chegar a chave requerida.

É isso mesmo ou tem algo mais inteligente??

Link para o comentário
Compartilhar em outros sites

  • 0

Ah sim, é porque após o ShellExecute é dado o FindWindow e como ShellExecute retorna imediatamente, FindWindow falha porque a janela ainda não está criada. O Sleep(1000) é muito tempo, veja se funciona assim:

var h1,h2:THandle; sKey,sValue:String; i:Integer;
begin
  sKey   := '\HKEY_LOCAL_MACHINE\SOFTWARE\Borland\BLW32';
  sValue := 'BLAPIPATH';
  WinExec('Regedt32.exe', SW_Hide);
  h1 := 0;
  While h1 = 0 do
    h1 := FindWindow('RegEdit_RegEdit', nil);
  h2 := 0;
  While h2 = 0 do
    h2 := FindWindowEx(h1, 0, 'SysTreeView32', nil);
  for i := 1 to 30 do
    SendMessage(H2, WM_KeyDown, VK_Left, 0);
  for i := 1 to Length(sKey) do
    if sKey[i] = '\' then
      SendMessage(H2, WM_KeyDown, VK_Right, 0)
    else
      SendMessage(H2, WM_Char, Ord(sKey[i]), 0);
  h2 := 0;
  While h2 = 0 do
    h2 := FindWindowEx(h1, 0, 'SysListView32', nil);
  ShowWindow(h1, SW_Show);
  SetForegroundWindow(h2);
  Sleep(100);
  SendMessage(h2, WM_KeyDown, VK_Home, 0);
  for i := 1 to Length(sValue) do
    SendMessage(h2, WM_Char, Ord(sValue[i]), 0);
end;

Link para o comentário
Compartilhar em outros sites

  • 0

s3c, obrigado, funcionou perfeitamente.

Você poderia, quando tiver tempo, dar uma explicada no código, seguindo sua sequência.

Não entendo bem, principalmente:

Os FindWindow e os SendMessage.

Não o que as funções fazem, mas sim porque aqueles parâmetros; SysTreeView32, SysListView32, WM_KeyDown, VK_Left, Ord(sKey)...

Link para o comentário
Compartilhar em outros sites

  • 0

Bom, FindWindow está procurando pela classe 'RegEdit_RegEdit' que é a janela principal do Regedit.

FindWindowEx procura pelas classes filhas 'SysTreeView32' e 'SysListView32' que são as janelas esquerda e direita.

Todas elas possuem um Handle e é por isso que aplica-se os SendMessage(s).

O SendMessage WM_KeyDown recebe em WParam o código da VK(Virtual Key) do teclado; ou seja; a janela recebe a informação que foi enviada aquela tecla, VK_Left(<-) volta um nível, VK_Right(->) avança um nível.

O SendMessage WM_Char recebe em WParam o código ascii do caracter; por isso o Ord e a janela recebe aquele caracter e como está em foco ela vai selecionando os valores que casam com o que é enviado.

Link para o comentário
Compartilhar em outros sites

  • 0

Pessoal, estava acompanhando o assunto e tenho uma pergunta. Paulo, haverá a possibilidade de a chave a ser presquisada não existir? Ou você sempre verificará que ela existe antes de abrir o RegEdit?

Pergunto isto porque, por exemplo, se você procurar pela chave: \HKEY_CURRENT_USER\Software\Freeware\Teste 5 e existir apenas: \HKEY_CURRENT_USER\Software\Freeware\Teste 2, ou mesmo não existir, o editor ficará posicionado na chave errada.

Passei umas horas pesquisando como ler o texto do nó selecionado, de modo a testar para ver se é o esperado. Isto, porque tem uma função da API (TreeViewGetItem) e uma mensagem também (TVM_GETITEM) que deveria funcionar, mas não funcionava. Encontrei o seguinte comentário em Experts-Exchange(link):

The common control messages cannot be used across process boundaries. You will need to use an injected DLL and communicate with the DLL as to what the common controls contain.

O que parece justificar o motivo de a aplicação teste não "acessar" dados do RegEdit. E acho que é isto mesmo porque achei no Delphi-PRAXiS uma função(link) que coloca todo um treview de outra aplicação em memos. Ela faz uso de VirtualAllocEx, já citado pelo s3c (link) no começo deste mês.

Então, dei uma enxugada para o propósito em questão e ficou assim:

function GetTreeViewText(hTVwnd: HWND; hItem :HTREEITEM): string;
const
  MAX_TEXT = 256;
var
  lpBuf: array[0..MAX_TEXT - 1] of char;
  tvi: TTVITEM;
  dwPId: DWORD;
  hProc: THANDLE;
  pText, pAddr: pointer;
  dwTmp: DWORD;
begin
  Result := '';
// Obtém ID da Thread e Processo
  if BOOL(GetWindowThreadProcessId(hTVwnd, @dwPId)) then
// Obtém o handle do processo que queremos acessar
    hProc := OpenProcess(PROCESS_VM_OPERATION or PROCESS_VM_READ or PROCESS_VM_WRITE, FALSE, dwPId);
  if hProc <> 0 then
  begin
// Aloca memoria para o texto a ser passado para o processo alvo
    pText := VirtualAllocEx(hProc, nil, MAX_TEXT, MEM_RESERVE or MEM_COMMIT, PAGE_READWRITE);
// Aloca memória para a estrutura TTVITEM a ser passada para o processo alvo
    pAddr := VirtualAllocEx(hProc, nil, sizeof(tvi), MEM_RESERVE or MEM_COMMIT, PAGE_READWRITE);

    tvi.mask := TVIF_TEXT;  // indica que desejamos obter o Texto 
    tvi.pszText := pText;      // Endereço da memória alocada para receber o resultado
    tvi.cchTextMax := MAX_TEXT - 1; // Nº máximo de caracteres a retornar
// Posiciona no item do treeview informado
    tvi.hItem := hItem;
// Escreve nossa estrutura para o processo
    if WriteProcessMemory(hProc, pAddr, @tvi, sizeof(tvi), dwTmp) and
// Executa a solicitação definida pela mensagem TVM_GETITEM juntamente com mask em tvi
      (SendMessage(hTVwnd, TVM_GETITEM, 0, Integer(pAddr)) <> 0) and
// Lê o resultado para lpBuf, respeitando MAX_TEXT
      ReadProcessMemory(hProc, pText, @lpBuf, MAX_TEXT, dwTmp) then
      Result := StrPas(lpBuf);  // Converte para String o retorno
  end;

  if Assigned(pAddr) then
    VirtualFreeEx(hProc, pAddr, 0, MEM_RELEASE);
  if Assigned(pText) then
    VirtualFreeEx(hProc, pText, 0, MEM_RELEASE);
  CloseHandle(hProc);
end;
No código que o Paulo, colocou fiz as seguintes inclusões:
var ...
  SelName,
  LastName :string;
begin
  ...
  for i := 1 to Length(sKey) do
    if sKey[i] = '\' then
    begin
      LastName := '';
      SendMessage(H2, WM_KeyDown, VK_Right, 0);
    end else
    begin
      LastName := LastName +sKey[i];
      SendMessage(H2, WM_Char, Ord(sKey[i]), 0);
    end;
  Sleep(100);

  SelName := GetTreeViewText(H2, TreeView_GetSelection(H2));

  if AnsiCompareStr(SelName, LastName) <> 0 then
    ShowMessage('Chave não encontrada');

  h2 := FindWindowEx(h1, 0, 'SysListView32', nil);
...

Legal essa idéia Paulo. Valeu.

Link para o comentário
Compartilhar em outros sites

  • 0

Paulo, haverá a possibilidade de a chave a ser presquisada não existir? Ou você sempre verificará que ela existe antes de abrir o RegEdit?

Micheus, realmente, quando postei o objetivo era acessar a chave a partir de uma string

já conhecida como existente. Pois ela estaria disponivel num listbox proveniente do registro.

Porém, depois cheguei a conclusão que poderia usar para uma pesquisa, tipo digitar o caminho num edit e mandar abrir. Existem chaves que todos sabem de cabeça, como exemplo a do RUN.

É claro que neste caso qualquer um de nós poderia digitar algo semelhante ao verdadeiro ou digitar errado.

Neste caso não saberia como fazer, até ler o seu post que tira esta dúvida.

Bem interessante este código, Micheus.

Essa idéia surgiu observando o programa RegAlyzer, do mesmo autor do programa Spybot (esse todos devem conhecer). O link é o seguinte:

http://www.spybot.info/pt/regalyzer/index.html

Neste programa, muito interessante para quem precisa acessar determinadas chaves do registro com rapidez o autor não fornece esta possibilidade(pelo menos que eu tenha percebido), a de abrir com foco numa string.

Já no também famoso RegMon 7.03 isso já é possível.

http://superdownloads.uol.com.br/download/10/regmon-(nt-xp)/

Aí fiquei pensando se um faz e o outro não é porque não deve ser tão simples, mas é possível, aí postei a pergunta!!

Legal essa idéia Paulo. Valeu.

Eu é que agradeço a todos vocês por essa oportunidade de aprender um pouco mais.

Link para o comentário
Compartilhar em outros sites

  • 0

Paulo, apenas para complementar, o ideal é que a cada fração da chave posicionada, ou seja, cada vez que encontrado um "\" a parte da chave anterior a ele deveria ser checada. Não apenas como eu coloquei, quando verifico apenas a última palavra. É que eu não queria mexer muito no que você postou, apenas dar uma idéia.

[]s

Link para o comentário
Compartilhar em outros sites

  • 0

Deve estar faltando CommCtrl no uses.

Realmente s3c,com esta unit os erros pararam de ocorrer, se bem que acho que não estou sabendo onde colocar o código do Micheus.

Mas não seria mais simples testar se chave e valor existem pelo TRegistry ?

Mas, como seria isso em cima do seu código, s3c?

Link para o comentário
Compartilhar em outros sites

  • 0
var Reg:TRegistry;
begin
  Reg         := TRegistry.Create;
  Reg.RootKey := Hkey_Local_Machine;
  if not Reg.OpenKey('\SOFTWARE\Borland\BLW32', false) or
     not Reg.ValueExists('BLAPIPATH')                  then
  begin
    Reg.Free;
    ShowMessage('Chave ou Valor Inexistente !');
    Exit;
  end;
  Reg.Free;
  . . .

Link para o comentário
Compartilhar em outros sites

Participe da discussão

Você pode postar agora e se registrar depois. Se você já tem uma conta, acesse agora para postar com sua conta.

Visitante
Responder esta pergunta...

×   Você colou conteúdo com formatação.   Remover formatação

  Apenas 75 emoticons são permitidos.

×   Seu link foi incorporado automaticamente.   Exibir como um link em vez disso

×   Seu conteúdo anterior foi restaurado.   Limpar Editor

×   Você não pode colar imagens diretamente. Carregar ou inserir imagens do URL.



  • Estatísticas dos Fóruns

    • Tópicos
      152,2k
    • Posts
      652k
×
×
  • Criar Novo...