0

我有用于更新客户站点计算机的 Inno Setup 安装程序。一般有两台电脑,但有时三台或更多。所有都是联网的,而且恰好一个是无头的。

在所有有头(如果这与无头?)工作站上运行安装程序相对容易,因此可以运行与这些计算机相关的所有任务。还有一些任务需要在无头工作站上执行。通常,这些是可以多次运行的快速、简单的任务(复制小文件和重新启动服务)。

但是,有时我会遇到最好只执行一次的耗时任务,例如需要重新启动的任务。在这种特殊情况下,我需要确定是否安装了损坏的 UltraVNC 版本,而我所知道的最好方法是查询无头工作站上的注册表。不幸的是,RegQueryStringValue不提供查询远程机器上的注册表的选项。

如何做到这一点?

4

2 回答 2

1

这个问题因两件事而变得复杂:

  1. UltraVNC 将自身安装在 64 位 Windows 上注册表的 64 位视图中,因此我们需要查询这两个视图,并且
  2. RemoteRegistry 在 Windows Vista 及更高版本上默认不运行。

这就是我想出的:

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

然后,调用函数相对简单。为简洁起见,大多数错误处理已被省略。此外,不会尝试读取非 REG_SZ 值。

<target>是目标,按名称或按 IP 地址。<key>并且<value>是要查询的远程键和值。

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;

有关更多详细信息,请参阅Microsoft 关于这些功能的文档。

于 2011-10-20T12:50:01.123 回答
0

可能最简单的方法是编写一个小程序,它直接使用注册表 API 来查询远程服务器并将退出代码与结果一起返回给 Inno。
另一种选择是使用 psexec 或类似工具来运行在远程服务器本身上执行工作的应用程序。

于 2011-10-20T10:12:40.650 回答