在安装之前检测重启是否挂起

时间:2019-10-17 19:41:49

标签: inno-setup

如果重新启动/重新启动已经挂起/需要,是否可以防止安装?

我们的安装程序安装了SQL Server Express,如果系统中有挂起的重新启动,有时它会拒绝这样做。 Inno Setup可以检测到这种情况,以便在安装我们的软件之前告诉用户重新启动吗?

我了解MakePendingFileRenameOperationsChecksum,但通常会提到在安装过程中检测是否需要重新启动。可以在使用之前吗?

2 个答案:

答案 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;
相关问题