You cannot call a DLL embedded in installer from uninstaller, 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.
- Use
UnloadDLL
to unload the loaded the DLL, so that you can delete it. (I believe that .NET assembyl DLLs cannot be unloaded. For those you might copy the DLL to a temp folder, before loading, so that you can delete the installed copy. See Load external DLL for uninstall process in Inno Setup)
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:"