1

I have an application that is on a network Drive. I have a DLL that needs to be unregistered, updated and reregistered. I understand that the DLL will be in use so have the RestartReplace option:

; Script generated by the Inno Setup Script Wizard.
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
; EMPSecure Update
#define MyAppName "EMPSecure"                                                                                                                                                            
#define MyAppVersion "2.0.1"

#define MyAppPublisher "Empyrean Security Pty Ltd"
#define MyAppURL "http://www.empyreansecurity.com"
#define MyAppExeName "EMPSecure.exe"
#define MyAppCopyright "Copyright © Empyrean Security 2012-2022"

#define MySourcePath     "\\mac\Dropbox\Embarcadero\EMPSecure Update"

    [Setup]
    PrivilegesRequired=admin
    AllowNetworkDrive=yes
    AllowUNCPath=yes
    AppId={{#MyAppID}
    AppName={#MyAppName}
    AppVersion={#MyAppVersion}
    ;AppVerName={#MyAppName} {#MyAppVersion}
    AppPublisher={#MyAppPublisher}
    AppPublisherURL={#MyAppURL}
    AppSupportURL={#MyAppURL}
    AppUpdatesURL={#MyAppURL}

The actual line is:

Source: "{#MySourcePath}\SFMS_ShellExt.dll"; DestDir: "{app}"; Flags: regserver restartreplace replacesameversion 64bit; Check: Is64BitInstallMode; 

If I have a UNC path for the app like \\mac\Dropbox\path....

I get this error:

Error MoveFileEx Failed, Code 87.

I have tried using a mapped network drive, but that fails in other places, but regardless, I really need to be able to use a UNC path (most users will not install using a UNC path, but some, like me, will so need to cater for that option).

I did try this: Deleting and unregistering DLL files during install using Inno Setup but the actual deletefile kept failing with Access Denied errors.

If the complete script would be useful then let me know, I just didn't want to confuse the issue with a deal of not relevant script lines.

Is there some 'trick' other than the AllowUNCPath in [Setup] that will get the restartreplace flag code to recognise the UNC path in {app}?

Thank you.

UPDATE

As advised by Martin, I have simply downloaded the file to {tmp} and converted my original batch file to pascal code. The operation unregisters the DLL in the {app} folder, copies the new DL:L from {tmp} to {app} and re-registers the DLL (because of what we do we need to kill and restart explorer, but that's not germane to the issue).

Because this is development stuff, the app folder is in my Dropbox on an iMac and the path is \mac\dropbox\etc etc. The original unregister precisely finds that path, but I get an error that says the folder not found. Here's the code which fails in the unregister statement because it cannot find the path:

[Code]

procedure RegisterShellExt();
var
  ResultCode: integer;

begin
  // Deregister and delete sfms_shellext.dll
  if Exec(ExpandConstant('Regsvr32 /u "{app}\SFMS_ShellExt.dll"'), '', '', SW_SHOW,ewWaitUntilTerminated, ResultCode) then
  begin
    // Successfully unregistered, copy the new dll
    Log('SFMS_ShellExt.dll successfully unregistered');
    sleep(5000)
    Exec('taskkill /f /fi "IMAGENAME eq explorer.exe"', '', '', SW_SHOW,ewWaitUntilTerminated, ResultCode);

    // Overwrite if Exists
    if FileCopy(ExpandConstant('"{tmp}\SFMS_ShellExt.dll"'), ExpandConstant('"{app}\SFMS_ShellExt.dll"'), False) then
    begin
      // Successfully copied, now register the dll
      Log(ExpandConstant('SFMS_ShellExt.dll successfully copied from: {tmp} to {app}'));
      if Exec(ExpandConstant('regsvr32 "{app}\SFMS_ShellExt.dll"'), '', '', SW_SHOW,ewWaitUntilTerminated, ResultCode) then
      begin
        // Successfully copied, now register the dll
        Log('SFMS_ShellExt.dll successfully re-registered');
      end
      else      
      begin
        // handle deregister failure
        MsgBox('Failed to re-register SFMS_ShellExt.dll, Error: ' + SysErrorMessage(ResultCode), mbError, MB_OK);
      end
    end
    else
    begin
      MsgBox(ExpandConstant('Failed to copy SFMS_ShellExt.dll from {tmp} to {app}'), mbError, MB_OK);
    end;
  end
  else                                                  
  begin
    // handle deregister failure
    MsgBox('Failed to deregister sfms_shellext.dll, registration not attempted, Error: ' + SysErrorMessage(ResultCode) + '  File: ' + ExpandConstant('"{app}\SFMS_ShellExt.dll"'), mbError, MB_OK);
  end;

  // Restart explorer and continue
  Exec('explorer.exe"', '', '', SW_SHOW,ewNoWait, ResultCode);
end;

File NOT FOUND Error Path and File exist

So question, I have tried this with a UNC path (thought that might be the erro), but tried it also with a straight c:.... path and even though the file exists, I get a file not found error. Any ideas what I might be doing wrong??

Kevin Black
  • 119
  • 1
  • 10

1 Answers1

0

The restartreplace mode uses MoveFileEx MOVEFILE_DELAY_UNTIL_REBOOT API. And it indeed does not work on the network shares as the Microsoft documentation says:

If dwFlags specifies MOVEFILE_DELAY_UNTIL_REBOOT, the file cannot exist on a remote share, because delayed operations are performed before the network is available.


So you would have to come up with an alternative solution. Like creating a batch file scheduled to run on the next login that does the delete/replace.

Also what about CloseApplications? It should do the job without the restartreplace.

Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
  • Thank you for the advice, unfortunately CloseApplications generates a deletefile error with Access Denied. I tried the DELETEFILE function suggested here without success: https://stackoverflow.com/questions/48807033/deleting-and-unregistering-dll-files-during-install-using-inno-setup – Kevin Black Apr 13 '22 at 04:51
  • *"unfortunately CloseApplications generates a deletefile error with Access Denied"* – post log file for that. + `DeleteFile` obviously cannot work on a file in use. + There's still the "batch file" (or other script) solution. – Martin Prikryl Apr 13 '22 at 05:08
  • Martin, I have come up with a solution that should work (based on your advice to develop something in code/batch file post processing), see my UPDATE above. Basically save DLL to {tmp}, unregister the extant DLL from {app}, copy the new dll from {tmp] to {app} and register it from the {app} folder. Works in a batch file, but code section cannot find file even though the path and filename are precisely correct. Any ideas why this might be? – Kevin Black Apr 19 '22 at 10:20
  • First, you have asked a question about "replacing file after restart". Now you have taken a completely different approach. So I believe you should either completely rewrite your question and start a new one. – Anyway, are you sure the *"not found"* refers to the DLL? It might as well refer to the `Regsvr32`. Did you try using an absolute path for a test? And why are you even using `regsvr32`? Use [`UnregisterServer`](https://jrsoftware.org/is6help/index.php?topic=isxfunc_unregisterserver). – Martin Prikryl Apr 19 '22 at 10:52
  • Martin, OK good points well made. I simply morphed the attempted solution into your suggestion, but I will do as you suggest and ask another question if explicitly pointing to regsvr32 (or indeed unregisterserver) does not work. The error message could indeed be referring to regsvr32 since it is me, not the error message that adds the file name. – Kevin Black Apr 19 '22 at 23:22
  • Well, I didn't really suggest what you are doing atm. It seems that you have misunderstood my suggestion. – Martin Prikryl Apr 20 '22 at 07:38
  • Also note an exit code of an application typically does not correspond to Windows system error codes. Only if the code comes from the system itself [and you cannot know that], when trying to execute the app (like indeed in case the `regsvr32` cannot be found), it makes sense to pass the code to `SysErrorMessage`. When the code comes from the application, you will be misinterpreting the code. Particularly for `regsvg32` the code 2 (system code for `ERROR_FILE_NOT_FOUND`) actually [means *"OleInitialize failed"*](https://devblogs.microsoft.com/oldnewthing/20180920-00/?p=99785). – Martin Prikryl Apr 20 '22 at 07:38
  • On the other hand, it's more likely that the code indeed means `ERROR_FILE_NOT_FOUND`, as *"OleInitialize failed"* is imo less likely to happen. – Martin Prikryl Apr 20 '22 at 07:40