I want to hide the first and the last message of the uninstaller. This code works with a modified version of inno setup (Inno Setup Ultra 5.5.1.ee2) but does not work well t
First, I must say that I do not agree with this at all. But it's interesting problem anyway, and the implementation might be useful for other, more appropriate cases.
Also you cannot avoid the message to appear briefly. The solution automates the UI, so needs the UI to work. That's one of the reasons I do not like it.
[Setup]
AppName=My Program
[Code]
const
BM_CLICK = $00F5;
function FindWindowEx(Parent, Child: HWND; ClassName, WindowName: string): HWND;
external 'FindWindowExW@user32.dll stdcall';
function SetTimer(hWnd, nIDEvent, uElapse, lpTimerFunc: LongWord): LongWord;
external 'SetTimer@User32.dll stdcall';
function KillTimer(hWnd, nIDEvent: LongWord): LongWord;
external 'KillTimer@User32.dll stdcall';
var
UpcomingMessage: string;
SubmitMessageTimer: LongWord;
SubmitMessagePossible: Boolean;
procedure SubmitMessageProc(
H: LongWord; Msg: LongWord; IdEvent: LongWord; Time: LongWord);
var
WindowHandle, ButtonHandle: HWND;
begin
{ TODO: Cancel the timer, if the message does not appear within few seconds }
WindowHandle := FindWindowByWindowName(UpcomingMessage);
if WindowHandle > 0 then
begin
Log(Format('Found message window "%s"', [UpcomingMessage]));
ButtonHandle := FindWindowEx(WindowHandle, 0, 'Button', '');
if ButtonHandle > 0 then
begin
Log('Found button');
PostMessage(ButtonHandle, BM_CLICK, 0, 0);
KillTimer(0, SubmitMessageTimer);
SubmitMessageTimer := 0;
end;
end;
end;
procedure SubmitUpcomingMessage(Msg: string);
begin
if not SubmitMessagePossible then
begin
Log('Cannot submit message');
end
else
begin
if SubmitMessageTimer > 0 then
KillTimer(0, SubmitMessageTimer);
Log(Format('Want to automatically submit message "%s"', [Msg]));
UpcomingMessage := Msg;
SubmitMessageTimer := SetTimer(0, 0, 100, CreateCallback(@SubmitMessageProc));
end;
end;
function FmtSetupMessageWithAppName(const ID: TSetupMessageID): string;
begin
Result := FmtMessage(SetupMessage(ID), ['{#SetupSetting('AppName')}']);
end;
function InitializeUninstall:boolean;
begin
Result := True;
SubmitMessagePossible :=
FileCopy(
ExpandConstant('{app}\InnoCallback.dll'),
ExpandConstant('{%TEMP}\InnoCallback.dll'), False);
SubmitUpcomingMessage(FmtSetupMessageWithAppName(msgUninstallAppFullTitle));
end;
procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
begin
if CurUninstallStep = usPostUninstall then
begin
SubmitUpcomingMessage(FmtSetupMessageWithAppName(msgUninstallAppFullTitle));
end;
end;
For CreateCallback function, you need Inno Setup 6.
If you are stuck with Inno Setup 5, you can use WrapCallback function from InnoTools InnoCallback library (the code needs Unicode version of Inno Setup 5). But using an external DLL library from an uninstaller is tricky and has its drawbacks. See Load external DLL for uninstall process in Inno Setup.
For a different approach to the problem, see Changing uninstall confirmation prompt.