2017-02-15 265 views
1

我想隱藏unisntaller的第一條和最後一條消息。該代碼可以使用Inno Setup的(Inno Setup的超5.5.1.ee2)修改後的版本,但不能很好地工作,以隱藏第一消息(短暫出現,消失):Inno Setup - 自動提交卸載提示

function FindWindowEx(Parent, Child: HWND; ClassName, WindowName: PansiChar): HWND; 
    external '[email protected] 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, 0,'Button', ''); 
    if WndEx > 0 then 
    begin 
     PostMessage(WndEx, BM_CLICK, 0, 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; 

如何修改這個代碼使用Inno Setup的當前正式版本正確工作並正確隱藏這兩個消息?

+0

Inno Setup中沒有'TTimer'類。你使用Inno Setup的第三方版本嗎? –

+0

@MartinPrikryl此代碼適用於inno setup的修改版本(Inno Setup Ultra 5.5.1.ee2)。我正在使用Inno Setup的最新版本。 –

+0

@MartinPrikryl我用這些信息編輯了我的帖子。 –

回答

0

首先,我必須說我完全不同意這一點。但無論如何,這是一個有趣的問題,而實施可能對其他更合適的案例有用。

此外,您無法避免短暫出現的消息。該解決方案使用戶界面自動化,因此需要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, Child: HWND; ClassName, WindowName: string): HWND; 
    external '[email protected] stdcall'; 
function SetTimer(hWnd, nIDEvent, uElapse, lpTimerFunc: LongWord): LongWord; 
    external '[email protected] stdcall'; 
function KillTimer(hWnd, nIDEvent: LongWord): LongWord; 
    external '[email protected] stdcall'; 

function WrapTimerProcUninstall(Callback: TTimerProc; ParamCount: Integer): LongWord; 
    external '[email protected]{%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, 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, 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