How to access registry of a remote machine in Inno Setup

*爱你&永不变心* 提交于 2020-01-03 04:55:07

问题


I have Inno Setup installers that I use to update computers at customer sites. Generally there are two computers, but sometimes three or more. All are networked, and exactly one is headless.

It is relatively easy to run the installer on all the headed (if that's the opposite of headless?) workstations, thus running all tasks associated with those computers. There are also tasks that need to be performed on the headless workstation. Generally, these are quick, simple tasks (copying small files and restarting services) that can be run multiple times.

Occasionally, however, I encounter time consuming tasks that are best performed exactly once, such as tasks that require reboots. In this particular case, I need to determine if I have a broken version of UltraVNC installed, and the best way I know of is to query the registry on the headless workstation. Unfortunately, RegQueryStringValue does not supply options for querying registries on remote machines.

How does one go about doing this?


回答1:


This issue is complicated by two things:

  1. UltraVNC installs itself in the 64-bit view of the registry on 64-bit Windows, so we need to query both views, and
  2. RemoteRegistry isn't running by default on Windows Vista and later.

This is what I came up with:

function RegConnectRegistry(machineName: String; hKeyRoot:Integer; var phKey: Integer): integer;
  external 'RegConnectRegistryA@Advapi32.dll';
function RegOpenKeyEx(hKeyRoot:Integer; subkey:string; reserved, access:integer; var phKey: Integer): integer;
  external 'RegOpenKeyExA@Advapi32.dll';
function RegQueryValueEx(hKey:Integer; value: String; reserved: integer; var pType: integer; data: string; var pDataLen:integer): integer;
  external 'RegQueryValueExA@Advapi32.dll';
function RegCloseKey(hKey:Integer): integer;
  external 'RegCloseKey@Advapi32.dll';

Then, calling the functions is relatively straightforward. Most error handling has been omitted for conciseness. Also, no attempt is made to read non-REG_SZ values.

<target> is the target, either by name or by IP address. <key> and <value> are the remote key and value to query.

procedure CheckRemoteVNC();
var
  HKRM, key: Integer;
  data: string;
  dwType, dataLen, retVal: Integer;
begin
  data := '12345678901234567890'; { Padding. Digits so I can easily count how long it is. }
  dataLen := 20
  { Make sure the Remote Registry service is running }
  Exec('sc', ExpandConstant('\\<target> start RemoteRegistry'), '', SW_HIDE, ewWaitUntilTerminated, retVal)
  RegConnectRegistry('<target>', HKEY_LOCAL_MACHINE, HKRM)
  if RegOpenKeyEx(HKRM, '<key>', 0, 1 {KEY_QUERY_VALUE}, key) = 2 {Bad registry entry} then
    { Try the 64-bit view. }
    retVal := RegOpenKeyEx(HKRM, '<key>', 0, 257 {0x101 == KEY_WOW64_64KEY | KEY_QUERY_VALUE}, key)
  RegQueryValueEx(Key, '<value>', 0, dwType, data, dataLen)
  data := Copy(data, 0, dataLen-1)

  { Deal with the data appropriately. }

  if key <> 0 then RegCloseKey(key)
  if HKRM <> 0 then RegCloseKey(HKRM)
end;

See Microsoft's documentation on these functions for more details.




回答2:


Probably the easiest way is to write a small applet that uses the registry API directly to query the remote server and return an exit code to Inno with the result.
Another option is to use psexec or similar to run an app that does the work on the remote server itself.



来源:https://stackoverflow.com/questions/7830652/how-to-access-registry-of-a-remote-machine-in-inno-setup

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!