こんにちは。
ご多忙の中、申し訳ありませんが皆さんの知恵をお貸しください。

私はVBは初心者中の初心者なのですが、
あるアプリケーションからEXEをキックし(このEXEは永久ループ)、
ある程度の処理をしたら、キックしたEXEを終了させたいと考えております。

基本的にキックされたEXEがウェイトして自らおちるのではなく、キックした
アプリから落としたいと考えています。

簡単に言えば、UNIXでいうKILLコマンドのような関数はありますかと
言うことです。(プロセスIDを使用して・・・)

ご存知の方がいらっしゃいましたら、教えてください。
宜しくお願い致します。m(_ _)m

A 回答 (1件)

サンプルをどうぞ。


http://www.microsoft.com/JAPAN/support/kb/articl …
しかし、強制終了するはあまりよくないと思います。
WM_CLOSEメッセージを投げる方法をお勧めします。
http://oshiete1.goo.ne.jp/kotaeru.php3?q=157242
    • good
    • 0
この回答へのお礼

ありがとうございました。

参考URL、参考にさせていただきました。

ご多忙の中、ご回答いただきありがとうございました。

お礼日時:2002/03/25 15:43

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

QVB6.0 SHELLで起動したプログラムを終了さしたいのですが

(1)メインプログラムから電卓を実行します。
 Shell("C:\WINNT\system32\CALC.EXE", 1)
(2)メインプログラムで電卓を終了させるにわ、どうすればいいのですか
 教えてください。

Aベストアンサー

(今会社なのですが、、、)サンプルありました。奥深く眠ってました。
Microsoftの終了方法と、定数が違いますが、こちらでも終了ができます。


コメントを見たら、処理の流れがわかると思いますが、処理の流れを記します。

Shellで電卓を起動します。Shell関数は起動したアプリのプロセスIDを返します。
次に Call EnumWindows(AddressOf EnumWinProc, 0&)を実行します。
これはたった一文で、FOR文/DO~LOOP文を使用してませんが、EnumWinProc関数内を何度も実行します。実行回数はWindowsに存在するハンドルの数だけ実行されます。
そしてその関数内で電卓のプロセスと同じハンドルを探し、電卓に終了の命令を送ってます。



EnumWinProc内を詳しく説明します。
GetParentが'0'ゼロの時、未処理としています。

これは何を意味するかというと、フォームだけでなく、フォームの中に存在するボタン、リストボックス、ラベル、それぞれのコントロールにハンドルが存在します。
しかしフォームとその中のコントロールには親子の関係があります。
GetParent(子のハンドル)の時 → '0以外'の数値を返します。基本的にフォーム(親)のハンドルのを返します。
GetParent(フォームのハンドル)の時 → '0'を返します。親が存在しないためです。

電卓にも多くのボタンが存在してます。そのボタンのハンドルはチェックする必要がないのでGoto文で未処理にさせています。必要なのは電卓本体が必要で、GetParentで0を返すものが、チェックの候補となるわけです。

あとは電卓のプロセスと比較し、一致するハンドルを取得するだけです。



Option Explicit

' ウィンドウのプロセスIDとスレッドIDを取得する関数の宣言
Private Declare Function GetWindowThreadProcessId Lib "user32.dll" _
  (ByVal hwnd As Long, lpdwProcessId As Long) As Long

'親ハンドルを取得する関数の宣言
Private Declare Function GetParent Lib "user32" _
  (ByVal hwnd As Long) As Long

'ウィンドウを列挙する関数の宣言
Public Declare Function EnumWindows Lib "user32" _
  (ByVal lpEnumFunc As Long, ByVal lParam As Long) As Long

'ウィンドウにメッセージ定数を送る関数の宣言
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" _
  (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Long) As Long

Public Const WM_CLOSE = &H10

'見つかったウィンドウハンドル
Private FindWinWnd As Long
'探すべきプロセス
Private FindPrs   As Long


Sub Main()
  Dim lngSts As Long

  '初期化を行う
  FindWinWnd = 0
  FindPrs = 0

  'とりあえず電卓を起動と同時に、電卓のプロセスを得る
  FindPrs = Shell("Calc.exe")
  
  'プロセス=0のとき起動失敗
  If FindPrs = 0 Then
    MsgBox "電卓の起動失敗"
    GoTo PGMEND
  End If
  
  'Windowsに存在する全部のハンドルから、電卓のプロセスの一緒のハンドルを探す
  Call EnumWindows(AddressOf EnumWinProc, 0&)
  
  '電卓を終了します。
  If (FindWinWnd <> 0&) Then
    MsgBox "電卓が見つかりませた。終了します。"
    Call SendMessage(FindWinWnd, WM_CLOSE, 0&, 0&)
  Else
    MsgBox "電卓が見つかりませんでした。"
  End If
  
PGMEND:
End Sub

'Windowsの全ハンドルを得ることができる関数
'内部処理は、
'(1)指定のプロセスを探す
'(2)見つかったプロセスのハンドルを記憶
Public Function EnumWinProc(ByVal hwnd As Long, lParam As Long) As Boolean
  Dim lngTrd As Long 'スレッド
  Dim lngPrs As Long 'プロセス
  
  'Trueの間は、Windowsに存在するハンドルを最後まで取得しようとする
  EnumWinProc = True
  
  '子ウィンドウは未処理
  If Not (GetParent(ByVal hwnd) = 0) Then GoTo PGMEND
  
  'スレッドとプロセスを取得する
  lngTrd = GetWindowThreadProcessId(hwnd, lngPrs)
  
  '同じプロセスだとしたら
  If lngPrs = FindPrs Then
    '取得してきたハンドルを記憶
    FindWinWnd = hwnd
    'これ以上のハンドルは取得しないでもいいので、Falseをセット
    EnumWinProc = False
  End If
  
PGMEND:
End Function

(今会社なのですが、、、)サンプルありました。奥深く眠ってました。
Microsoftの終了方法と、定数が違いますが、こちらでも終了ができます。


コメントを見たら、処理の流れがわかると思いますが、処理の流れを記します。

Shellで電卓を起動します。Shell関数は起動したアプリのプロセスIDを返します。
次に Call EnumWindows(AddressOf EnumWinProc, 0&)を実行します。
これはたった一文で、FOR文/DO~LOOP文を使用してませんが、EnumWinProc関数内を何度も実行します。実行回数はWindowsに存在する...続きを読む

Qvbaから他のアプリを終了

エクセルVBAから他のアプリを終了するマクロを書きたいのですが、途中で行き詰ってます。

Sub test()
Dim h As Long
h = FindWindow(vbNullString, "タイトル")
Call SendMessage(h, 0, 0, "ALT+{F4}")
End Sub


FindWindowでハンドルを取得してALT+F4を送ればいいじゃないかと思ってますが
ALT+F4の送り方がわかりません。どなたか教えてください。
また、ほかに良い方法があれば併せてご提案くださると幸甚です。

よろしくお願いします。

--
エクセル2003

Aベストアンサー

そこまでできているのなら下記のように変更して見て下さい。
VB6.0 用のコードをそのまま転記していますがご理解頂けるかと。

Private Sub hwndAcquire()
'ハンドル取得及び終了処理のサブプロシージャ
  Dim hwnd As Long
  Dim ret As Long
  If Len(strClassName) Then
    'クラス名を与えてハンドルを取得
    '起動中ならハンドルが返り、起動していなければ 0 が返る
    hwnd = FindWindow(strClassName, vbNullString)
  ElseIf Len(strCaptionName) Then
    'キャプション名を与えてハンドルを取得する場合
    'strCaptionName = "Microsoft Excel - Book1"  '電卓の場合  "電卓"
    hwnd = FindWindow(vbNullString, strCaptionName)
  End If
  '指定のハンドルに終了のメッセージを送る
  ret = SendMessage(hwnd, WM_CLOSE, 0&, 0&)
End Sub

そこまでできているのなら下記のように変更して見て下さい。
VB6.0 用のコードをそのまま転記していますがご理解頂けるかと。

Private Sub hwndAcquire()
'ハンドル取得及び終了処理のサブプロシージャ
  Dim hwnd As Long
  Dim ret As Long
  If Len(strClassName) Then
    'クラス名を与えてハンドルを取得
    '起動中ならハンドルが返り、起動していなければ 0 が返る
    hwnd = FindWindow(strClassName, vbNullString)
  ElseIf Len(strCaptionName) Then
    ...続きを読む

QExcelVBAにてアプリをタスクマネージャーから強制終了させたいのですが

とある組み込みアドイン(.exe)が働いて素直に(終了しますか?YESNO)ExcelがApplicAtion.Quitしてくれません。

全自動が前提でExcelの終了、OSの再起動、Excelの起動を毎日定時に作動するものを考えています。

組み込みアドインが不便で、制御が出来ないのが実情で困っています。

こいつをタスクマネージャーよりプロセスの終了をして切断したいのですが、
コード記述により自動的に出来ますでしょうか?

Aベストアンサー

コマンドプロンプト にて help を入力すると
「TASKKILL」 コマンドがあります。

これでどうでしょうか ためしにEXCELを強制終了してみました
以下のコマンドを実行

taskkill /F /IM excel.exe

つまり、バッチファイルに このコマンドを指定する。
あるいは VBAから SHELL関数 にて起動すればできるのでは

QプロセスIDの取得方法について

下に同様の質問をしたのですが、削除方法分からない為、再度質問させていただきまし。

VB5.0を利用しています。
VBで書いたexeを実行した際に、そのプロセスID(自分の)は、GetCurrentProcessIdを利用すれば取得できると分かりました。
が、プログラム内でExcelを下記の様にオブジェクトを作成した場合、そのプロセスIDをどうやって取得すればいいのでしょうか?
ご存知の方居ましたら、教えて下さい。

Set ExcelObj = CreateObject("Excel.Application")
ここで起動?されたExcelのプロセスIDを取得したいのですが。

Aベストアンサー

FindWindowなどのキャプションか、クラス名で対象オブジェクトハンドルを取得し、
GetCurrentProcessId関数で、プロセスIDとスレッドIDを取得する方法が一般的。
過去スレにいっぱいサンプルがあります。

スクリプトを使用するなら、以下の方法もあったりする。

でもどちらも複数EXCEL起動時は、考えなければいけない部分多し。

Sub Main()
  Dim ExcelObj As Excel.Application
  
  Set ExcelObj = CreateObject("Excel.Application")
  ExcelObj.Visible = True
  Call DebugHandle
  ExcelObj.Quit
  Set ExcelObj = Nothing
End Sub

Public Function DebugHandle()
  Dim strSQL   As String
  Dim objWk    As Object
  Dim objXlsProc As Object
  strSQL = "SELECT Handle FROM Win32_Process WHERE Name = 'EXCEL.EXE'"
  Set objWk = GetObject("winmgmts:").ExecQuery(strSQL)
  For Each objXlsProc In objWk
    Debug.Print objXlsProc.Handle
  Next
End Function

FindWindowなどのキャプションか、クラス名で対象オブジェクトハンドルを取得し、
GetCurrentProcessId関数で、プロセスIDとスレッドIDを取得する方法が一般的。
過去スレにいっぱいサンプルがあります。

スクリプトを使用するなら、以下の方法もあったりする。

でもどちらも複数EXCEL起動時は、考えなければいけない部分多し。

Sub Main()
  Dim ExcelObj As Excel.Application
  
  Set ExcelObj = CreateObject("Excel.Application")
  ExcelObj.Visible = True
  Call DebugH...続きを読む

QVBで実行中のEXEファイルの情報を取得したい

WindowsXPでVB6.0でプログラムを組んでますが、その中であるEXEファイルを起動するようにしています。しかし、そのEXEが起動している場合は二重起動を避けるようにしたいのです。
使っているPCで起動されているいくつかのEXEから目的のEXEが起動しているかどうかを知りたいです。
FindWindowを使うには開いているファイル名まで変数の中に渡さなければならないため使えません。(開いているファイル名は不明として下さい)
タスクマネージャーの「プロセス」タブのイメージ名に出てくるexeファイル名を取得できればいいのですが、方法をご存知の方おられませんか?

Aベストアンサー

ご参考にしてください。
Sub ProcessID()
  Dim objSet
  Dim obj
  Dim Locator
  Dim Server
  '
  Set Locator = CreateObject("WbemScripting.SWbemLocator")
  Set Server = Locator.ConnectServer
  Set objSet = Server.ExecQuery("Select * From Win32_Process")
  '
  For Each obj In objSet
    MsgBox "プロセス名=" & obj.Caption
  Next
  Set objSet = Nothing
  Set obj = Nothing
  Set Server = Nothing
  Set Locator = Nothing
End Sub

Q起動しているプロセスの確認

2005の.netです。
  If notepadが起動していたら Then
・・・
Else
・・・
End If
というのを作りたいのですが、
タスクマネージャのプロセスから確認するというのでしょうか、
直接、起動しているかの確認をさせたいのですが、
教えてもらえないでしょうか。

Aベストアンサー

Lengthは文字数ではありませんよ

この場合のLengthは GetProcessesByNameメソッドが返す Process型の配列の個数を表します

MSDNなどのレファレンスでメソッドが何を返してくるのかを確認しましょう

MSDNより引用 ---
Process.GetProcessesByName メソッド (String)
が題目

Visual Basic (宣言)
Public Shared Function GetProcessesByName ( _
processName As String _
) As Process()

Visual Basic (使用法)
Dim processName As String
Dim returnValue As Process()

returnValue = Process.GetProcessesByName(processName)

ここまで
宣言の方の as Process() となっている部分に注目します
as の後には返されるデータなどの型名がきます
一番最後に () が付く場合は その型名の配列が返されることになります

関数名を 英単語で分解してみると Get Process es By Name といった具合になります
Get : 何かをもらう
Process : プロセス
es : 複数形
By : なにかによって
Name : 名前

この訳を そのままつなげてみると
何かをもらう プロセス 複数形 何かによって 名前 ・・・
日本語的にすると
『名前によって複数のプロセスを取得する』といえるでしょう

Lengthは文字数ではありませんよ

この場合のLengthは GetProcessesByNameメソッドが返す Process型の配列の個数を表します

MSDNなどのレファレンスでメソッドが何を返してくるのかを確認しましょう

MSDNより引用 ---
Process.GetProcessesByName メソッド (String)
が題目

Visual Basic (宣言)
Public Shared Function GetProcessesByName ( _
processName As String _
) As Process()

Visual Basic (使用法)
Dim processName As String
Dim returnValue As Process()

returnValue = ...続きを読む

QEXCELファイルのカレントフォルダを取得するには?

EXCELファイルのカレントフォルダを取得するには?

C:\経理\予算.xls

D:\2005年度\予算.xls

EXCEL97ファイルがあります。

VBAで
  カレントフォルダ名
(C:\経理\,D:\2005年度\)
を取得する事は可能でしょうか?

CURDIRでは上手い方法が見つかりませんでした。

Aベストアンサー

こんばんは。
Excel97 でも、同じですね。以下で試してみてください。

Sub test()
'このブックのパス
a = ThisWorkbook.Path
'アクティブブックのパス
b = ActiveWorkbook.Path
'Excelで設定されたデフォルトパス
c = Application.DefaultFilePath
'カレントディレクトリ
d = CurDir
MsgBox "このブックのパス   : " & a & Chr(13) & _
   "アクティブブックのパス: " & b & Chr(13) & _
   "デフォルトパス    : " & c & Chr(13) & _
   "カレントディレクトリ : " & d & Chr(13)
End Sub

Q【Excel VBA】マクロでExcel自体を終了させたい

環境:WindowsXP、Excel2003

マクロでエクセルを終了(ブックを閉じて、アプリケーション自体も終了)させたいのですが、以下のコードではアプリケーションが閉じてくれません。

ThisWorkbook.Close
ExcObj.Quit
Application.Quit

どこか悪いところはありますでしょうか?

よろしくお願いします。

Aベストアンサー

普通に考えれば質問者のコードで上手くいきそうですが
hana-hana3さんの回答にもあるようにThisWorkBook.Closeでコード終了となりますので
Application.QuitをThisWorkBook.Closeの前にもってこないといけません。
Application.Quitはそれがあるプロシージャのコードが全て終わるまで
その実行を保留するちょと特別動作をします。

'-------------------------------------
 Application.Quit
 ThisWorkbook.Close
'-------------------------------------
 
 

QVBAで既に開いている別アプリケーションのオブジェクトを得る

 VBAで別のアプリケーションにアクセスするには、CreateObject関数を使ってアプリケーションのオブジェクトを作るようにすると思います。例えば、ワード文書にアクセスするなら次の構文になると思います。
  Set appWord = CreateObject("Word.Application")
  appWord.Visible = True
 しかしこれだと新しいワード文書を作ったり、既存のワードファイルを開いて扱うことしかできません。GetObject関数を用いても同様のようです。既に別ウィンドウで開いているワード文書があって、そこへアクセスするにはどうしたらよいのでしょうか。
 また、同じアプリで複数のファイルを開いている場合には、どうやって目的のファイルへのオブジェクトを得るのでしょうか。(ファイル名などを参照して判断?)

Aベストアンサー

Internet Explorerで開いているWindowを取得することはできますよ。

そのためには、まず開いているWindowを順番に取得し、それがInternet Explorerならばそれをオブジェクトに代入し、ひとつもIEウィンドウが存在しない場合は新規作成(CreateObject)すればいいのです。
Windowを取得するにはShell.Applicationというのを使います。

Dim ObjIE As Object
Dim ObjShell As Object
Dim ObjWindow As Object
Dim WinExist As Boolean

WinExist = False
Set ObjShell = CreateObject("Shell.Application")
For Each ObjWindow In ObjShell.Windows
If TypeName(ObjWindow.Document) = "HTMLDocument" Then
 WinExist = True
 Set ObjIE = ObjWindow
End If
Next
Set ObjShell = Nothing

If Not WinExist = True Then
Set ObjIE = CreateObject("InternetExplorer.Application")
End If

ObjIE.Navigate "http://nantokakantoka.html"
ObjIE.Visible = True


というような感じです。
Wordの場合はわからなくてすみません。
独学なのでもっといい方法があるかもしれないですが。

Internet Explorerで開いているWindowを取得することはできますよ。

そのためには、まず開いているWindowを順番に取得し、それがInternet Explorerならばそれをオブジェクトに代入し、ひとつもIEウィンドウが存在しない場合は新規作成(CreateObject)すればいいのです。
Windowを取得するにはShell.Applicationというのを使います。

Dim ObjIE As Object
Dim ObjShell As Object
Dim ObjWindow As Object
Dim WinExist As Boolean

WinExist = False
Set ObjShell = CreateObject("Shell.Applicatio...続きを読む

QDoEvents関数って何?

こんにちは。

VBAやプログラミングに詳しい皆様に
教えていただきたい質問があります。

cells(1,1)からcells(5000,1)までの値を消去するときに
処理の進行状況を表示するためにuserform上にプログレスバーを表示したいと思います。

そこで下記のようなコードを入力しました。

userform1.show
for i =1 to 5000
cells(i,1)=""
userform1.progressbar1.value=i/5000*100
next i
unload userform1

しかしこれだとuserformの背景が真っ白になってしまい
ラベルの文字も消えてしまいます。
そこで「EXCEL VBA パーフェクトマスター」という本を見たら

for i =1 to 5000
cells(i,1)=""
userform1.progressbar1.value=i/5000*100
DoEvents
next i
unload userform1
と入力すれば解決することがわかりました。

しかし「DoEvents」についてあまり詳しく書いていなかったのでDoEvents関数をヘルプで見ると、
「発生したイベントがオペレーティング システムによって処理されるように、プログラムで占有していた制御をオペレーティング システムに渡すフロー制御関数です。」

と書いてあるのですが正直、書いてあることがよくわかりません。

どなたかDoEvents関数について、
もう少しわかりやすく教えていただけませんか。
それから、最初に書いたコードで実行すると
ユーザーフォームの背景が真っ白になってしまう原因も
教えていただけませんか?

よろしくお願いいたします。

こんにちは。

VBAやプログラミングに詳しい皆様に
教えていただきたい質問があります。

cells(1,1)からcells(5000,1)までの値を消去するときに
処理の進行状況を表示するためにuserform上にプログレスバーを表示したいと思います。

そこで下記のようなコードを入力しました。

userform1.show
for i =1 to 5000
cells(i,1)=""
userform1.progressbar1.value=i/5000*100
next i
unload userform1

しかしこれだとuserformの背景が真っ白になってしまい
ラベルの文字も消えてしまいます。
そ...続きを読む

Aベストアンサー

簡単に言うと、
OS に制御を渡すってことです。(ヘルプそのまんま)
時間が掛かるループ処理などの場合、ループが終わるまで制御は独占されてしまいます。
ですのでループ中は OS や Excel そのものにも再描画をさせる暇さえ与えません。
途中に DoEvents を入れると制御が OS に渡るので、OS は溜まっていた処理をそこで行うことができます。
結果、フォームの再描画などが行われることになります。

注意点ですが、
Private Sub CommandButton1_Click()
  Dim i As Long

  For i = 1 To 50000
    DoEvents
    Cells(i,1) = ""
  Next i
End Sub

Private Sub CommandButton2_Click()
  MsgBox "hoge"
End Sub

っていうフォームのコードがあった場合、
DoEvents を入れることによって、ループ中にユーザーがCommandButton2 を押すことによって CommandButton2 のクリック イベントも動いちゃいます。
CommandButton1 のクリック イベントではループの前に
CommandButton1.Enabled = False
CommandButton2.Enabled = False
を書いてフォーム上の CommandButton を無効にしておき、ループが終わったら
CommandButton1.Enabled = True
CommandButton2.Enabled = True
と書いて CommandButton を有効に戻してください。

これを工夫すれば、CommandButton2 で CommandButton1 のループを途中キャンセルする処理もすることができます。

Private Canceled As Boolean

Private Sub CommandButton1_Click()

  CommandButton2.Enabled = False

  Dim i As Long
  For i = 1 To 50000
    DoEvents

    If Canceled = True Then
      MsgBox "キャンセルしました"
      Exit Sub
    End If

    Cells(i, 1).Value = ""
  Next i
End Sub

Private CommandButton2_Click()
  Canceled = True
End Sub



コードの行頭にあるスペースは見易さのために全角スペースで作成していますので、これをこのままコピペするとエラーになるかもしれません。
コピペするなら行頭の全角スペースを半角スペースに直してください。

簡単に言うと、
OS に制御を渡すってことです。(ヘルプそのまんま)
時間が掛かるループ処理などの場合、ループが終わるまで制御は独占されてしまいます。
ですのでループ中は OS や Excel そのものにも再描画をさせる暇さえ与えません。
途中に DoEvents を入れると制御が OS に渡るので、OS は溜まっていた処理をそこで行うことができます。
結果、フォームの再描画などが行われることになります。

注意点ですが、
Private Sub CommandButton1_Click()
  Dim i As Long

  For i = 1 To 50000
...続きを読む


このQ&Aを見た人がよく見るQ&A

人気Q&Aランキング

おすすめ情報