DOBON.NET DOBON.NETプログラミング掲示板過去ログ

割り込み発生につきまして

環境/言語:[環境(Windows XP 使用言語(VB6)]
分類:[VB6以前]

度々、お世話になります。

割り込み発生につきまして

ハンドル取得は
ハンドル = FindWindow(vbNullString, "キャプション")を
タイマ割り込み(Timer.Interval = 100)周期で行っています。
少しでもCPU使用率負担にならないような方法はありませんでしょうか?。
(たとえば:キャプションを登録しおき、その登録キャプションが認識されたら割り込みが発生)
ご教示願えませんでしょうか。宜しくお願い致します。
■No24956に返信(saさんの記事)
> ハンドル = FindWindow(vbNullString, "キャプション")を
> タイマ割り込み(Timer.Interval = 100)周期で行っています。
> 少しでもCPU使用率負担にならないような方法はありませんでしょうか?。
> (たとえば:キャプションを登録しおき、その登録キャプションが認識されたら割り込みが発生)

  VB6の場合、多分それしか方法が無いかと・・・

  結果、どういう処理をしたいのでしょうか?
  それによっては、別の方法があるかも・・・です。

以上。
オショウ 様

返答下さいましてありがとうございました。

>VB6の場合、多分それしか方法が無いかと・・・
はい、そうですか。

>結果、どういう処理をしたいのでしょうか?
ハンドル取得したウインドウズをマウスポインタにより閉「×」じます。
いつハンドル取得ができるのか決まっていませんのでTimer.Interval = 100間隔
でハンドル取得を繰り返しています。


Private Sub Timer_Timer()

 Dim Pos As POINTAPI
 Dim nRect As RECT
 Dim ハンドル As Long

 ハンドル = FindWindow(vbNullString, "xxxxxx")
 If ハンドル <> 0 Then

Call GetWindowRect(ハンドル, nRect)

 '現在のマウス位置を取得
 Call GetCursorPos(Pos)
 '現在のウィンドウのマウス位置取得
 PosX1 = Pos.x
PosY1 = Pos.y

Ret = SetCursorPos(nRect.Right - 15, nRect.Top + 15) ' 「×」へマウスポインタ移動

'マウスの左ボタンを押す
Call mouse_event(&H2, 0, 0, 0, 0)

'マウスの左ボタンを離す
Call mouse_event(&H4, 0, 0, 0, 0)

Ret = SetCursorPos(PosX1, PosY1) '元の位置にマウスのカーソルを戻す


End If

End Sub
> ハンドル取得したウインドウズをマウスポインタにより閉「×」じます。
> いつハンドル取得ができるのか決まっていませんのでTimer.Interval = 100間隔
> でハンドル取得を繰り返しています。

  見る限り・・・
  起動したプロセスを終了させているだけだと思いますが・・・

  であれば、WMIのプロセス起動監視を使ってやれば、プロセスが
  起動したタイミングでイベントが発生しますので、そのイベント
  の処理中に、起動したプロセスを終了させるようにすればよいだ
  けだと思いますが。

  http://lightbox.matrix.jp/ginpro/patio.cgi?mode=view&no=261&w=700

  VB6なので、VBScriptのコードを参考にしてみて下さい。
  イベントが発生した時点で、FindWindowかEnumWindows使って目的
  のプロセスのウィンドウかどうか判断し、終了処理させれば・・・

※ わざわざ『×』ボタンをクリックすると言うエミュレーションを
  しなくても、取得したウィンドウハンドルにWM_QUITをPostMessage
  するか、プロセスハンドルが取れますので、TerminateProcessで
  終了させれます。

※ WMIで監視する場合もタイマー使って監視しているのですが、VB側
  でタイマー作って監視するよりは楽なので・・・

上記の機能を調べてみて下さい!

以上。
オショウ 様

返答下さいましてありがとうございます。
情報提供をして下さいましてお礼を申し上げます。
>WMIのプロセス起動監視を使ってやれば
>http://lightbox.matrix.jp/ginpro/patio.cgi?mode=view&no=261&w=700
>VB6なので、VBScriptのコードを参考にしてみて下さい。
以上につきましては使用したことがありません。
時間がかかると思われますがご報告致します。
オショウ 様

ご提供下さいました[ VBSCript(同期メソッド)の場合 ] の一部変更追加しました。
>http://lightbox.matrix.jp/ginpro/patio.cgi?mode=view&no=261&w=700
お陰様でWMIで監視してプロセスの監視を終了することができる様になりました。
終了はウィンドウズの「X」閉じるをクリックしますと
'-----------------------------------------------------
   他のアプリケーションがサーバを使用しているため、この操作を
   完了できません。操作を続けるには、「切り替え」ボタンを選択
   して、他のアプリケーションを終了させて下さい。      
      [切り替え]  [再試行]  [キャンセル]    
'-----------------------------------------------------
いろいろと検索して試してみましたが解決することができませんでした。
従いましてタスク マネージャからタスクの終了ボタンをクリックして終了しています。
>※ WMIで監視する場合もタイマー使って監視しているのですが、VB側でタイマー作って監視
VB側でのタイマー作りは分かりませんでした。
●VBSCriptにつきましては良く分かっていませんのでご了承下さい。


Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" _
(ByVal lpClassName As String, _
ByVal lpWindowName As String) As Long

Private Declare Function PostMessage Lib "user32" Alias "PostMessageA" _
(ByVal hWnd As Long, _
ByVal wMsg As Long, _
ByVal wParam As Long, _
ByVal lParam As Long) As Long

Private Sub Command1_Click()

Set objWMIservice = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\.\root\cimv2")
Set objMonitor = objWMIservice. _
ExecNotificationQuery("select * from __instancecreationevent " _
& " within 1 where TargetInstance isa 'Win32_Process'")

Do
    ' 次に新しいプロセスが開始されるまで、待ちます
    Set objProcess = objMonitor.NextEvent

    ' 終了する手段として winver.exe を実行します
    'If UCase(objProcess.TargetInstance.Name) = "WINVER.EXE" Then
        ' Wscript.Echo "プロセスの監視を終了します"
          ' Exit Do
     'end if

      'Wscript.Echo objProcess.TargetInstance.Name
      'Wscript.Echo objProcess.TargetInstance.ExecutablePath
'Loop


'-----------------------この部分を一部追加しました------------------------
     Dim ハンドル As Long
     WM_QUIT = &H12

    ハンドル = FindWindow(vbNullString, "キャプション")
    If ハンドル <> 0 Then

'※ 取得したウィンドウハンドルにWM_QUITをPostMessageするか

    ret = PostMessage(ハンドル, WM_QUIT, 0, 0)  

  End If
Loop
'-----------------------この部分を一部追加しました------------------------

End Sub
> 終了はウィンドウズの「X」閉じるをクリックしますと
> '-----------------------------------------------------
>    他のアプリケーションがサーバを使用しているため、この操作を
>    完了できません。操作を続けるには、「切り替え」ボタンを選択
>    して、他のアプリケーションを終了させて下さい。      
>       [切り替え]  [再試行]  [キャンセル]    
> '-----------------------------------------------------
> いろいろと検索して試してみましたが解決することができませんでした。

  http://hpcgi1.nifty.com/MADIA/VBBBS2/wwwlng.cgi?print+200811/08110018.txt

  ここの最後の魔界の仮面弁士さんのコメントが、参考になるかと。

  次に終了のさせ方ですが、Win32_Processで得られるProcessHandle
  を使用して、TerminateProcess(ProcessHandle)とすれば、よいと
  思いますが・・・

  http://www.anchorsystems.jp/anchor/ashp/netmon/samples/wmi_os.html#Win32_Process.htm

※ 注意
  プロセス生成のイベントを受信しても、画面にウィンドウが表示され
  ていないタイミングがある場合があります。

  起動完了を待って終了させたいならば、プロセス生成のイベント受信
  時にFindWindowでウィンドウの表示を待ち合わせてから終了させるの
  がよいように思います。

※ .NETならもっと楽に記述できるんですが・・・

以上。
オショウ様

返答下さいましてありがとうございました。
>ここの最後の魔界の仮面弁士さんのコメントが、参考になるかと。
魔界の仮面弁士さんのコメントを参考にさせてもらいます。
>http://www.anchorsystems.jp/anchor/ashp/netmon/samples/wmi_os.html#Win32_Process.htm
ご提供下さいました終了のさせ方も参考にさせてもらいます。

後ほどご報告致しますので宜しくお願い致します。
2009/07/16(Thu) 14:07:56 編集(投稿者)

# おぉぅ。思いっきり被ってる。。。まぁいいか。

----
■No24965に返信(saさんの記事)
> ご提供下さいました[ VBSCript(同期メソッド)の場合 ] の一部変更追加しました。
WMI のイベント、たとえば
 __InstanceCreationEvent(作成イベント)
 __InstanceDeletionEvent(削除イベント)
 __InstanceModificationEvent(変更通知イベント)
などを使うのであれば、同期処理ではなく、イベントとして
非同期的に通知させた方が良いとおもいます。


VB6 から WMI のイベントを利用するには、参照設定に
[Microsoft WMI Scripting Library]を追加して、SWbemSink オブジェクトの
OnObjectReady イベントを受け取るようにします。

たとえば、下記の [2008/11/14 21:48:13] のサンプルを使うと、
他のアプリケーションが起動されるたびに、その情報が逐次、
イミディエイトに表示されるようになります。
http://hpcgi1.nifty.com/MADIA/VBBBS2/wwwlng.cgi?print+200811/08110018.txt


> VB側でのタイマー作りは分かりませんでした。
Form に[Timer コントロール]を貼り付け、Interval プロパティをセットしておけば、
定期的に[Timer イベント]が発生しますので、そこで処理を行います。
なお、タイマーは Enabled プロパティ メソッドで開始/停止できます。
追記しました。
すっかり忘れていました。
■24965 / inTopicNo.6)  Re[5]: 割り込み発生につきまして

Wscript.Echo "プロセスの監視を終了します"
を記述しますと実行時エラー '424':オブジェクトが必要です。となります。
よく分かりませんがWscript.Echoにしても駄目でした。
オブジェクトの何が必要か分かりません。
ヒントでもご教示願えますと幸いです。
■No24969に返信(saさんの記事)
> Wscript.Echo "プロセスの監視を終了します"

VBScript の記事を参考にするなら、いきなり VB6 に移植するのではなく、
まずは *.vbs ファイルに記述して、先に実際の動作を確認されてから
移植するべきかと思いますよ。VBScript に関する知識が無いならなおの事。


で。WScript.Echo というのは、画面への表示を意味します。
http://wsh.style-mods.net/topic3.htm

VB6 で言えば、
 Debug.Print "プロセスの監視を終了します"
とか、
 Form1.Print "プロセスの監視を終了します"
とか、
 Form1.Caption = "プロセスの監視を終了します"
とか、
 MsgBox "プロセスの監視を終了します"
とか、
 App.LogEvent "プロセスの監視を終了します"
のようなもの…と思ってもらえば良いかと。
魔界の仮面弁士 様

返答下さいましてありがとうございました。

>WScript.Echo というのは、画面への表示を意味します。
>http://wsh.style-mods.net/topic3.htm
情報提供下さいましてお礼を申し上げます。
下記のアドバイスは大切な順序の指摘をしてもらいました。

>VBScript の記事を参考にするなら、いきなり VB6 に移植するのではなく、
>まずは *.vbs ファイルに記述して、先に実際の動作を確認されてから
>移植するべきかと思いますよ。

>同期処理ではなく、イベントとして非同期的に通知させた方が良いとおもいます。
参照設定に[Microsoft WMI Scripting Library]を追加しました。
>Form に[Timer コントロール]を貼り付け、Interval プロパティをセットしておけば、
>定期的に[Timer イベント]が発生しますので、そこで処理を行います。
WMIで監視するタイマーと普段使用していますタイマー(Timer1_Timer)とは
別なものと勘違いしていました。
ご指摘してもらいました下記については今から行ってみたいと思います。
SWbemSink オブジェクトのOnObjectReady イベントを受け取るようにして
他のアプリケーションが起動されるたびに、その情報が逐次、イミディエイト
に表示。VBScriptが分かるようになりましたら投稿したいと思います。
オショウ様にご指導して頂きましたプロセスのイベントは大変勉強になりました。
ありがとうございました。
■No24971に返信(saさんの記事)
>>>> ※ WMIで監視する場合もタイマー使って監視しているのですが、VB側でタイマー作って監視
>>> VB側でのタイマー作りは分かりませんでした。
>> Form に[Timer コントロール]を貼り付け、Interval プロパティをセットしておけば、
>> 定期的に[Timer イベント]が発生しますので、そこで処理を行います。
> WMIで監視するタイマーと普段使用していますタイマー(Timer1_Timer)とは
> 別なものと勘違いしていました。

ちなみに、「__IntervalTimerInstruction」を使うと、
WMI 側でタイマーを用意する事もできます。蛇足までに。

# 今回使う必要があるかどうかは別として。
魔界の仮面弁士 様

返信下さいましてありがとうございました。
>WMI 側でタイマーを用意する事もできます。
>「__IntervalTimerInstruction」
参考にさせてもらいます。
お知らせ下さいましてお礼を申し上げます。

DOBON.NET | プログラミング道 | プログラミング掲示板