web-dev-qa-db-ja.com

複数のOfficeドキュメントを開いたときの複数のインスタンス

Officeのバージョン16.0.8625.2121以降(WordおよびExcelでテスト済み)-エクスプローラーで複数のドキュメントを選択し、Enterキーを押してそれらを開くと、前回選択したドキュメントの数までインスタンスが表示されます。

再現するには、次の手順を実行します。

  • マシン上の任意の場所に2つの空のExcelワークブックを作成します
  • それらの2つのファイルを選択します
  • Enterキーを押す
  • タスクマネージャーを確認すると、Excelの2つのインスタンスが表示されます

16.0.8625.2121より前のバージョンでは、インスタンスは1つしかありませんでした。

テスト済み

  • 16.0.4266.1003-使用していたかなり古いイメージで、新しいバージョンに更新した

    officec2rclient.exe /update user updatetoversion=16.0.xxxx.yyyy
    

これらの新しいビルドで段階的に再テストしました:

  • 16.0.8431.2094
  • 16.0.8431.2107
  • 16.0.8528.2139
  • 16.0.8528.2147

明らかな説明がされる前に、DisableMergeInstanceは設定されていません。

それは新しい「機能」ですか、それともバグですか?バグだと思います。

それを回避する方法はありますか?

詳細情報:

この動作を(常に最新バージョン)でテストしました

  • Windows 7 + Office 2016-誤動作が発生する
  • Windows 10 + Office 2016-誤動作が発生する

また、古いバージョンのOfficeをチェックして、これがOffice 2016のものであることを確認しました

  • Windows 8 + Office 2013-起こりません
  • Windows 7 + Office 2010-起こりません
  • Windows 10 + Office 2010-起こりません
  • Windows 10 + Office 2013-起こりません
9
Rand Random

説明を繰り返し述べた場合はお詫びしますが、この問題は非常に複雑であるため、読者にとって状況に応じて理解できるようにしました。

これがバグか意図したものかはわからないかもしれませんが、ハード引数の代わりにDDEメッセージを作成することにより、Dynamic Data Exchangeプロトコル(DDE)を使用して「同じ」インスタンスで強制的に開くことができます "% 1 "は、そのインスタンスがファイルの実行時に開くファイルを指します。 (ただし、DDEはハード引数でも使用されます)。

この場合、DDEメッセージは、プログラムにファイルを開くように指示するために使用されます。実行されるすべてのファイルについて、実際には毎回新しいインスタンスが作成されます。しかし、DDEプロトコルが使用されると、最初にインスタンスが既に作成されているかどうかが調べられ、作成されている場合はDDEメッセージが最初に見つかったインスタンスにリレーされて終了するため、すべてのファイルが単一インスタンスで瞬時に開かれているように見えます。

憶測

複数のインスタンスで開かれるファイルの問題は、別のインスタンスが呼び出されているときに単一のインスタンスがすでにロードされている量に関係している可能性があります。最初のインスタンスと2番目のインスタンスの実行時間の差の傾向は、実行間の時間が増加すると1つのインスタンスを生成する傾向があり、減少すると2つのインスタンスを生成する傾向があります。これは、別のファイルが実行された場合、同じインスタンスで新しいファイルを開くには、最初のインスタンスが読み込まれるか、「準備ができている」必要があることを示しています。

ファイルパスがプログラムの引数として使用される場合、この傾向に従うだけのようです。

  • Word 2016
  • エクセル2016

最初のインスタンスを超えてインスタンスを作成するための引数として使用する場合、最初のインスタンスの準備ができている場合(または最初でないインスタンスが準備ができていることがわかっている場合)、最初でないインスタンスは、引数をDDEメッセージとして最初のインスタンスにリレーできるようです。

ただし、プログラムを実行し、DDEメッセージを使用してファイルを開く場合、最初のインスタンスが引数を介してDDEメッセージを受け入れる準備ができているかどうかに関係なく、DDEプロトコルにすぐに従うようです。最初のインスタンスの準備ができているかどうかは、非最初のインスタンスが準備ができていると見なすかどうか、またそうでない場合は最初のインスタンスにDDEメッセージを送信しないことに依存します。これは、引数を介して開いたときにのみ発生するようです。 。 「最初」を「準備完了」または「存在しない」と見なさない最初の推測は、(最初​​からではない)DDEメッセージが最初に受け入れられるという事実によって示唆されています。引数の連結 "%1"; DDEメッセージを介して開くように指示されます。

そのため、私の推測は次のとおりです。これらのアプリケーションのコードは、別のインスタンスが「準備完了」かどうかを判断するためにあいまいな方法を使用し、準備ができている場合は、引数が使用されるときにDDEプロトコルを使用します。これは、別のインスタンスに送信するかどうかを決定するためにDDEプロトコルを受信したときとは異なる方法を使用しているようです。実際には、疑似コードは次のようになります。

_if(argrument.wasUsed()){
    // Office's obscure condition
    if(Office.thinksInstanceIsReady(anotherInstance)){
        // Use DDE Protocol
        if(anotherInstance.exists()){ // already knew that
            sendDDEmessage(anotherInstance);
            exitThisInstance();
        }
    } else {
        selfFollowDDEmessage(); // Leave open this instance
    }
if(givenDDEMessage()){
    // Use DDE Protocol
    if(anotherInstance.exists()){
        sendDDEmessage(anotherInstance);
        exitThisInstance();
    } else {
        selfFollowDDEmessage();
    }
}
_

これがバグなのか、それとも何らかの理由で不明瞭であることが意図されていたのかをプログラマが知らせずに判別する方法はありません。

決議

特定のファイル拡張子の実行を調整して、実行中のファイルのファイルパス( "%1")を引数として送信せず、実行中のプログラムにDDEメッセージの内容を実行するよう指示します。ファイルを開くリクエストが含まれています。ファイルが存在する場合、それを使用し、存在しない場合はそれを中継します。投機的には、ファイルパスへの引数が使用されている場合、別のインスタンスが「準備完了」と見なされるように、これらのアプリケーションのあいまいな要件をバイパスします。

これらは、xに置き換えられるクラスキーに関連付けられたすべてのファイル拡張子です。

Wordの場合

_FILEEXT          CLASS NAME (x)
 .doc*           Word.Document.8
 .docm†    Word.DocumentMacroEnabled.12
 .docx*         Word.Document.12
 .dot            Word.Template.8
 .dotm†    Word.TemplateMacroEnabled.12
 .dotx†         Word.Template.12
 .odt        Word.OpenDocumentText.12
 .rtf†             Word.RTF.8
 .wbk             Word.Backup.8
 .wiz             Word.Wizard.8
 .wll             Word.Addin.8
_

Excelの場合

_FILEEXT             CLASS NAME (x)
 .csv*                Excel.CSV
 .ods       Excel.OpenDocumentSpreadsheet.12
 .slk                 Excel.SLK
 .xla                Excel.Addin
 .xlam†        Excel.AddInMacroEnabled
 .xld                Excel.Dialog
 .xlk                Excel.Backup
 .xll                 Excel.XLL
 .xlm              Excel.Macrosheet
 .xls*              Excel.Sheet.8
 .xlsb†     Excel.SheetBinaryMacroEnabled.12
 .xlshtml           Excelhtmlfile
 .xlsm†       Excel.SheetMacroEnabled.12
 .xlsx*             Excel.Sheet.12
 .xlt†             Excel.Template.8
 .xlthtml          Excelhtmltemplate
 .xltm†        Excel.TemplateMacroEnabled
 .xltx†             Excel.Template
 .xlw               Excel.Workspace
 .xlxml               Excelxmlss
_

*最低限必要な最も重要な/共通のファイル拡張子。主観的。

†最低限必要な二次的な最も重要な/共通のファイル拡張子。主観的。

これらのリストはコマンドラインで複製できます:_assoc | findstr Word_ Wordを正式な短縮名(大文字と小文字を区別)に置き換えます。

あなたがそれを必要だと感じた場合、あなたはそれらすべてを行うことができます。もっとやりたいことがあれば、私が提供するオプションの手順を実行することをお勧めします。これにより、必要な作業が減ります。

以下のすべてのレジストリキーについて、xを選択した対応するクラスに置き換えて、次の手順に従う必要があります。

  • _HKEY_CLASSES_ROOT\x\Shell\Open_
  • _HKEY_CLASSES_ROOT\x\Shell\OpenAsReadOnly_

(例:_HKEY_CLASSES_ROOT\Excel.Sheet.12\Shell\Open_)

もう一度、OpenAsReadOnlyキーはオプションです。これは、ファイルが実行されたときに読み取り専用になるように準備されます。

ちょっとした注意-バックアップ

変更前のレジストリ値を最もよく覚えるために、キーブランチ_HKEY_CLASSES_ROOT_を右クリックし、コンテキストメニューの下の[エクスポート]をクリックして、登録ファイルを特定の場所に保存します。 Doc Brownが「戻る必要がある」と言った場合は、レジストリキーを実行し、指示に従ってインポートするだけです。

または、これを実行して、commandの値とクラス名を思い出して、次のような小さな間違いを修正することもできます。

_assoc>>fileexts.txt_を使用してフィルターできる_type fileexts.txt | findstr Word_

_ftype>>classnames.txt_を使用してフィルタリングできます_type classnames.txt | findstr Word_

指示

これらは、あなたが望むように、上にリストされたすべてのキー値に対して従われます。

お気に入りのレジストリエディタまたはregeditに移動して、変更するクラスに移動します。

commandというキーを入力し、_(Default)_値を右クリックして、コンテキストメニューの[変更]をクリックします。

現在設定されているのは_ftype | findstr Word_によって実行されたものでなければなりません

これを変更して、値の最後にある直接引数を削除しますincludedスペース:

  • _"C:\Program Files\Microsoft Office\Root\Office16\Excel.EXE"_
    (Excel 64ビット用)
  • _"C:\Program Files\Microsoft Office\Root\Office16\WINWORD.EXE"_
    (Word 64ビット用)
  • "C:\Program Files (x86)\Microsoft Office\Root\Office16\WINWORD.EXE"
    (Word 32ビット用)
  • "C:\Program Files (x86)\Microsoft Office\Root\Office16\Excel.EXE"
    (Excel 32ビット用)

ddeexecキーの横にあるcommand(存在しない場合はキーを作成)というキーに入力し、_(Default)_値を右クリックして、[変更]をクリックします"コンテキストメニューで、次のように値を設定します。

  • [REM _DDE_Direct][FileOpen("%1")]-(Wordの場合)
  • [open("%1")]-(Excelの場合)

ddeexecの下にtopicという新しいキーを作成し(存在しない場合)、_(Default)_値を右クリックして、コンテキストメニューの[変更]をクリックし、 systemになる値(まだの場合)。

変更後、レジストリにこれらの変更を作成した後、管理者特権のコマンドプロンプトまたはシェルでこれを実行してShell32.dllを更新する必要がある場合があります。

_regsvr32 /i Shell32.dll_

これは、Windows 10 Office 2016バージョン16.0.8625.2127でテストされています

代替ショートカット

また、ファイル拡張子のキー(_HKEY_CLASSES_ROOT\.xlsx_など)に移動して、「(デフォルト)」の値を単一のクラスに変更することもできます。このアプローチを使用すると、複数のファイル拡張子を同じクラスの値にポイントできます( _Excel.Sheet.12_)など、DDEメッセージでそのクラスを一度変更するだけで済みます。これを行う場合は、そのレジストリブランチ内のクラス名のすべての繰り返しの名前も変更する必要があります。ただし、この方法は簡単に壊れる可能性があるためお勧めできません。時間を節約するためにすべてのファイル拡張子を使用する場合は、この方法を実行する必要があります。

傍注:

_/o_引数はURLの引数であり、渡されることはほとんどないため、この機能が失われることは大きな問題ではありません。ただし、必要に応じて、_(Default)_値を調整するときに、引数のこの部分をオンのままにしておくことができます。

これは非常に投機的で未完成であるため(WordとExcelだけではなかった場合)、これをコミュニティーWikiにすることを検討しています。これについての意見をコメントしてください。

6
El8dN8

@ El8tedN8teによる優れた回答に加えて、Excelの場合、ddeexecレジストリキーを変更する必要がないことを述べます。

_(Default)_アイテムの値を設定するだけで十分です。

"C:\Program Files (x86)\Microsoft Office\Root\Office16\Excel.EXE" /dde "%1"

私のテストによると、Excelのインスタンスが1つだけ実行されることが保証されます。

1
harrymc