二重起動したら既に起動しているアプリを終了する方法

解決


初心者M  2013-02-07 11:44:41  No: 103399  IP: [192.*.*.*]

(VB6+XP)  Indexのような機能を持つアプリ_Aから各種の条件を指示してアプリ_Bを起動するソフトを作り、使用してきました。  アプリ_BにはIf App.PrevInstance Then ・・・・・  と書いて2重起動を禁止して古いアプリを消すように促してきましたがこれを自動化して新しく起動する前に古いアプリを自動的に終了させるようにしたいと思います。アプリ_Aから命令を出してアプリ_Bを終了させる方法はあるのでしょうか?  あれば教えてください。

編集 削除
魔界の仮面弁士  2013-02-07 15:30:03  No: 103400  IP: [192.*.*.*]

後から起動した方が有効として、先に起動していた方が終了とするのではなく、
既に起動されていたら、自分は何も実行せずに即時終了させる…という
逆パターンでは駄目なのでしょうか。それで良ければ、こんな感じにできます。
http://support.microsoft.com/kb/185730/ja


もし、自分以外のアプリを終了させるとなると、たとえば
  (1) Project1.EXE を起動させる。これを「A」とする。
  (2) 他に同アプリは起動していなかったので、A は特に何もしない。
  (3) 後から、同EXE がほぼ同時に 2 つ起動された。これらは「B」「C」と呼ぶ。
  (4) B は A と C に終了通知を投げ、C は A と B に終了通知を投げる。
  (5) そして誰も居なくなった…。
という事態になってしまうことも考えられますので、
この部分の作りこみをどうするかは、事前に良く考えておいてください。


なお、プロジェクト間通信としては、以下のような案で如何でしょう。

・DDE を用いる。(非表示の Label コントロール等を通信に利用)
    相手側の Label に文字列を送り込み、受信側は Change イベントが
    発生したタイミングで、自分自身を終了させるように実装する。
    http://7ujm.net/VB/VB6DDE.html
    http://support.microsoft.com/kb/189498/ja
  利点:VB の標準命令だけで実装できる。
  欠点:複数アプリとの通信ができない。

・ActiveX EXE によるオートメーション操作。
    http://kozhouse.homeip.net/dcomchat/
    VB6 付属 CD-ROM 内の Coffee クライアントサンプルなど
    http://msdn.microsoft.com/en-us/library/aa445814.aspx
  利点:どのようなデータでも引き渡せるため、終了以外の目的にも応用可能。
  欠点:ActiveX であるがため、事前にレジストリへの登録が必要となる。
    また、同アプリにサーバー/クライアントの機能を同居させるため、
    相手が終了した後は、自身がサーバーの責を引継ぐよう設計する必要がある。

・ウィンドウメッセージを用いる。
    SendMessage API で WM_CLOSE を送出して終了させる。
    あるいは、WM_SETTEXT メッセージを TextBox で送出し、TextBox_Change で
    受けたり、ユーザー定義メッセージをサブクラス化して受け取るなどして、
    それを終了の合図とするように作りこむなど。
  利点:レジストリ登録が不要となる。
  欠点:通信相手のウィンドウハンドル(hWnd)を調べる必要がある。

・Win32_Process クラスの Terminate メソッドを呼び出す。
    WMI にてプロセスを列挙し、自分以外に対して終了命令を投げていく。
  利点:API 宣言も ActiveX 宣言も不要となる。
  欠点:外部からの強制終了となるため、Form の Unload イベント等は実行されない。

・TASKKILL コマンドを用いる。
    Shell 関数にて TaskKill.exe を呼び出して終了通知を発行する。
  利点:終了時に QueryUnload も発生するため、比較的安全・簡単に終了させられる。
  欠点:通信相手のプロセスIDが必要となる。
    また、XP Home には TASKKILL が用意されていない(Pro なら OK)。

編集 削除
初心者M  2013-02-08 14:56:12  No: 103401  IP: [192.*.*.*]

魔界の仮面弁士様  お世話になります。各種のアイデアをご提供いただきありがとうございました。DDE通信というものを初めてでしたが試してみましたところ、これで目的の動作が得られるものと思いましたので解決のチェックを入れさせていただきました。  テストしたものは下記のようなものですが、これで何か問題が考えられるようでしたらご指摘ください。ありがとうございました。

----------サーバー側 (Project1.exe)---------------
'③通信するフォームのプロパティにて以下の様に設定
'LinkTopic  :    IdentString   ←DDE通信時の識別子、重複しないユニークな名前をつける
'LinkMode   :    1             ←DDE通信をアクティブに設定

Private Sub Command1_Click()

Text1.Text = "sayonara"

'様子を見てDelayが必要?

text1.text = "welcome"
ret = Shell("project2.exe", 1)

End Sub

----------クライアント側(Project2.exe)---------------
Private StartDoc As String
Private NewDoc As String

Private Sub Form_Load()
   '各種設定
    Text1.LinkTopic = "Project1|IdentString"
    Text1.LinkItem = "Text1"

    'DDE通信の開始
    Text1.LinkMode = 1
    StartDoc = Text1.Text
    
    Caption = Now
    WindowState = 0

End Sub

Private Sub Text1_Change()

    NewDoc = Text1.Text    
    If NewDoc <> StartDoc and NewDoc="sayonara" Then End    

End Sub

編集 削除