问题
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:
- UltraVNC installs itself in the 64-bit view of the registry on 64-bit Windows, so we need to query both views, and
- 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