はじめまして。
現在、タスクトレイ常駐のアプリを作成しております。
セットアッププロジェクトでインストーラーも作成し、
EXEを実行すると、タスクトレイにてメールの常駐監視
を行います。
動作面は完成したので、アンインストールの動作も確認
しようと思い、EXE実行中にアンインストールしたら
インストールフォルダ内のEXEファイルなどの削除は確認
できたのですが、タスクトレイでは実行中のままになって
おり、困っております。
セットアッププロジェクトの設定に不足があるのか、アプリ
の処理に不足があるのか?全くわからず手詰まりです。
どなたかアドバイスを頂戴できないでしょうか?
宜しくお願いいたします。
環境:
Vista ビジネス
VisualStudio2005(VC++)
MFC
タスクトレイアイコンは、タスクトレイアイコンを登録したEXEが終了しただけでは自動
的に消えることはありません。(ただし、タスクトレイアイコンにマウスカーソルを宛て
ると消える、中途半端だがそういう仕様らしい)
アンインストール作業中に自分で消すようにしましょう。
それとも、EXEのインスタンスが終了しないという話?
だとしたら、話が全く変わります。
bunさん、コメントありがとうございます。
>タスクトレイアイコンは、タスクトレイアイコンを登録したEXEが終了しただけでは自動
>的に消えることはありません。
この部分はEXE終了時に、タスクトレイアイコンの削除をしているので、何とか消えてます。
EXEが終了してくれれば、タスクトレイアイコンの削除処理を通ってくれるので、良いの
ですが…
>それとも、EXEのインスタンスが終了しないという話?
その通りです。
書き方が紛らわしかったかもしれません。
[手順]
1.AAA_Setup.exeでAAA.exeをインストール。
2.AAA.exeを実行し、タスクトレイに常駐開始。
3.「コントロールパネル」の「プログラムの追加と削除」からAAA.exeの削除を選択
4.Program Files内のAAAフォルダ(AAA.exeの格納場所)が削除される。
5.タスクトレイのAAA.exeは常駐中。(ここが問題)
[したいこと]
案1.
<4.>の際に、<2.>で常駐開始しているAAA.exeも常駐を自動的に終了してタスクトレイ
から削除してしまいたい。
案2.
<3.>の際に、「AAA.exeが起動中です。終了させてください。」的なメッセージを
表示させて、終了するまではアンインストールできないようにする。
上記のようなことをしたいと考えているのですが、「どうしたもんか…」という
状況です。
もし、よろしければヒント等を教えていただけないでしょうか?
よろしくお願いいたします。
> 4.Program Files内のAAAフォルダ(AAA.exeの格納場所)が削除される。
たぶんですが、これは削除されていないです。
AAA.exeが実行中なら、AAA.exeの削除は失敗し、したがって空でないAAAフォルダの削除
も失敗すると思うからです。
それで、結論ですが、
タスクトレイ常駐型のアプリケーションは、
・2重起動を許さない
・アプリケーション終了時に保存確認をしない
場合がほとんどだと思いますので、案1の方がより親切かと思います。
案1の実現方法はいろいろ考えられますが、最も安全なのは、起動中のAAA.exeを普通に
終了することです。
FindWindow()というAPIを使用して、起動中のアプリケーションのメインウィンドウのハ
ンドル(見つかったハンドルをhWndとする)を探し、
::PostMessage(hwnd, WM_CLOSE);
とするだけです。
FindWindow()の使い方は
以下のHPの[二重起動防止]のコーディング例が参考になるでしょう。
http://hp.vector.co.jp/authors/VA000092/win32/misc.html
より安全なのは、ウィンドウクラス名で検索をかける方です。
bunさん、アドバイスありがとうございます。
サイトの方を確認させていただいたのですが、この場合、
1.アンインストール時用のexeを作成し、その中にFindWindow()の処理を記載する。
2.アンインストール時に<1.>のexeを呼び出し、AAA.exeを終了させる。
という形になるのかな?と読んだのですが、アンインストール時に別exeを呼び出す
方法がわかりません。
それとも、読み取り方が間違っているのでしょうか…
質問ばかりで申し訳ございませんが、よろしくお願いいたします。
# 使用しているインストーラーの種類にもよると思うのですが。
InstallShieldの場合なら、ファイル削除のアンインストール直前にスクリプト
が起動できたような気がします。
スクリプトが起動できるのであれば、WSHなりをコールして削除対象のプロセスを
殺せないカナ、と思ったり。
VC2005で、exeとセットアッププロジェクトを作成し
XPsp2で試してみたところ
アプリケーションが起動中に、プログラムの追加と削除で削除しようとすると
アプリケーションの終了確認がでますね
vistaでは、でなくなってしまったのかな
終了確認には「無視」ってのがあって
これを選ぶと、起動中のアプリからファイルの関係を切り離し、
exeファイルだけ消しますが
すでに起動してあるものを閉じるときに終了処理はされますので
タスクトレイのアイコンは消せます。
ところでちょっと気になったのですが
>>それとも、EXEのインスタンスが終了しないという話?
>その通りです。
インスタンスが残ってることはどうやって確認しましたか?
>5.タスクトレイのAAA.exeは常駐中。(ここが問題)
ここで残ってるアイコンから、起動してるアプリに操作(作ってあればだけど)
したりできますか?
玲音 (st.lain)さん、rinさん、コメントありがとうございます。
玲音 (st.lain)さん
>スクリプトが起動できるのであれば、WSHなりをコールして削除対象のプロセスを
>殺せないカナ、と思ったり。
セットアッププロジェクトで、インストーラを作成しているのでカスタム動作の所
にアンインストール時の項目があるので、そこに追加したら良いのかもしれません。
ただ、WSHが未だわかってないので、今、急きょ調査中です…
rinさん
>vistaでは、でなくなってしまったのかな。
普通、出そうなものなのですが…
コントロールパネルから、プログラムの削除を選択すると、確認メッセージが表示される
のですが、インストーラーをダブルクリックして、「プログラムの削除」を選択した時に
は確認メッセージなど表示されません。(Vista)
XPでダブルクリックしてみても、確認メッセージなど表示されないので、セットアップ
プロジェクトの設定が間違ってると思うのですが、確認メッセージの表示有無の設定箇所
もなさそうですし…
>インスタンスが残ってることはどうやって確認しましたか?
自信がないのですが…
exe起動したら、タスクマネージャーにAAA.exeが動作中になっている状態なので、
メモリに配置されているのかな??と思い、「その通りです。」と回答してしまいました。
プログラム・Windowsの基礎的な知識がないので、まず、そこから勉強すべきだとは思うの
ですが…
>ここで残ってるアイコンから、起動してるアプリに操作(作ってあればだけど)
したりできますか?
残っているアイコンの右クリックメニューで操作はできるので、なんらかの操作は
できそうです。
いっそのこと、インストーラにレジストリ書き込み設定を付けて、常駐中にレジストリ
を定期的に見に行って、フォルダにexe残ってなかったらタスクトレイ終了という方法
もあるかな?
と思っています。
> アンインストール時の項目があるので、そこに追加したら良いのかもしれません。
申し訳ないです、確認したら「アンインストールが終わった後」のようでした。
結局、アンインストール前の確認はrinさんの書かれたような競合確認に
委ねられるのカナ・・・。(同じくWinXP上でダイアログは確認しました)
ちょっと見ないうちに話が進んでいますね。
アンインストール時に別exeを呼び出す方法について触れなかったのは、玲音 (st.lain)
さんの話通り、インストーラによって呼びだす方法が異なるからです。
InstallShieldのような高度なインストーラだと、FindWindow()の処理を実装したDLLを
作成しておいて、それを呼び出せます。
私がフリーソフトに使用しているようなインストーラだと、コマンド呼び出しができま
すので、コマンドライン引数によりアンインストール時の処理を実行しています。
(例) AAA.exe /Uninstall
このように呼びだして、コマンドライン引数「/Uninstall」が指定された場合に、
FindWindow()の処理をするように実装するわけです。
私の場合は、ほとんどこの方法でやっていますね。
同じ方法で、インストール時の処理なども実装できます。
すいません
XPですが、現象確認しました
ウィンドウが見えない状態(タスクバーも消しておく)のときだけアンインストールす
ると、
なんの確認もでないまま、インスタンスを残してexeファイルを削除しちゃいました。
コントロールパネル>「プログラムの...」、およびインストールにつかったexeからの
アンインストールの
どちらでも起きました。
アンインストール後に再起動させるものなんかは、こういう場合にも必要なのかもしれ
ないですね
インストーラだけで再起動させるのはVC2005だけでは無理らしいので(msiを弄るOrcaが
必要らしい)
FindWindowをつかった終了させる終了.exeつくり
セットアッププロジェクトのカスタム動作で、アンインストール後に終了.exeを動かす
ようにしたら
起動中のインスタンスも消せました。
#アンインストール後ってことになってるけど
#終了.exeでエラー起こさせると、アンインストールに失敗したことになって
#AAA.exeが消えなかった
カスタム動作は、セットアッププロジェクトを開いてる状態で
[表示]→[エディタ]→[カスタム動作]
です
玲音 (st.lain) さん、bun さん、rinさん、アドバイスありがとうございます。
返信、遅れましてすみません。
レジストリいじる方法でやってみようと触ってたら、PCにちょっと不具合出ちゃいました…。
>私がフリーソフトに使用しているようなインストーラだと、コマンド呼び出しができま
>すので、コマンドライン引数によりアンインストール時の処理を実行しています。
>(例) AAA.exe /Uninstall
私もフリーソフトで実現できないかと思い、試してみたのですが、そのソフト特別な動きを
させる場合は、PsacalScriptでコードを記述するらしく、他のソフトを模索中です。
>FindWindowをつかった終了させる終了.exeつくり
>セットアッププロジェクトのカスタム動作で、アンインストール後に終了.exeを動かす
>ようにしたら
>起動中のインスタンスも消せました。
一度、このexeを作って試してみます。
ありがとうございました。
FindWindowでHWNDを取得させようと作成してみたのですが、HWND取得のところで躓いてお
ります。
AAA.exe(タスクトレイ常駐アプリ)を終了させるBBB.exeを作成しようとしています。
CAAADlg自体は画面が非表示で作成しておりまして、ALT+TABなどで一覧に表示されない様に
作成しております。
常駐中はタスクマネージャのアプリケーション一覧にはでてきません。
タスクマネージャのプロセス一覧には表示されております。
AAAで何らかのダイアログを表示させると、表示させたダイアログを終了できるのは確認
できたのですが、ウィンドウをもたないものを終了したいのですが、どうすれば良いので
しょうか?
試しに自分でもやってみたのですが、トップレベルウィンドウが存在すれば、非表示で
あってもうまく動作しました。
うまく動作したときの条件は以下の通りです。
・SDIでプロジェクトを作成
プロジェクト名は'Test'にした
・CMainFrame::PreCreateWindow(CREATESTRUCT& cs)の先頭で
// タイトルを'Test'固定文字列にする
cs.style &= ~(FWS_ADDTOTITLE | FWS_PREFIXTITLE);
・CxxxApp::InitInstance()で、
[/Uninstall]が指定されないときは、最初からメインウィンドウを非表示とし、
タスクバーにも非表示とするために以下のコードを実装
ParseCommandLine(cmdInfo);の直前で
m_nCmdShow = SW_HIDE;
関数末尾の以下の2行をコメントアウト
// m_pMainWnd->ShowWindow(SW_SHOW);
// m_pMainWnd->UpdateWindow();
[/Uninstall]が指定された時は、
関数先頭で
HWND hWnd = ::FindWindow(NULL, _T(Test));
if(hWnd) ::PostMessage(hWnd, WM_CLOSE, 0, 0);
return FALSE;
これで、[/Uninstall]指定無し起動で非表示起動し、[/Uninstall]指定あり起動で、非
表示起動したインスタンスおよび自分自身のインスタンスの双方が終了しました。
ダイアログアプリの場合は、また違うんでしょうかねぇ?
ちょっと、こちらでも試してみます。
仮に、BBB.exeが終了させたいAAA.exeの絶対パスを把握しているのであれば、
WMIのWIN32_PROCESSで対象のプロセスを列挙してTerminate()するのも手カナ、と。
WQL
SELECT * FROM Win32_Process WHERE ExecutablePath = '<実行ファイルパス>'
注: <実行ファイルパス>のパスセパレート文字(\)はエスケープしてください。
参考リンクは以下のとおりです。
>> Hey, Scripting Guy! - Win32_Process
>
http://www.microsoft.com/japan/technet/scriptcenter/resources/qanda/nov04/hey11
15.mspx
C++からのWMIが・・・(ry
ただし、Win32_ProcessがTerminate(恐らくは、Win32のTerminateProcess())しか
ないので、プロセスを安全に終了させる場合は避けるべき方法となります。