Process.WaitForExitが効かない への返答
投稿で使用できる特殊コードの説明。(別タブで開きます。)
以下の返答は逆順(新しい順)に並んでいます。
投稿者 オショウ  (社会人)
投稿日時
2009/12/9 07:49:32
追伸・・・
http://meteoricstream.com/tips/hsp/rundll.html
参考まで
以上。
http://meteoricstream.com/tips/hsp/rundll.html
参考まで
以上。
投稿者 オショウ  (社会人)
投稿日時
2009/12/9 07:47:04
VISTA Ultimate ですが、そのコードですと、確かにインターネットのプロパティが
開いた瞬間、『終了しました』と表示されますネ!
以下のように修正して下さい。
以上。
開いた瞬間、『終了しました』と表示されますネ!
以下のように修正して下さい。
Dim pi As ProcessStartInfo
pi = New ProcessStartInfo
With pi
.FileName = "rundll32.exe"
.Arguments = "shell32.dll,Control_RunDLL inetcpl.cpl"
End With
Using p As Process = Process.Start(pi)
p.WaitForExit()
MsgBox("終了しました")
End Using
以上。
投稿者 brv  (中学生)
投稿日時
2009/12/9 00:54:36
プロセスから攻めても仕方がないということで、ウインドウハンドルを取得してやってみました。
かなりの力技ですが…
WinAPIに頼りすぎですね…
それと、ボタンを押してコントロールパネルが開かないうちにほかのウインドウをアクティブにされると困ります。そっちのウインドウをコントロールパネルと勘違いして、そのウインドウが閉じるまで、フォームがEnabled = Falseの状態になってしまいます。
一応できましたが、もっといい方法があれば教えてください。
かなりの力技ですが…
Public Class Form1
Declare Function GetForegroundWindow Lib "user32.dll" () As IntPtr
Declare Function SetWiondowText Lib "user32.dll" Alias "SetWindowTextA" ( _
ByVal hWnd As IntPtr, ByVal lpString As String) As Integer
Declare Function IsWindow Lib "user32.dll" (ByVal hWnd As IntPtr) As Integer
Declare Function SetActiveWindow Lib "user32.dll" (ByVal hWnd As Integer) As Integer
Private CplWindowHandle As IntPtr
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Process.Start("inetcpl.cpl")
Do
'最前のウインドウを取得
CplWindowHandle = GetForegroundWindow
If CplWindowHandle <> Me.Handle Then
'自分のウインドウでない(コントロールパネル)なら脱出
Exit Do
End If
'スリープをかませる
Threading.Thread.Sleep(400)
Application.DoEvents()
Loop
Me.Enabled = False
WaitForWindowClose(CplWindowHandle)
Me.Enabled = True
End Sub
Private Sub WaitForWindowClose(ByVal hWnd As IntPtr)
Do
If IsWindow(hWnd) = 0 Then
'ウインドウが存在しないなら脱出
Exit Do
End If
'スリープをかませる
Threading.Thread.Sleep(400)
Application.DoEvents()
Loop
End Sub
End Class
WinAPIに頼りすぎですね…
それと、ボタンを押してコントロールパネルが開かないうちにほかのウインドウをアクティブにされると困ります。そっちのウインドウをコントロールパネルと勘違いして、そのウインドウが閉じるまで、フォームがEnabled = Falseの状態になってしまいます。
一応できましたが、もっといい方法があれば教えてください。
投稿者 brv  (中学生)
投稿日時
2009/12/8 01:26:59
いろいろと試行錯誤をしてみました。
プロセスの起動後、5秒ほど待ってからプロセスのメインウインドウのタイトルを取得してみました。
しかし、プロセスがすでに終了していて取得できませんでした。
タスクマネージャで確認したところ、コントロールパネルを閉じるとrundll32.exeが閉じるのがわかりました。
コントロールパネルを開いた5秒後にrundll32.exeを取得しようとしましたが…
メッセージボックスが一つも出ずに終了しました。こちらもUACの関係でrundll32.exeのプロセスが取得できないようです。
結局何もわかりませんでした…
プロセスの起動後、5秒ほど待ってからプロセスのメインウインドウのタイトルを取得してみました。
Using cplProcess As Process = Process.Start("inetcpl.cpl")
Threading.Thread.Sleep(5000)
MsgBox(cplProcess.MainWindowTitle)
End Using
しかし、プロセスがすでに終了していて取得できませんでした。
タスクマネージャで確認したところ、コントロールパネルを閉じるとrundll32.exeが閉じるのがわかりました。
コントロールパネルを開いた5秒後にrundll32.exeを取得しようとしましたが…
Using cplProcess As Process = Process.Start("inetcpl.cpl")
End Using
Threading.Thread.Sleep(5000)
For Each p As Process In Process.GetProcessesByName("rundll32.exe")
If p.HasExited Then
MsgBox("終了しました")
Else
MsgBox("終了していません")
End If
Next
メッセージボックスが一つも出ずに終了しました。こちらもUACの関係でrundll32.exeのプロセスが取得できないようです。
結局何もわかりませんでした…
投稿者 葉月  (社会人)
投稿日時
2009/12/7 06:31:31
7でも想定された動作はしませんね。
VistaからUAC(ユーザーアカウント制御)の導入など、セキュリティに力を入れているの
でその関係かも知れません。
今回のはUAC絡みではないです。
一時的に切って試してみましたが、想定された動作はしませんでした。
ただ、以下のサンプルは正常動作するので、原因はコンパネに絞っていいと思います。
他の方の回答をまってみてください。
■サンプル
VistaからUAC(ユーザーアカウント制御)の導入など、セキュリティに力を入れているの
でその関係かも知れません。
今回のはUAC絡みではないです。
一時的に切って試してみましたが、想定された動作はしませんでした。
ただ、以下のサンプルは正常動作するので、原因はコンパネに絞っていいと思います。
他の方の回答をまってみてください。
■サンプル
Dim info As New ProcessStartInfo()
info.FileName = "notepad.exe"
info.RedirectStandardOutput = True
info.UseShellExecute = False
Using p As Process = Process.Start(info)
p.WaitForExit()
MsgBox("終了しました")
End Using
投稿者 brv  (中学生)
投稿日時
2009/12/7 01:56:31
>実行しているOSはなんでしょうか?
すみません。書くのを忘れていました。
Windows Vista Home Premiumです。
>Windows XPでは再現しませんでした。
そうですか…
うちにはXPもあるのでそっちの環境でも後で試してみます。
ありがとうございます。
すみません。書くのを忘れていました。
Windows Vista Home Premiumです。
>Windows XPでは再現しませんでした。
そうですか…
うちにはXPもあるのでそっちの環境でも後で試してみます。
ありがとうございます。
投稿者 あにす  (社会人)
投稿日時
2009/12/7 01:45:28
Windows XPでは再現しませんでした。実行しているOSはなんでしょうか?
投稿者 brv  (中学生)
投稿日時
2009/12/7 01:30:15
コントロールパネルの項目(インターネットオプション)を表示し、終了するまでフォームを待機させておくコードを書きました。
しかし、インターネットオプションが開いた直後に「終了しました」とメッセージボックスが出ます。
Process.Startの引数をEXEファイルやテキストファイルにした場合は終了した後にメッセージボックスが出ました。メッセージボックスが終了前に出てしまう理由、そしてコントロールパネル終了までアプリケーションを待機させる方法を教えてください。
コードの作成には、以下のページを参考にしました。
http://dobon.net/vb/dotnet/process/opencontrolpanel.html
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Using p As Process = Process.Start("inetcpl.cpl")
p.WaitForExit()
MsgBox("終了しました")
End Using
End Sub
しかし、インターネットオプションが開いた直後に「終了しました」とメッセージボックスが出ます。
Process.Startの引数をEXEファイルやテキストファイルにした場合は終了した後にメッセージボックスが出ました。メッセージボックスが終了前に出てしまう理由、そしてコントロールパネル終了までアプリケーションを待機させる方法を教えてください。
コードの作成には、以下のページを参考にしました。
http://dobon.net/vb/dotnet/process/opencontrolpanel.html
これからも何かあった時はよろしくお願いします。