问题
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