• 締切済み

外部アプリケーションの起動について

Windows 7 32ビット機で、VC++ 2010 Express を利用して Windowsフォームアプリケーションを作成しております。文字コードはマルチバイト文字を選択しました。 アプリケーション自体は、メニュー画面にいくつかのボタンを設け、押下すると所定の実行ファイルが起動するといった非常に簡単なものです。 外部アプリケーションの起動方法ですが、ShellExecute()関数またはCreateProcess()関数を使用するのが一般的との事ですので、今回はCreateProces()関数を使うことにしました。大きな理由は、アプリケーションの実行待機機能が使いたかったためです。 とくに問題なくビルドが完了し実行してみたところ、殆どのアプリケーションは起動できるのですが、ひとつだけ起動できないものがありました。正確には、起動できないというよりは、タスクマネージャーにより起動されていることは確認できるのですが、バックグラウンドで動作するかのように肝心の画面が表示されません。 この状態になると(主プロセスである?)メニュー画面の制御がきかず(応答なし状態)、タスクマネージャーにより強制終了すると、ここでやっと表示されなかった画面が表示されるといった具合です。 何故このような現象が起こるのか、どのようにすれば解決するのかわかりません。誠に恐れ入りますがご教示賜りたく、何卒よろしくお願いいたします。 なお、下記にご参考となり得る情報を記載します。 1. 関数部分の記述は以下のとおりです。 rVal = CreateProcess ((LPTSTR)Fname, NULL, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); Fnameは、フルパスのファイル名がセットされたchar型変数で、ここでは第1引数に記述していますが、第2引数に記述した場合でも結果は同じです。 2. 上記の(LPTSTR)の記述はおまじない的なもので、この記述が無くても挙動は変わりません。どこかの記事で、Windows 7 で動作しない場合の対応と紹介されていましたので。 3. 実行ファイルは、R社のプリンタドライバーのインストーラ(.exe)です。 4. Z社のプリンタドライバーのインストーラやその他のアプリケーション(.exe)は問題なく動作します。 5. メニュー画面には複数のボタンがありますが、対応するロジックはすべて同じで、Fnameにセットされた値のみ異なります。 6. ShellExecute()関数を利用すると、問題なく動作します。

みんなの回答

  • davidfox
  • ベストアンサー率58% (21/36)
回答No.1

何も判りませんが、ShellExecute()関数で成功するならば、違いはウィンドウ絡みを疑います。 自分なら ShellExecute の nShowCmd を変えてみて何が必要か推測します。

nrstyo
質問者

お礼

結局、ShellExecute()関数でパラメータを変えてみましたが、いずれもまったく動作は変わりませんでした。 また、Windows 8.1でも、同様の不具合が発生することもわかりましたが、期待どおりに動作することもしばしばありました。 そこで、CreateProcess()関数でもパラメータのみならず、ソースコード自体もいろいろと変えてテストを行いましたところ、どうやら子プロセスの終了待機に問題があることが判明しました。 即ち、WaitForSingleObject()を使用していましたが、この部分を外すか、直前にダイヤログメッセージを表示してやると本件現象が回避されるのです。 そこでMicrosoft社のWaitForSingleObject()関数解説を読み直してみたところ、最後の方に注意書きがあり、ウィンドウを作成するスレッドではMsgWaitForMultipleObjects()関数等を使用せよという主旨の記述がありました。 早速この部分を修正してみたところ、今度は期待どおりに動作することが確認されました。 なお、何故Windows8.1では動作したのかは現在のところ謎ですので、今後調べてみることにします。 「いろいろ試行してみろ」というアドバイスのおかげをもちまして本件解決に至り、誠にありがとうございました。

nrstyo
質問者

補足

davidfox 様 アドバイスありがとうございました。 手元にWindows 7 32ビットOS機がないので、ShellExcute()関数での試行ができていませんが、来週にでも職場で行ってみます。皮肉にも、実行するプリンタドライバーのインストーラが64ビットOSには非対応なのでエラーとなり、その時点で親プロセスには正常終了の戻り値が返ります。 なお、さらに新しい現象が発生しました。 何と、Windows 8.1 では正常に動作したのです。 Vista はありませんが、XP/Server 2003/2008 などは手元にありますので、こちらでも試してみます。 まずは、ご報告まで。

関連するQ&A

  • 外部アプリケーションの呼び出し方

    現在VC++で環境ウィンドウズ2000でプログラミングを行っています。 メニュー画面上のボタンをクリックすると外部のアプリケーションを呼び出し作業したいと思っています。関数CreateProcessを使うとできるということまではわかったのですが、どうもうまくいきません。 下記のプログラムはメモ帳を呼び出すものでこれはうまくできました。 STARTUPINFO sin; PROCESS_INFORMATION pin; ZeroMemory( &sin, sizeof( STARTUPINFO ) ); ZeroMemory( &pin, sizeof( PROCESS_INFORMATION ) ); sin.cb = sizeof( STARTUPINFO ); sin.dwFlags = STARTF_USESHOWWINDOW; sin.wShowWindow = SW_SHOWNORMAL; if ( !CreateProcess( NULL, _T("notepad.exe C:\\foo.txt), NULL, NULL, FALSE, 0, NULL, NULL, &sin, &pin ) ) { // 起動失敗 } } 実際はデスクトップに置いてあるアプリケーションを呼び出したいと思っています。自分ではアプリケーション名の書き方等が間違っているのではないかと思っていろいろ試したのですが、どうもうまくいきません。 初心者で説明も不十分な点もあると思いますがどうかよろしくお願い致します。

  • CreateProcessでコンソールアプリケーションを起動するには

    コンソールアプリケーションの中で、CreateProcess関数を用いて、自分自身のアプリケーションを起動したところ、次の結果になりました。 ・CreateProcess関数自体は成功する ・タスクマネージャで確認すると自分自身が2つ起動されている ただし、コンソールアプリケーションのウィンドウは1つしか開かず、そのウィンドウを2つのアプリケーションで共有しているかのように動作します(printfによるメッセージが2重に表示されるなど)。 使用言語はVC++ .NET 2008で、デバッガによる動作をさせています。 詳しい方、宜しくお願いします。

  • アプリケーション起動について

    ひろと申します。 クライアントからサーバの共有フォルダにある、他のアプリケーションを オプション付きで起動させるプログラムをVC++で作成したのですが、 クライアントがNTだとうまくいきません。 たとえば、サーバ上にあるapp.exeを「app.exe /i」のような感じで 起動すると、クライアントがwin98の場合はアプリケーションが 表示されるのですが、NTから起動させようとすると、 アプリケーションは表示されません。 また、オプションを外すとアプリケーションは NTでも表示されます。 APIは、WinExec,ShellExecuteEx,CreateProcessで試したのですが 同じ結果でした。 CreateProcess は以下のように設定してます。 ------------------------------------------------------------------ STARTUPINFO si; PROCESS_INFORMATION pi; ZeroMemory(&si, sizeof(STARTUPINFO)); ZeroMemory(&pi, sizeof(PROCESS_INFORMATION)); si.cb = sizeof(STARTUPINFO); si.dwFlags = STARTF_USESHOWWINDOW; si.wShowWindow = SW_SHOWNORMAL; CreateProcess(NULL, "serverpath\\app.exe /i", NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); プロセスの起動は成功していうようです。 クライアントがNTの場合、他に必要な設定があるのでしょうか? よろしくお願いします。

  • 外部アプリケーションの呼び出し方

    現在VC++6.0を使いプログラミングを行っています。 PCの環境はウィンドウズ2000です。 現在アプリケーションを作成しており、メニュー画面にボタンを作りそこから外部のアプリケーションを呼び出し作業したいと考えています。 少し調べたところCreateProcess()を使うことによってできることがわかりました。しかしメモ帳のテキストファイルの呼び出しはですが、現在実際に呼び出したいアプリケーションを呼び出すことがうまくいきません。また呼び出したいアプリケーションは今はディスクトップ上にあります。 またその他何かよい方法があればよかったら教えて頂けないでしょうか? プログラミング初心者なので質問の説明で不十分な点があるかもしれませんがどうぞよろしくお願い致します。

  • ShellExecuteが起動したプロセスのID

    CreateProcessは起動したプロセスのIDをくれますが、ShellExecuteでは分からないものでしょうか。 ShellExecuteExならプロセスのハンドルを受け取ることはできますが、IDは分かりません。 ハンドルから元のIDを割り出す関数でもないですかね。

  • USB アプリケーションの自動起動

    usbにブラウザのexeを入れて差し込んだ瞬間にブラウザが起動すると言う方法は無いのでしょうか。いぜんの記事で「autorun.inf に open=(実行ファイル名) を追加すると、ドライブを入れると同時にアプリケーションを起動することが出来ます。インストーラやメニューが表示されるやつです。実行ファイルはもちろんディスク内にあるファイルです。もし html ファイルをブラウザで表示させたい場合は、 open=rundll32.exe url,FileProtocolHandler index.html の様に記述します。」 とありましたがうまく起動しませんでした。どなたか知識のある方ご教授お願いします。

  • CreateProcess関数について

    ■CreateProcess関数で実行フアイル(.exe)を呼ぶプログラムを作成しています。 ■CreateProcess関数はプロセスを作成すると直に呼出側に戻って来るが、起動したプログラムの実行結果ではない。 ■その様な事を踏まえてプログラム下記にコーテイングしました(概要) ■「呼び出し側」も「呼び出される」もCD-ROM内に有ります。 ■問題はCreateProcess関数で呼んでから、実際に画像が表示されるまでに、時間が掛かる事です。、 ■「質 問」「やりたい事」 CreateProcess関数で呼んでから、実行画面が表示される時間の間に 「その旨のなんだかのメッセージを表示したい」 例えば、Webでのダウンロードやインストールの時の様な... この様な事を、実現するのはどの様にしますか、宜しくお願いします。 STARTUPINFO si; PROCESS_INFORMATION pi; ZeroMemory(&si,sizeof(si)); si.cb=sizeof(si); ZeroMemory(&pi,sizeof(pi)); if(CreateProcess(NULL,(LPTSTR)cmdline,NULL,NULL,FALSE,0,NULL,NULL,&si,&pi)){ CloseHandle(pi.hThread); //CD-ROMから直ぐ表示出来ない場合に備えて //この間で表示に時間を要している事をメッセージ出来ないか? ShowWindow(hWnd,SW_MINIMIZE);//タスクトレイに入れる。 WaitForSingleObject(pi.hProcess,INFINITE); CloseHandle(pi.hProcess); ShowWindow(hWnd,SW_RESTORE););//タスクトレイから出す。 }

  • createprocessで起動させる別.exeをモーダルで起動したい

    createprocessで起動させる別.exeをモーダルで起動したい お世話になります。 VC++6.0 MFCで開発しております。 現在A.exeのあるボタンを押すとcreateprocessでB.exeを起動させるようにしております。 B.exeを起動後、A.exeの画面表示をクリックするとA.exeがアクティブになるのです。 それを、B.exeが終了しないとA.exeがアクティブにならないように変更したいのですがどのようにすればよいでしょうか? 現状は PROCESS_INFORMATION pi; STARTUPINFO si; si.cb=sizeof(si); CreateProcess(実行EXEパス,コマンドライン,NULL,NULL,TRUE,NORMAL_PRIORITY_CLASS,NULL,NULL,&si,&pi); で起動しております。 また、実現不可能というお答えでもいいので教えていただければと思います。 お手数ですが何卒よろしくお願いします。

  • ShellExecuteでエクセルファイルが起動しません。

     今、API関数GetOpenFileNameで「ファイルを開く」コモンダイアログを出して、  そこから選んだファイルのフルパスをテキストボックスに入れています。  さらにそのテキストボックスの中に入ったフルパスをAPI関数ShellExecuteで起動  させようとしているのですが、起動してくれません。  ちゃんとフルパスは入っています。  試しに新しいフォームを作ってShellExecute単独で、直接フルパスを  指定してやってみたところ起動できました。  問題は、パスではなく他の引数でしょうか??  ちなみに第1引数   : me.hwnd      第2引数   : "open"      第3引数   : フルパス      第4・5引数 : vbNullString      第6引数   : SW_SHOW と指定しました。  第4と5の引数はvbNullCharや""と指定してみました。  よろしくお願いします。

  • CreateProcessでアプリが終了しない

    ちょっとした変換ツールを作ろうと思い、ダイアログベースの MFCアプリケーションを作成しました。 OKボタンが押された時にCreateProcess()で子プロセスを 起動して、終了したら結果表示して親プロセスも終了する 様にしようと思ったのですが、結果表示までは正常に 実行されるのですが、親プロセスが終了しません。 恐らくCreateProcess()に渡す引数が悪いのだと思うのですが、 どなたかわかる方がいらしたらご教示願います。 void CMscGenSelectorDlg::OnBnClickedOk() {   STARTUPINFO si;   PROCESS_INFORMATION pi;   ZeroMemory( &si, sizeof si );   si.cb = sizeof si;   ZeroMemory( &pi, sizeof pi );   // 子プロセス起動   CreateProcess(     NULL,                // モジュール名     _T("mscgen.exe -Tpng hoge.msc"),  // コマンドライン     NULL,                // セキュリティ記述子     NULL,                // セキュリティ記述子     FALSE,               // ハンドルの継承オプション     0,                 // 作成のフラグ     NULL,                // 新しい環境ブロック     NULL,                // カレントディレクトリ名     &si,                // スタートアップ情報     &pi);                // プロセス情報   // 子プロセス終了待ち   WaitForSingleObject( pi.hProcess, INFINITE );   CloseHandle( pi.hProcess );   CloseHandle( pi.hThread );   // シーケンスチャート表示   ShellExecute( NULL, _T("open"), _T("hoge.png"), NULL, NULL, SW_SHOW );   // 終了   OnOK(); }

専門家に質問してみよう