我想要隐藏unisntaller的第一条和最后一条消息.此代码适用于inno setup(Inno Setup Ultra 5.5.1.ee2)的修改版本,但不能很好地隐藏第一条消息(短暂显示并消失):
function FindWindowEx(Parent,Child: HWND; ClassName,WindowName: PansiChar): HWND; external 'FindWindowExA@user32.dll stdcall'; const BM_CLICK = $00F5; var Timer: TTimer; msg: string; Wnd,WndEx: HWND; procedure OnTimer(Sender: TObject); begin Wnd:= FindWindowByWindowName(msg); if Wnd > 0 then begin WndEx:= FindWindowEx(Wnd,'Button',''); if WndEx > 0 then begin PostMessage(WndEx,BM_CLICK,0); Timer.Enabled:= False; end; end; end; function InitializeUninstall:boolean; begin Result := True; msg:= SetupMessage(msgUninstallAppFullTitle); StringChange(msg,'%1','{#SetupSetting('AppName')}'); OnTimer(nil); Timer:= TTimer.Create(nil); with Timer do begin OnTimer:= @OnTimer; Interval:= 1; Enabled:= True; end; end; procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep); begin if CurUninstallStep=usPostUninstall then begin OnTimer(nil); Timer:= TTimer.Create(nil); with Timer do begin OnTimer:= @OnTimer; Interval:= 1; Enabled:= True; end; end; end;
解决方法
首先,我必须说我根本不同意这一点.但无论如何这都是一个有趣的问题,实施可能对其他更合适的案例有用.
此外,您无法避免短暂出现该消息.该解决方案可自动化UI,因此需要UI才能工作.这是我不喜欢它的原因之一.
此代码使用InnoTools InnoCallback DLL library来实现计时器.但是使用来自卸载程序的外部DLL库是棘手的并且有其缺点.见Load external DLL for uninstall process in Inno Setup.
[Setup] AppName=My Program [Files] Source: "InnoCallback.dll"; DestDir: {app} [Code] const BM_CLICK = $00F5; type TTimerProc = procedure(HandleW,msg,idEvent,TimeSys: LongWord); function FindWindowEx(Parent,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'; function WrapTimerProcUninstall(Callback: TTimerProc; ParamCount: Integer): LongWord; external 'wrapcallback@{%TEMP}\InnoCallback.dll stdcall uninstallonly delayload'; 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,''); if ButtonHandle > 0 then begin Log('Found button'); PostMessage(ButtonHandle,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,100,WrapTimerProcUninstall(@SubmitMessageProc,4)); 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;
该代码需要Unicode Inno Setup.
有关该问题的不同方法,请参阅Changing uninstall confirmation prompt.