環境:WinXP VB6sp5
常駐型のプログラムを作成しようとしています。
Windows上でプログラムが起動されたことをトリガに処理をさせたいのですが、SendMessageでよいのでしょうか?
> Windows上でプログラムが起動されたことをトリガに
その起動されたプログラムとは、常駐プログラム自身の事ですか?
それとも常駐プログラムが、他のプログラムの起動を監視するのですか?
あるいは起動された他のプログラムが、常駐プログラムに処理の開始を依頼するのですか?
> SendMessageでよいのでしょうか?
誰が何の処理を行うのかによって、実装も変わってくるかと思います。
常駐アプリの起動時に、何か処理を行いたいのであれば、たとえば
『常駐アプリが、自身の起動時に処理用アプリを起動する。』
といった実装にできるでしょう。
他のアプリの起動状況を調べたいのであれば、WMI のイベント通知を用いて
Win32_Process クラスの変化を捉えるようにするとか。
有難う御座います。
監視するのは他のプログラムになります。
Win32_Processについて調べてみます。
以下の処理で実現できました。
有難う御座いました。
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
もしかして、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