VBで別EXEの起動を判定するには?


ナナ  2004-01-23 10:56:39  No: 81677  IP: [192.*.*.*]

基本的な事かもしれませんが、教えて下さい。
現在VB6で開発をしています。OSはXPです。
実現したいことは、2つのEXEを使用おり、
一方のEXE(仮にEXE:A)からもう一方(仮にEXE:B)をShellで起動させ、
起動が確認出来たらAのEXEを落としたいのですが、
どの様に判定したらいいかわかりません。
どなたか教えて下さい。よろしくお願いします。

編集 削除
ムラタ  2004-01-23 11:35:55  No: 81678  IP: [192.*.*.*]

Dim RetVal
RetVal = Shell("XXXXXXXXXXXXXX.EXE")

プログラムの実行に問題が発生した場合は、RetValに0が帰ってきます。
なので

if Shell("XXXX\B.EXE") <> 0 then unload me

で解決できるでしょうか?

編集 削除
ナナ  2004-01-23 11:50:01  No: 81679  IP: [192.*.*.*]

少し私の説明不足な部分がありました。すみません。。
ムラタさんに教えて頂いた方法でも解決が出来なかったのですが、
どのような問題を解決したいかと言いますと、
呼び出したEXEが表示される前に呼び出しもとのEXEが
デスクトップ上より消えてしまい、一瞬の事ですが、
デスクトップが見えてしまう(どちらのEXEも表示されていない)
のを解決したいのです。。

編集 削除
吉野  2004-01-23 12:23:17  No: 81680  IP: [192.*.*.*]

これで解決できるでしょうか。
Shell "ProgramFile.exe",vbNormalFocus

編集 削除
吉野  2004-01-23 12:26:14  No: 81681  IP: [192.*.*.*]

書き方が悪かったので再度、
ムラタさんのコードと同じですが、
Shell関数に引数を追加しています。
If Shell("ProgramFile.exe",vbNormalFocus) <> 0 Then Unload Me

編集 削除
ムラタ  2004-01-23 13:05:21  No: 81682  IP: [192.*.*.*]

ナナさん了解です。
付け足してみました。

Dim RetVal

'フォーカスを持たずに起動させる。
RetVal = Shell("ProgramFile.exe", vbNormalNoFocus)

'正常起動時に、アクティブにする。
If RetVal <> 0 Then AppActivate RetVal: Unload Me

ちなみに、テストしてみて上手くいきました。

編集 削除
ナナ  2004-01-23 13:10:35  No: 81683  IP: [192.*.*.*]

吉野さんの方法も試してみましたが、うまくいきませんでした。
以前VB5で開発されていたコードがあり、

Dim TIMEX, RcX, RcY As Long

RcX = Shell("ProgramFile.EXE " & PARM, 3)
TIMEX = Timer
RcY = FindWindow(vbNullString, "Form1")
Do While (RcY = 0 And Timer < TIMEX + 300)
    RcY = FindWindow(vbNullString, "Form1")
Loop

このような形で書かれていたのですが、
これをそのままVB6にのせて使用すると、
EXE起動に時間がかかりすぎたり、固まってしまったりします。
どのように回避したらいいかわからず困っています。

編集 削除
ナナ  2004-01-23 13:11:50  No: 81684  IP: [192.*.*.*]

ムラタさん。ごめんなさい。
入れ違いでカキコしてしまいました。
今から試してみます。

編集 削除
ナナ  2004-01-23 13:17:31  No: 81685  IP: [192.*.*.*]

さっそくムラタさんの方法で試してみたのですが、
やはり両EXEとも消えてしまう瞬間があります。。
また、モジュールレベルで試すとうまくいっているのですが、
EXEで実行するとうまくいかないんです。。
同じEXEで他端末で試すとうまくいったのですが、
どうしてうまくいかないのか原因がわかりません((+_+))

編集 削除
ムラタ  2004-01-23 13:43:28  No: 81686  IP: [192.*.*.*]

グハッ><
そうですか〜

Unload Me 内でいろいろやってますか?

編集 削除
ナナ  2004-01-23 13:47:17  No: 81687  IP: [192.*.*.*]

オブジェクトの開放くらいですが・・・

編集 削除
吉野  2004-01-23 18:13:05  No: 81688  IP: [192.*.*.*]

ムラタさんのコードに追加

Dim RetVal

'フォーカスを持たずに起動させる。
RetVal = Shell("ProgramFile.exe", vbNormalNoFocus)

'正常起動時に、アクティブにする。
If RetVal <> 0 Then AppActivate RetVal: DoEvents: Unload Me
                                       ^^^^^^^^^^

編集 削除
ナナ  2004-01-26 09:51:07  No: 81689  IP: [192.*.*.*]

吉野さんありがとうございます。
試してみたのですが、
やはりうまくいきませんでした。。

FindWindowを使う方法も試しているのですが、
どちらの方法でもうまく解決出来ません((+_+))

編集 削除
吉野  2004-01-26 12:27:40  No: 81690  IP: [192.*.*.*]

実際に動かしていないので間違っているかもしれませんが、参考までに。

呼び出される側ExeのForm_Load若しくは、Form_Initializeに
処理時間がかかるような作業をしていませんか?
取りあえず、強制的に表示するようにしてみては如何でしょうか。
卑怯な手かもしれませんが…

呼び出される側Exe
Form_Load イベントに Me.Show を追加。(コードの一番上に追加します)

後は、これまでと同様、Shellを使って呼び出してみます。

呼び出し側Exe
Dim lngReturnCode As Long
lngReturnCode = Shell("ProgramFile.exe", vbNormalFocus)
If lngReturnCode <> 0 Then 
  Unload Me
End If

これでも表示されない場合は、
呼び出される側Exeの Me.Show の後に、
DoEvents 若しくは、Me.Refreshを追加してみてください。

編集 削除
ブラックリスト  2004-01-26 16:43:50  No: 81691  IP: [192.*.*.*]

もしBもプログラムできるなら、
AからBを立ち上げ、BからAを終了させるようにしたらどうでしょう。

AのフォームのKeyPreviewをTrueにしておき、
最新の一定文字数を常にバッファに入れるようにし、
バッファとキーワードが一致したらENDするようにプログラムしておく。
そしてBをノーマルフォーカス付で立ち上げる。
Bは立ち上がったら先ずshowで表示し、
AをAppActivateしてキーワードをSendkeysで送る。

編集 削除
ブラックリスト  2004-01-26 16:46:00  No: 81692  IP: [192.*.*.*]

実際にXP上でVB6で作成し、EXEファイルでテストしたところ、
上手くいきましたYO。

編集 削除
ナナ  2004-02-03 14:55:37  No: 81693  IP: [192.*.*.*]

サイト復活したんですね☆

ブラックリストさんありがとうございます。
早速簡易EXEで試そうとしたのですが、
ロジックをうまく組むことが出来ませんでした。
A側とB側のサンプルコードを書いて頂けないでしょうか?
よろしくお願いしますm(__)m

編集 削除
ねろ  2004-02-03 16:46:44  No: 81694  IP: [192.*.*.*]

こんな大げさなことをしてもいいなら
呼び出す側のプログラムは自分のハンドルを呼び出されるプログラムに渡す。

Dim s As String
Dim r 
s = "B.exe" & " " & CStr(Me.hWnd)
r = Shell(s, 1)

呼び出されるプログラムは
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 Declare Function FindWindow Lib "user32" Alias _
"FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Const WM_CLOSE = &H10

Private Sub Form_Load()   
    Me.ZOrder 0
    r = PostMessage(Val(Command), WM_CLOSE, 0, ByVal CLng(0))
End Sub

こんな方法も。

編集 削除
ブラックリスト  2004-02-06 13:52:05  No: 81695  IP: [192.*.*.*]

Project1にForm1とCommand1を準備してください。
Project2にForm2を準備してください。
それで、以下のコードをコピペしてください。
プロパティ等はなにも触らなくて良いです。
コンパイルして実行ファイルを同じフォルダにおけば動作します。

Project1のコード

Dim KeyBuf As String        'キーバッファ
Const txt = "END"           '終了指定文字列なんでもかまいません
Const num = 3               '終了指定文字列の文字数

Private Sub Form_Load()
    Form1.Caption = "Project1"  'キャプションを指定します。後でウィンドウの指定に使います。
    Form1.KeyPreview = True     '他のコントロールがあるなら、この指定をしてください。
    Form1.Left = 0              '以下は特に必要ないけど、切り替えが上手くいってるのが見易い。
    Form1.Top = 0
    Form1.Width = Screen.Width
    Form1.Height = Screen.Height
End Sub

Private Sub Form_KeyPress(KeyAscii As Integer)
    KeyBuf = Right(KeyBuf + Chr$(KeyAscii), num)    '押された最後のnum個の文字を保存する
    If KeyBuf = txt Then End                        '文字列が終了文字列と同じなら終了
End Sub

Private Sub Command1_Click()
    Shell "project2.exe", vbNormalFocus     '二つ目のアプリを起動します。
End Sub

Project2のコード

Private Sub Form_Load()
    Form2.Caption = "Project2"      '分かり易いようにキャプションを変えました。
    Form2.Left = 0                  '見易いようにしました。
    Form2.Top = 0
    Form2.Width = Screen.Width
    Form2.Height = Screen.Height
    Me.Show                         'フォームを表示します
    
    AppActivate "Project1"          '最初のウインドウのキャプションを指定します。
    SendKeys "END"                  '終了指定文字を送ります。
End Sub

編集 削除
ブラックリスト  2004-02-06 14:06:23  No: 81696  IP: [192.*.*.*]

BからAを終了させるという考え方はねろさんも同じですね。
この場合は、APIを使った方がスマートですね。

SendKeyを使う方法は、終了だけでなくBからAを色々コントロールできるので、色々な応用ができます。参考になればいいね。

編集 削除