Possible to call DLL function in uninstaller if DLL has dontcopy flag?

若如初见. 提交于 2020-08-23 13:02:48

问题


As the title says I need a function in my DLL which I need to call while uninstalling.

The DLL is included this way

#define myProgData "C:\ProgramData\Foo\Bar"

[Files]
Source: "mydll.dll"; Flags: dontcopy

I already use one function while installing and now I want to know if I can use the same DLL for uninstall or does the DLL have to be copied so the uninstaller can access it?

I've tried a simple call already but got the

Could not call proc - Exception

So I'm looking for the reason for this.

Update:

I've tried to copy the DLL out of the setup, the call works just great then.

Update 2: (sorry for late response)

Here's what the script looks like

[Files]
Source: "myDll.dll"; Flags: dontcopy;
(...)

[Code]    
function myUninstallFunction(foo: Integer): Boolean;
external 'myFunction@{#myProgData}myDll.dll stdcall uninstallonly';

which is used this way

function InitializeUninstall(): Boolean;
begin
    if myUninstallFunction(1) then
    begin
        MsgBox(ExpandConstant('{cm:uninstallFail}'), mbError, MB_OK);
        Result := false;     
    end;
    (...)
end;

I've tried to use another event procedure too e.g. CurUninstallStepChanged(CurUninstallStep: TUninstallStep);.


回答1:


You cannot call a DLL embedded in installer from uninstalled, as at uninstall time, the uninstaller is not aware of installer location (and it may not exist anymore anyway).

It's possible to embed the DLL into uninstaller instead, but it's way more work. See my answer to How keep uninstall files inside uninstaller?

Other than that, there's no better solution than you have found already:

  • Install the DLL somewhere
  • And reference the path to the installed DLL in the uninstall code.

Some background information to explain the behavior you are experiencing:

There's files: prefix available in the external declaration that makes the Inno Setup automatically extract the DLL when the function is needed and delete the extracted DLL automatically.

See Pascal Scripting: Using DLLs:

During Setup, a special 'files:' prefix may also be used to instruct Setup to automatically extract one or more DLLs from the [Files] section before loading the first DLL.

Example:

procedure MyDllFuncSetup(hWnd: Integer; lpText, lpCaption: AnsiString; uType: Cardinal);
external 'MyDllFunc@files:MyDll.dll stdcall setuponly';

But it does not work in the uninstaller.

You can see that even the official example CodeDll.iss uses the files: for an installer function, but resorts to using the installed DLL ({app}\) for an uninstaller function:

[Files]
...
; Install our DLL to {app} so we can access it at uninstall time
; Use "Flags: dontcopy" if you don't need uninstall time access
Source: "MyDll.dll"; DestDir: "{app}"
[Code]
...
procedure MyDllFuncSetup(hWnd: Integer; lpText, lpCaption: AnsiString; uType: Cardinal);
external 'MyDllFunc@files:MyDll.dll stdcall setuponly';

procedure MyDllFuncUninst(hWnd: Integer; lpText, lpCaption: AnsiString; uType: Cardinal);
external 'MyDllFunc@{app}\MyDll.dll stdcall uninstallonly';

Even the Inno Setup source code confirms that (Projects\main.pas function CodeRunnerOnDllImport):

if Pos('files:', DllName) = 1 then begin
  if IsUninstaller then begin
    { Uninstall doesn't do 'files:' }
    DllName := '';
    ForceDelayLoad := True;

That explains the "Could not call proc - Exception", as Inno Setup would behave as if the DLL name is not even specified, but delayload flag is there. The DLL is not found by the uninstaller and you get the cryptic error message (as you get normally with delayload flag only).

You can also check that using both files: and uninstallonly gets you

"uninstallonly" cannot be used with "files:"



来源:https://stackoverflow.com/questions/32782610/possible-to-call-dll-function-in-uninstaller-if-dll-has-dontcopy-flag

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!