Inno Setup unable to find and execute ie4uinit.exe

2019-04-15 19:19发布

问题:

This question already has an answer here:

  • A command in a .bat file is unrecognized when the .bat file is called from an Inno Setup but works fine when I run the bat file manually 2 answers

I am trying to refresh the Windows icon cache using the well known and documented method of calling ie4uinit.exe -ClearIconCache for anything below Window 10 and ie4uinit.exe -Show on Windows 10 and above:

[Run]
Filename: "{sys}\ie4uinit.exe"; Parameters: "-ClearIconCache"; StatusMsg: "Rebuilding Windows icon cache..."; Flags: runhidden; Check: not IsWindows10AndAbove
Filename: "{sys}\ie4uinit.exe"; Parameters: "-Show"; StatusMsg: "Rebuilding Windows icon cache..."; Flags: runhidden; Check: IsWindows10AndAbove

Both commands work as expected when run in Explorer or at a command prompt. They also work correctly in Inno Setup when running on an x86 system. However, on an x64 system, the following error is produced:

The path to the file, using the {sys} constant, resolves correctly and the file exists and can be seen both in Explorer and in a directory listing at the command prompt:

The following variation of the above code, running through the command prompt, also fails in much the same way, although it is silent and only indicated by an exit code of 1 in the install log.

[Run]
Filename: "{cmd}"; Parameters: "/c {sys}\ie4uinit.exe -ClearIconCache"; StatusMsg: "Rebuilding Windows icon cache..."; Flags: runhidden; Check: not IsWindows10AndAbove
Filename: "{cmd}"; Parameters: "/c {sys}\ie4uinit.exe -Show"; StatusMsg: "Rebuilding Windows icon cache..."; Flags: runhidden; Check: IsWindows10AndAbove

I have already read clear icon cache in win 7 programmatically - execute ie4uinit.exe-ClearIconCache using C# or Visual Basic, which also has mention of this being a problem in Inno Setup (towards the bottom) and tried the workaround to copy the file and run it from elsewhere. However, attempting to copy the file to another location, using the FileCopy function, also failed to find it in C:\Windows\System32. I also tried running the same command in the [Code] section using the Exec function, but this also fails to find it in C:\Windows\System32.

I considered making a copy of the file and installing it to the temp directory to run it from there, but this file is a different version on each Windows version, so this is not really a viable solution, especially as, being a system file, it may also change in the future.

The accepted answer in the above question seems to be to build the executable for 'Any CPU' rather than 'x86'. However, I am not sure if this can be done in Inno Setup and also if doing so would have any unforeseen side effects on the installers behaviour?

Is there any way to resolve or work around this in Inno Setup?

回答1:

A far simpler and better solution (thanks for the links Martin) is to have two duplicated [Run] entries for x64 with Check: IsWin64 and Flags: 64bit and to add Check: not IsWin64 to the original lines:

[Run]
Filename: "{sys}\ie4uinit.exe"; Parameters: "-ClearIconCache"; StatusMsg: "Refreshing Windows icon cache..."; Flags: runhidden; Check: not IsWindows10AndAbove and not IsWin64
Filename: "{sys}\ie4uinit.exe"; Parameters: "-Show"; StatusMsg: "Refreshing Windows icon cache..."; Flags: runhidden; Check: IsWindows10AndAbove and not IsWin64
Filename: "{sys}\ie4uinit.exe"; Parameters: "-ClearIconCache"; StatusMsg: "Refreshing Windows icon cache..."; Flags: runhidden 64bit; Check: not IsWindows10AndAbove and IsWin64
Filename: "{sys}\ie4uinit.exe"; Parameters: "-Show"; StatusMsg: "Refreshing Windows icon cache..."; Flags: runhidden 64bit; Check: IsWindows10AndAbove and IsWin64


回答2:

I finally figured this out. Inno Setup cannot find the file as, rather confusingly, despite it displaying that it is looking in C:\Windows\System32, Windows file redirection is actually silently causing it to look in C:\Windows\SysWOW64, where ie4uinit.exe does not exist. The solution, therefore, is to temporarily disable file redirection in the [Code] section, using the [Run] section BeforeInstall and AfterInstall directives, followed by the EnableFsRedirection function, after which Inno Setup can now see and access the actual C:\Windows\System32 directory, copy the file to the temp directory and run it from there, before restoring file redirection to it's previous state:

[Run]
Filename: "{tmp}\Config Tools\ie4uinit.exe"; Parameters: "-ClearIconCache"; StatusMsg: "Refreshing Windows icon cache..."; Flags: runhidden; Check: not IsWindows10AndAbove; BeforeInstall: StartRefreshIconCache; AfterInstall: FinishRefreshIconCache
Filename: "{tmp}\Config Tools\ie4uinit.exe"; Parameters: "-Show"; StatusMsg: "Refreshing Windows icon cache..."; Flags: runhidden; Check: IsWindows10AndAbove; BeforeInstall: StartRefreshIconCache; AfterInstall: FinishRefreshIconCache

[Code]
//Start refresh or rebuild of the Windows icon cache
procedure StartRefreshIconCache();
var
  OriginalFileRedirectionState: Boolean;
begin
  if not IsWin64 then
    begin
      if FileCopy(ExpandConstant('{sys}\ie4uinit.exe'), ExpandConstant('{tmp}\Config Tools\ie4uinit.exe'), False) then
        begin
          Log(ExpandConstant('Copied {sys}\ie4uinit.exe to {tmp}\Config Tools\ie4uinit.exe'));
        end;
    end
  else if IsWin64 then
    begin
      //Store Windows file redirection's original state and temporarily disable to allow access to the System32 directory on x64 to allow copy of ie4uinit.exe
      OriginalFileRedirectionState := EnableFsRedirection(False); 
      Log('File redirection temporarily disabled for x64 compatibility.');
      try
        if FileCopy(ExpandConstant('{sys}\ie4uinit.exe'), ExpandConstant('{tmp}\Config Tools\ie4uinit.exe'), False) then
          begin
            Log(ExpandConstant('Copied {sys}\ie4uinit.exe to {tmp}\Config Tools\ie4uinit.exe'));
          end;
      finally
        //Restore file redirection's original state
        EnableFsRedirection(OriginalFileRedirectionState);
        Log('File redirection restored to it''s original state.');
      end;
    end;
end;

//Finish refresh or rebuild of the Windows icon cache
procedure FinishRefreshIconCache();
begin
  if DeleteFile(ExpandConstant('{tmp}\Config Tools\ie4uinit.exe')) then
    begin
      Log(ExpandConstant('Deleted {tmp}\Config Tools\ie4uinit.exe'));    
    end;
end;