2017-02-15 7 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を自動化するため、UIを機能させる必要があります。それが私が好きではない理由の1つです。


このコードは、タイマーを実装するために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を参照してください。

関連する問題