- PR -

別アプリを起動した後、プログラムの終了ができない

投稿者投稿内容
いわた
会議室デビュー日: 2005/10/07
投稿数: 16
投稿日時: 2006-03-28 17:14
WindowsXP SP2
C#(.NET Framework 1.1)

いわたと申します。いつもお世話になっています。
ちょっと不可解な現象を見つけたのですが、どなたか何かご存知ないでしょうか?

現象というのは、以下の通りです。

System.Diagnostics.Processクラスを使用して、C#のプログラムから別のアプリを起動しています。
※起動するアプリのパスを直接指定するのではなく、オープンするファイル(EXCELなら、〜.xls等)を指定しています。

その後、プログラムを終了しようとすると、起動されたアプリの側の状態によって、プログラムが正常に終了しないことがあります。(画面は消えるが、タスクマネージャにプロセスが残る)


EXCELを使用して再現させることが出来たので、以下に手順を示します。

1.EXCELのファイルを作成し、適当にマクロを登録する。

2.C#でWindowsアプリケーションを作成する。

3.メインフォームにテキストボックス(textBox1)、ボタン(button1)を配置する。

4.button1のクリックハンドラに、以下のコードを追加する。
コード:
private void button1_Click(object sender, System.EventArgs e)
{
	using ( Process p = new Process() )
	{
		p.StartInfo.FileName = textBox1.Text;
		p.Start();
	}
}



5.作成したプログラムを起動し、テキストボックスに1で作成したEXCELファイルのパスを入力して、ボタンをクリックする。
→ EXCELが起動し、セキュリティ警告ダイアログ(マクロを有効にするか無効にするかを選択するダイアログ)が表示される。

この状態で起動元のプログラムを終了すると、タスクマネージャにプロセスが残ってしまいます。
EXCEL側でセキュリティ警告ダイアログを閉じた後なら、正常に終了します。
※プログラムを終了した後にセキュリティ警告ダイアログを閉じても、プロセスは消えません。

この動作は不具合なのでしょうか?それとも外部アプリの起動方法がおかしいだけで、何か回避手段があるのでしょうか?

ちなみに、System.Diagnostics.Processクラスを使用するのではなく、ShellExecute APIを使用した場合も、同様の現象が発生しました。
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2006-03-28 17:41
引用:

いわたさんの書き込み (2006-03-28 17:14) より:

それとも外部アプリの起動方法がおかしいだけで、


別におかしくはないですよ。

引用:

何か回避手段があるのでしょうか?


Excel COM Interop を使ってセキュリティ ダイアログ自体を表示しないとか。

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
いわた
会議室デビュー日: 2005/10/07
投稿数: 16
投稿日時: 2006-03-28 18:39
じゃんぬねっと様

ありがとうございます。

起動方法自体は問題ないということですね。

Excel COM Interopを使用するとのことですが、Excelというのは一例でして、他のアプリでも同じ問題が起きています。
ドキュメント管理系のプログラムなので、そもそも開かれるファイルの種類はなんでもありなんです。

例えば、ShellExecuteするだけのプログラムをCか何かで作って間に挟むとか、あまりかわいくない回避策は色々思いつくのですが、出来ればスマートに解決する方法は無いかと思いまして、ご相談させていただいてます。
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2006-03-28 18:51
引用:

いわたさんの書き込み (2006-03-28 18:39) より:

Excel COM Interopを使用するとのことですが、Excelというのは一例でして、他のアプリでも同じ問題が起きています。


たとえば、どんなアプリケーションでしょうか?
ちょっと色々試行してみます。

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
いわた
会議室デビュー日: 2005/10/07
投稿数: 16
投稿日時: 2006-03-28 19:25
じゃんぬねっと様

こちらで確認しているのはあまり一般的なアプリではないので、試していただくというのは難しいと思います。
一応、SolidEdgeという3次元CADソフトなのですが。


1.OLEオートメーションのサーバとして、外部から操作できる仕組みを持っている。

2.ファイルのロード完了前に、何らかのダイアログなどが表示されてInputIdle状態になる。

というのが共通点なので、WordやPowerPointなどでも2番の条件を満たすようなデータであれば再現するかも知れません。
(Excelファイルにマクロを追加、というのは疑わしい要素が多すぎて例としてはちょっと不適切だったかも知れないですね。)
いわた
会議室デビュー日: 2005/10/07
投稿数: 16
投稿日時: 2006-03-28 19:54
自己レスです。

引用:

WordやPowerPointなどでも2番の条件を満たすようなデータであれば再現するかも知れません。



今試してみましたが、Wordだと以下のオペレーションで再現しました。
PowerPointでは同じことをしても再現しませんでした。

1. 適当なdocファイルを作成して、別の端末でそのファイルを開いておく。

2. このプログラムを使用して、そのファイルを開く。
→「使用中のファイル」ダイアログが表示される。
この状態で、プログラムを終了してもプロセスは消えない。

また、プログラムにメインメニューを追加して、ショートカットキーを割り当てると、ExcelやWordでダイアログが表示されている間はショートカットキーが効かなくなるようです。

やれやれ。

Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2006-03-29 22:47
 そういう動きで正解、だと思います。

 モーダルダイアログが表示されているので、COM の参照が開発者の意図通りに解放されないのだと思います。
 これに該当すると思います。
引用:

Office のサーバーサイド オートメーションについて より:
デスクトップとの対話性 : Office アプリケーションは、対話型デスクトップで動作することを想定し、場合によっては、何らかのオートメーション関数を適切に実行するには、アプリケーションを表示する必要がある場合もあります。Office アプリケーションは、予期しないエラーが発生した場合、または関数を完了するために未指定の引数が必要な場合には、ユーザーに操作内容を確認するモーダル ダイアログ ボックスが表示されるように設計されています。非対話型デスクトップでのモーダル ダイアログ ボックスは閉じることができず、これが原因となり、そのスレッドが応答しないままになります (ハング)。コーディングを工夫することで、このような状態に陥る可能性を軽減することはできますが、完全に防ぐことはできません。この事実のみからも、サーバーサイド環境からの Office アプリケーションの実行は危険であり、このような実行はサポートされません。

いわた
会議室デビュー日: 2005/10/07
投稿数: 16
投稿日時: 2006-03-30 10:11
Jitta様

ありがとうございます。

リンク先を見てみたのですが、要するに
「サーバ側でメッセージボックスとか出ると誰もOK押せないからそのまま固まっちゃうよ」
という話だと思ったのですが、今回の件にも影響を及ぼすのでしょうか?

また、ShellExecuteでキックするだけでもCOMの参照を掴んでしまうものなのでしょうか?
それだとC言語のアプリからComInitializeをコールしなくてもShellExecuteが使えるのは
なぜ?内部で勝手に呼んでるの?、とか新たな疑問がわくのですが。
でも発生している現象からすると、確かにCOMの解放関係があやしそうではありますね。

スキルアップ/キャリアアップ(JOB@IT)