如果重新启动/重新启动已经挂起/需要,是否可以防止安装?
我们的安装程序安装了SQL Server Express,如果系统中有挂起的重新启动,有时它会拒绝这样做。 Inno Setup可以检测到这种情况,以便在安装我们的软件之前告诉用户重新启动吗?
我了解MakePendingFileRenameOperationsChecksum
,但通常会提到在安装过程中检测是否需要重新启动。可以在使用之前吗?
答案 0 :(得分:0)
如果要检测是否存在需要重新启动的挂起重命名,请查询PendingFileRenameOperations
注册表值。
另请参阅How to find out if an MSI I just installed requested a Windows reboot?
function IsRestartPending: Boolean;
var
S: string;
begin
if RegQueryMultiStringValue(
HKLM, 'SYSTEM\CurrentControlSet\Control\Session Manager',
'PendingFileRenameOperations', S) then
begin
Log(Format('PendingFileRenameOperations value exists with value [%s]', [S]));
Result := (Trim(S) <> ''); { This additional check is probably not needed }
end
else
begin
Log('PendingFileRenameOperations value does not exist');
Result := False;
end;
end;
function InitializeSetup(): Boolean;
begin
if IsRestartPending then
begin
MsgBox('Restart your machine please', mbError, MB_OK);
Result := False;
Exit;
end;
Result := True;
end;
答案 1 :(得分:0)
另一个被接受的答案仅涉及一种情况。但是,实际上有许多不同的情况需要检查。我发现this article描述了所有要检查的注册表项,并围绕它编写了一个函数。这实际上是在Delphi中,但是也应该在Inno Setup中轻松实现。实际上,其中一部分I got from here(位于Inno设置中)用于检查有效的GUID。
请注意,这通常会检查是否有未决的Windows更新,这不一定是需要的。您可以对其进行修改,并删除您不想为自己的目的执行的检查。对于SQL Server,PendingFileRenameOperations
的第二和第三次检查实际上似乎不是必需的。
const
S_OK = $00000000;
CO_E_CLASSSTRING = $800401F3;
type
LPCLSID = TGUID;
LPCOLESTR = WideString;
function CLSIDFromString(lpsz: LPCOLESTR; pclsid: LPCLSID): HRESULT;
stdcall; external 'ole32.dll';
function IsValidGuid(const Value: string): Boolean;
var
GUID: LPCLSID;
RetVal: HRESULT;
begin
RetVal := CLSIDFromString(LPCOLESTR(Value), GUID);
Result := RetVal = S_OK;
if not Result and (RetVal <> CO_E_CLASSSTRING) then
OleCheck(RetVal);
end;
function IsRestartPending(const RestartOnly: Boolean = True): Boolean;
var
R: TRegistry;
L: TStringList;
X: Integer;
T: String;
begin
R:= TRegistry.Create(KEY_READ);
try
L:= TStringList.Create;
try
Result:= False;
R.RootKey:= HKEY_LOCAL_MACHINE;
if R.OpenKey('SOFTWARE\Microsoft\Updates', False) then begin
try
if R.ValueExists('UpdateExeVolatile') then begin
if R.ReadInteger('UpdateExeVolatile') <> 0 then
Result:= True;
end;
finally
R.CloseKey;
end;
end;
if not RestartOnly then begin
//These next 2 checks are not necessary for a SQL Server installation.
if not Result then begin
if R.OpenKey('SYSTEM\CurrentControlSet\Control\Session Manager', False) then begin
try
Result:= R.ValueExists('PendingFileRenameOperations');
finally
R.CloseKey;
end;
end;
end;
if not Result then begin
if R.OpenKey('SYSTEM\CurrentControlSet\Control\Session Manager', False) then begin
try
Result:= R.ValueExists('PendingFileRenameOperations2');
finally
R.CloseKey;
end;
end;
end;
end;
if not Result then begin
Result:= R.KeyExists('SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired');
end;
if not Result then begin
if R.OpenKey('SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Services\Pending', False) then begin
try
L.Clear;
R.GetKeyNames(L);
for X := 0 to L.Count-1 do begin
if IsValidGuid(L[X]) then begin
Result:= True;
Break;
end;
end;
finally
R.CloseKey;
end;
end;
end;
if not Result then begin
Result:= R.KeyExists('SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\PostRebootReporting');
end;
if not Result then begin
if R.OpenKey('SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce', False) then begin
try
Result:= R.ValueExists('DVDRebootSignal');
finally
R.CloseKey;
end;
end;
end;
if not Result then begin
Result:= R.KeyExists('Software\Microsoft\Windows\CurrentVersion\Component Based Servicing\RebootPending');
end;
if not Result then begin
Result:= R.KeyExists('Software\Microsoft\Windows\CurrentVersion\Component Based Servicing\RebootInProgress');
end;
if not Result then begin
Result:= R.KeyExists('Software\Microsoft\Windows\CurrentVersion\Component Based Servicing\PackagesPending');
end;
if not Result then begin
Result:= R.KeyExists('SOFTWARE\Microsoft\ServerManager\CurrentRebootAttempts');
end;
if not Result then begin
if R.OpenKey('SYSTEM\CurrentControlSet\Services\Netlogon', False) then begin
try
Result:= R.ValueExists('JoinDomain');
finally
R.CloseKey;
end;
end;
end;
if not Result then begin
if R.OpenKey('SYSTEM\CurrentControlSet\Services\Netlogon', False) then begin
try
Result:= R.ValueExists('AvoidSpnSet');
finally
R.CloseKey;
end;
end;
end;
if not Result then begin
if R.OpenKey('SYSTEM\CurrentControlSet\Control\ComputerName\ActiveComputerName', False) then begin
try
T:= R.ReadString('ComputerName');
finally
R.CloseKey;
end;
end;
if R.OpenKey('SYSTEM\CurrentControlSet\Control\ComputerName\ComputerName', False) then begin
try
if R.ReadString('ComputerName') <> T then
Result:= True;
finally
R.CloseKey;
end;
end;
end;
finally
L.Free;
end;
finally
R.Free;
end;
end;