プログラムが起動されたことを知るには?

解決


ABC  2008-11-14 13:19:07  No: 140841  IP: 192.*.*.*

環境:WinXP VB6sp5

常駐型のプログラムを作成しようとしています。
Windows上でプログラムが起動されたことをトリガに処理をさせたいのですが、SendMessageでよいのでしょうか?

編集 削除
魔界の仮面弁士  2008-11-14 14:25:18  No: 140842  IP: 192.*.*.*

> Windows上でプログラムが起動されたことをトリガに

その起動されたプログラムとは、常駐プログラム自身の事ですか?
それとも常駐プログラムが、他のプログラムの起動を監視するのですか?
あるいは起動された他のプログラムが、常駐プログラムに処理の開始を依頼するのですか?


> SendMessageでよいのでしょうか?
誰が何の処理を行うのかによって、実装も変わってくるかと思います。

常駐アプリの起動時に、何か処理を行いたいのであれば、たとえば
『常駐アプリが、自身の起動時に処理用アプリを起動する。』
といった実装にできるでしょう。

他のアプリの起動状況を調べたいのであれば、WMI のイベント通知を用いて
Win32_Process クラスの変化を捉えるようにするとか。

編集 削除
ABC  2008-11-14 14:53:45  No: 140843  IP: 192.*.*.*

有難う御座います。
監視するのは他のプログラムになります。

Win32_Processについて調べてみます。

編集 削除
ABC  2008-11-14 18:08:48  No: 140844  IP: 192.*.*.*

以下の処理で実現できました。
有難う御座いました。


    Dim PrcEvt
    Dim Prc
    Dim Locator
    Dim Service
    Dim MesStr

    Set Locator = CreateObject("WbemScripting.SWbemLocator")
    Set Service = Locator.ConnectServer
    
    Set Prc = Service.ExecNotificationQuery _
        ("SELECT * FROM __InstanceOperationEvent " _
        & "WITHIN 1 WHERE TargetInstance ISA 'Win32_Process'")


    Do
        DoEvents
                
        Set PrcEvt = Prc.NextEvent

         Select Case PrcEvt.Path_.Class
            Case "__InstanceCreationEvent"
                  If MsgBox(PrcEvt.TargetInstance.Name & "が起動しました。" & vbCrLf & _
                       "監視を終了しますか?", vbYesNo + vbQuestion) = vbYes Then Exit Do
            Case "__InstanceDeletionEvent"
                  If MsgBox(PrcEvt.TargetInstance.Name & "が終了しました。" & vbCrLf & _
                       "監視を終了しますか?", vbYesNo + vbQuestion) = vbYes Then Exit Do

        End Select

    Loop

    Set PrcEvt = Nothing
    Set Prc = Nothing
    Set Locator = Nothing
    Set Service = Nothing

編集 削除
魔界の仮面弁士  2008-11-14 21:48:13  No: 140845  IP: 192.*.*.*

もしかして、VBScript 版のソースを参考にされたのでしょうか?

そのコードだと、ポーリング間隔(1 秒ごと)の DoEvents が実行されるまでの間、
VB アプリが応答無し状態になってしまいますので、VB6 から利用する場合には、
非同期メソッドを用いて、イベントで処理する事をお奨めします。


それと、監視したいのはアプリの起動だけなのですよね。であれば、
__InstanceOperationEvent を使うのは少々大袈裟で、
__InstanceCreationEvent で十分かもしれません。


' === 参照設定:Microsoft WMI Scripting V1.2 Libary ===
Option Explicit

Private WithEvents InstanceCreationEvent As WbemScripting.SWbemSink
'Private WithEvents InstanceOperationEvent As WbemScripting.SWbemSink
'Private WithEvents InstanceDeletionEvent As WbemScripting.SWbemSink
'Private WithEvents InstanceModificationEvent As WbemScripting.SWbemSink

Private Sub Form_Load()
    Const PollingInterval As Integer = 1

    Dim Locator As WbemScripting.SWbemLocator
    Set Locator = New WbemScripting.SWbemLocator

    Dim Service As WbemScripting.SWbemServices
    Set Service = Locator.ConnectServer()


    Dim WQL As String
    Set InstanceCreationEvent = New WbemScripting.SWbemSink
    WQL = "SELECT * FROM __InstanceCreationEvent WITHIN " _
        & CStr(PollingInterval) & " WHERE TargetInstance ISA 'Win32_Process'"

    Service.ExecNotificationQueryAsync InstanceCreationEvent, WQL
End Sub

Private Sub InstanceCreationEvent_OnObjectReady( _
        ByVal objWbemObject As WbemScripting.ISWbemObject, _
        ByVal objWbemAsyncContext As WbemScripting.ISWbemNamedValueSet)

    Dim Win32_Process As WbemScripting.SWbemObjectEx
    Set Win32_Process = objWbemObject.TargetInstance

    Dim dt As WbemScripting.SWbemDateTime
    Set dt = New WbemScripting.SWbemDateTime
    dt.Value = Win32_Process.CreationDate
    Dim sDate As String
    sDate = Format(dt.GetVarDate(True), "yyyy/MM/dd hh:mm:ss")
    sDate = sDate & Format(".000000", CDec(dt.Microseconds) / CDec(1000000))

    Debug.Print "----------"
    Debug.Print "プロセス名     ["; Win32_Process.Name; "]"
    Debug.Print "プロセスID     ["; Win32_Process.ProcessID; "]"
    Debug.Print "起動元プロセス ["; Win32_Process.ParentProcessID; "]"
    Debug.Print "実行ファイル名 ["; Win32_Process.ExecutablePath; "]"
    Debug.Print "コマンドライン ["; Win32_Process.CommandLine; "]"
    Debug.Print "起動日時       ["; sDate; "]"
End Sub



なお、細かい情報までは必要ではないのであれば、Win32_ProcessStartTrace クラスを
使うという手もあります。こちらを使うと、ポーリング間隔の指定が不要になります。
(システムの監視負荷も若干軽減されるらしい…未検証)


Option Explicit

Private WithEvents InstanceCreationEvent As WbemScripting.SWbemSink

Private Sub Form_Load()
    Dim Locator As WbemScripting.SWbemLocator
    Set Locator = New WbemScripting.SWbemLocator

    Dim Service As WbemScripting.SWbemServices
    Set Service = Locator.ConnectServer()
    
    Dim WQL As String
    Set InstanceCreationEvent = New WbemScripting.SWbemSink
    WQL = "SELECT * FROM Win32_ProcessStartTrace"
    Service.ExecNotificationQueryAsync InstanceCreationEvent, WQL
End Sub

Private Sub InstanceCreationEvent_OnObjectReady( _
        ByVal objWbemObject As WbemScripting.ISWbemObject, _
        ByVal objWbemAsyncContext As WbemScripting.ISWbemNamedValueSet)
    Debug.Print "----------"
    Debug.Print "プロセス名     ["; objWbemObject.ProcessName; "]"
    Debug.Print "プロセスID     ["; objWbemObject.ProcessID; "]"
    Debug.Print "起動元プロセス ["; objWbemObject.ParentProcessID; "]"
End Sub

編集 削除