single.php

Microsoft Excel を別のインスタンスで起動する(Excelの起動オプション)

先回紹介したWaitForSingleObject関数を使ってプロセスを監視する方法で、対象をMicrosoft Excelにした場合に、困ることがあります。例えば、既にExcelが起動していた場合など、バージョンによってはプロセスが統合されてしまいWaitForSingleObject関数が正しく機能しません。

Excel 2013での仕様変更

Excelはバージョン2013からMDIからSDIへの仕様変更がされています。(Excel 2013 からのウィンドウ管理方法変更について – Japan Office Developer Support Blog)

要は、2010までのExcelは1つのアプリ画面内で複数のブック(スプレッドシート)が開いていた表示方法が、2013以降は1つのアプリ画面に1つのブックが表示されるようになりました。

これに伴い、起動した際のプロセスの取り扱いが次のようになっています。

操作 Excel 2010 以前 Excel 2013 以降
プログラムを起動 新規 既存
ファイルを開く 既存 既存
オブジェクト生成(CreateObject) 新規 新規
OLE埋め込みオブジェクト 既存 既存

Excelを起動した場合だけ動作が変更になっています。例えば、既に別のブックが開かれている場合(Excelのプロセスが存在する場合)には、後からExcelを起動した場合でも既に存在するプロセスに統合されて起動するようになります。

WaitForSingleObject

話をプロセス監視に戻すと、WaitForSingleObject関数の場合、パラメタで受け渡されたプロセスのハンドルを使って監視するように設計されています。

例えば、Excelが起動した状態で、次のコードを走らせた場合には正しく動作がしません。

PROCESS_INFORMATION procInfo;
STARTUPINFO startUpInfo;
ZeroMemory(&procInfo, sizeof(PROCESS_INFORMATION));
ZeroMemory(&startUpInfo, sizeof(STARTUPINFO));
startUpInfo.cb = sizeof(STARTUPINFO);
CString sCommandLine = "C:\Windows\Notepad.exe";
CreateProcess(
NULL, sCommandLine.GetBuffer(), 0, 0, FALSE,
CREATE_NEW_PROCESS_GROUP | CREATE_NEW_CONSOLE | NORMAL_PRIORITY_CLASS,
0, 0, &startUpInfo, &procInfo);

sCommandLine.ReleaseBuffer();

::WaitForSingleObject(procInfo.hProcess, INFINITE);
::CloseHandle(procInfo.hProcess);

デバッガーを使って動作を検証すると分かりますが、CreateProcess関数で、CREATE_NEW_PROCESS_GROUP、CREATE_NEW_CONSOLEなどの引数を与えて作成したプロセスは、この時点では新しいオブジェクト(クラス)として発生しています。

その後に、Excelがインスタンス(実体化)する際に仕様に合わせて既存のプロセスに統合されています。

その後の処理でWaitForSingleObject関数で監視を行う訳ですが、オブジェクトとして発生したプロセスが既存のインスタンスに統合する際に、破棄されてしまうため、終了と見なされます。(WaitForSingleObject関数にしてみれば、統合されることなど予想していないので、当然と言えば当然の処理です)

そのため、エラーにもなりません。正常処理として関数は戻り値を返却してきます。

別インスタンスで起動するオプション

Excelには様々な起動オプションがあり、その中に別インスタンスで起動してくれるオプションが使えます。

  説明
/x Excel の新しいインスタンスを(別プロセスで)起動します。

excel.exe /x “c:\My Folder\book1.xlsx”

/e Excel が起動画面を表示せず、新しい空のブックも開かないようにします。

excel.exe /e

その他の起動オプションは以下を参考にしてください。
Microsoft Office 製品のコマンド ライン スイッチ

私が試した場合には、/e オプションでも別インスタンスで起動してくれましたが、解説には、/x オプションで新しいインスタンス(別プロセス)で起動と説明があるので、運用するのであれば、/x を利用するべきです。

実際に先のコードを走らせると、Excelで既に新しいブックが開いている状態でもWaitForSingleObject関数で正しく処理が停止してくれました。

また、オプションはすべてのExcelのバージョンで利用できるわけでは無いので、適用するExcelのバージョンによって使い分ける必要が出てきます。

スポンサーリンク

最後までご覧いただき、ありがとうございます。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です