2019年5月26日日曜日

13: 'soffice'または'soffice.exe'の実行はどのように動作するか

<このシリーズの前の記事 | このシリーズの目次 | このシリーズの次の記事>

うむ?この'soffice'呼び出しはなぜ即座にリターンするのだ?うーん、この呼び出しはなぜこんなに遅いのか?

話題


About: UNO (Universal Network Objects)
About: LibreOffice
About: Apache OpenOffice

この記事の目次


開始コンテキスト



ターゲットコンテキスト



  • 読者は、'soffice'または'soffice.exe'の実行はどのように動作するかを理解する。
ト書き
Hypothesizer 7、Objector 13AがWindowsコンピューターの前にいる。


オリエンテーション


Objector 13A
はあ?なんで?こんなのおかしい!

Hypothesizer 7
...サー、何がおかしいのですか、もし、お聞きしてよろしければ?

Objector 13A
私のC#プログラムは、'soffice.exe'を呼び出し、そのLibreOfficeプロセスが終了するまで待つのだ。

Hypothesizer 7
ふーむ...

Objector 13A
しかし、呼び出しはすぐにリターンする、LibreOfficeプロセスが終了するのを待たずに!

Hypothesizer 7
ああ...

Objector 13A
「ああ...」なんだ?

Hypothesizer 7
'soffice.exe'呼び出しがリターンすることとLibreOfficeインスタンスが終了することとを混同していらっしゃいませんか?

Objector 13A
はあ?「混同してい」るとはどういう意味だ?

Hypothesizer 7
えーと、言い換えると、'soffice.bin'プロセスとLibreOfficeインスタンスを混同していらっしゃいませんか?

Objector 13A
はあ?「soffice.bin」って何だ?'soffice.exe'だろう?

Hypothesizer 7
いいえ。「soffice.bin」です。...サー、あなたのプログラムは、'soffice.exe'を呼び出すことで何を成し遂げたいのですか、もし、お聞きしてよろしければ?

Objector 13A
私のプログラムは、LibreOfficeによってドキュメントファイルをデスクトップ上に開き、そのドキュメントをユーザーが編集し終わるまで待ち、それからそのドキュメントファイルに処理を行ないたいのだ。私のプログラムは、そのドキュメントをユーザーが編集し終わるまで絶対に待たなければならない。

Hypothesizer 7
ああ...

Objector 13A
「ああ...」何だ?

Hypothesizer 7
あなたの状況を考えると、あなたのプログラムが'soffice.exe'を呼び出したときには、あるLibreOfficeインスタンスが既に立ち上がっており、当該'soffice.bin'プロセスは、その既存LibreOfficeインスタンスへのUNOクライアントとして動作したのであって、一人前のLibreOfficeプロセスにはならなかったに違いないと思います。

Objector 13A
はあ?お前は寝言を言っているのか?「UNO」?「UNOクライアント」?

Hypothesizer 7
えーと、多分、あなたは、UNOとは何か、およびそれがLibreOfficeまたはApache OpenOfficeにどう関係しているかを理解する必要があります、何が起きているかを理解するためには。

Objector 13A
...


本体


1: 'soffice'または'soffice.exe'と'soffice.bin'の区別


Hypothesizer 7
予備知識として、'soffice'(Linuxの場合)または'soffice.exe'(Windowsの場合)と'soffice.bin'の区別を理解しましょう。

'soffice.bin'は、LibreOfficeまたはApache OpenOfficeのメインプログラムであり、'soffice'または'soffice.exe'は、'soffice.bin'プロセスを起動するものです。

Linuxでは、'soffice'はシェルスクリプトであり、それが、'soffice'が実行された際、'ps'コマンドは'soffice.bin'プロセスを示すが'soffice'プロセスを示さない理由です(シェルスクリプトは、それ自体がプロセスになるものではなく、シェルプロセスに読みこまれる指示データです)。

Windowsでは、'soffice.exe'が実行された際、'タスクマネージャー'は'soffice.bin'プロセスと'soffice.exe'プロセスを示します('soffice.exe'は、バッチファイルではなく、正真正銘の実行可能ファイルだから)。


2: 'LibreOfficeインスタンス'または'Apache OpenOfficeインスタンス'('オフィスインスタンス'とも呼ぶ)を定義しよう


Hypothesizer 7
論理的に言って、誰がいかなる用語を恣意的に定義しても構わないが、少なくとも、2つの互いに異なるコンセプトがあれば、それらに別の名前を与えてそれらを区別をする必要はあります。

そこで、私たちは、一人前のLibreOfficeプロセスまたはApache OpenOfficeプロセスを'LibreOfficeインスタンス'または'Apache OpenOfficeインスタンス'と呼びます(私は'オフィスインスタンス'も使います、常に2つの名前を挙げられるのは一部の読者にはうっとうしいでしょうから)、その一方で、任意の'soffice.bin'プロセスのことは''soffice.bin'プロセス'と呼びます。...実際は、'LibreOfficeプロセス'、'Apache OpenOfficeプロセス'、'オフィスプロセス'という用語を使ってもよいのですが、私は大抵'インスタンス'を使用します。

Objector 13A
...「一人前のLibreOfficeプロセスまたはApache OpenOfficeプロセス」というのはどういう意味だ?

Hypothesizer 7
一人前のLibreOfficeプロセスまたはApache OpenOfficeプロセスとは、LibreOfficeまたはApache OpenOfficeのメインの機能群を本当に実行する能力を持つプロセスのことです。

Objector 13A
...「本当に実行する」というのはどういう意味だ?

Hypothesizer 7
そのプロセスはLibreOfficeまたはApache OpenOfficeのメインの機能群を自身の中で実行する、その機能群の実行を別のプロセスに委ねるのではなく、という意味です。

Objector 13A
ふーむ...、まだ私には理解できない、ある'soffice.bin'プロセスがオフィスインスタンスでないということがどのように起こり得るのか。

Hypothesizer 7
それは、次のセクションで明らかになります。


3: 'オフィスインスタンス'は、オペレーティングシステムユーザー毎のシングルトンである


Hypothesizer 7
'オフィスインスタンス'は、オペレーティングシステムユーザー毎のシングルトンです、つまり、オペレーティングシステムユーザー毎に1つより多くのオフィスインスタンスは同時に存在できません。

Objector 13A
...と言うと?

Hypothesizer 7
あるオペレーティングシステムユーザーにオフィスインスタンスがなければ、そのユーザーによる'soffice'または'soffice.exe'の実行は、オフィスインスタンスを起動します。

Objector 13A
例えば、私のプログラムが、あるドキュメントファイルのパスを引数として'soffice.exe'を実行する時、...

Hypothesizer 7
オフィスインスタンスが起動され、そのオフィスインスタンスが自身の中にそのドキュメントファイルをオープンします。

Objector 13A
それは分かる。

Hypothesizer 7
その一方、そのユーザーに既にオフィスインスタンスが1つあれば(1つより多くあることはない)、'soffice'または'soffice.exe'の実行は、新たなオフィスインスタンスを起動せず、既存オフィスインスタンスに接続するUNOクライアントになります。

Objector 13A
しかし、お前の記事が言ってるような、LibreOfficeをUNOサーバーとしてセットアップすることは私はしていない。

Hypothesizer 7
ああ、いい指摘です。その記事に記述があるとおり、オフィスインスタンスは、'soffice.exe'コマンドによっていつでもUNOサーバー化することができます。実際、第2の'soffice.exe'コマンドはまさにそれをしたのです。

Objector 13A
オフィスインスタンスをソケットUNOサーバーにしたのか?

Hypothesizer 7
いいえ、コマンドは、オフィスインスタンスを名前付きパイプUNOサーバーにしました。

Objector 13A
えーと、例えば、その状況で私のプログラムが、あるドキュメントファイルのパスを引数として'soffice.exe'を実行する時、...

Hypothesizer 7
その'soffice.bin'プロセスは、そのドキュメントファイルを自身の中でオープンせず、既存オフィスインスタンスにそのドキュメントファイルをオープンするよう依頼し、そして終了します。

Objector 13A
...そのドキュメントはどうなるんだ?

Hypothesizer 7
そのドキュメントは、既存オフィスインスタンス内にオープンされたままになります、それが明示的に閉じられるまでは。

Objector 13A
それでは、その'soffice.exe'呼び出しは、そのドキュメントが閉じられるのを待つことなくすぐにリターンすることになる、当然。

Hypothesizer 7
...当然です。

ご注意ください、別のオペレーティングシステムユーザーは別のオフィスインスタンスを持つことができ、'soffice.bin'プロセスは別のオペレーティングシステムユーザーのオフィスインスタンスには接続しません、それが、「'オフィスインスタンス'は、オペレーティングシステムユーザー毎のシングルトンである」の意味です。


4: 'soffice'(Linuxの場合)または'soffice.exe'(Windowsの場合)がどのように動作するか、デモンストレーションしてみよう


Hypothesizer 7
前セクションで学んだとおりに'soffice.exe'呼び出しが動作することをデモンストレーションしてみましょう。

ターミナルを開いて、'soffice.exe'コマンド('soffice.exe'ファイルはLibreOfficeディレクトリの'program'ディレクトリにあります)を'--writer'オプション付きで実行してください(新たなWriterドキュメントをオープンすることを意味します)、オフィスインスタンスが立ち上がっていないことを確認した後で。

ト書き
Objector 13Aは、以前のLibreOfficeインスタンスをシャットダウンし、ターミナルを開き、そのターミナル上で以下を実行する。

@cmd ソースコード
soffice.exe --writer

Objector 13A
すぐにリターンしたが...

Hypothesizer 7
'start /wait soffice.exe --writer'としてください: 即座にリターンするのは、'soffice.exe'の問題ではなく、ターミナルの問題です。

ト書き
Objector 13Aは、以前のLibreOfficeインスタンスをシャットダウンし、ターミナル上で以下を実行する。

@cmd ソースコード
start /wait soffice.exe --writer

Objector 13A
ああ、デスクトップ上に新たなドキュメントが新たなウィンドウにオープンし、コマンドはすぐにリターンはしない。

Hypothesizer 7
そのコマンドは1つのオフィスインスタンスを起動し、そのオフィスインスタンスは新たなWriterドキュメントを自身の中にオープンしました。

そのオフィスインスタンスを立ち上がったままにして、同一のコマンドをもう一度実行してください。

ト書き
Objector 13Aは、別のターミナルを開き、そのターミナル上で以下を実行する。

@cmd ソースコード
start /wait soffice.exe --writer

Objector 13A
デスクトップ上に新たなドキュメントが新たなウィンドウにオープンするが、コマンドがすぐにリターンする、新たにオープンされたウィンドウがオープンしたままで...

Hypothesizer 7
第2のコマンドは、既存のオフィスインスタンスに接続し、そのオフィスインスタンスに新たなWriterをオープンするよう依頼し、そして終了しました。その新たなウィンドウはその既存のオフィスインスタンスのものです。


5: 結びとその先


Hypothesizer 7
これで、私たちは、'soffice'または'soffice.exe'の実行がどのように動作するかを理解しました。

'soffice'または'soffice.exe'を呼ぶことは、新たなLibreOfficeまたはApache OpenOfficeインスタンス(オフィスインスタンス)を起動することを必ずしも意味せず、呼び出しがリターンすることは、オフィスインスタンスの終了を必ずしも意味しません。

もしも、あるプログラムが、'soffice'または'soffice.exe'の呼び出しのリターンを待つことでオフィスインスタンスの終了(および、そのオフィスインスタンス内にオープンされているドキュメントがクローズされるの)を待つといったコントロールをしなければならないのであれば、そのプログラムは、その呼び出しの前に、そのオペレーティングシステムユーザにオフィスインスタンスが動作していないことを確認しなければならないでしょう。

しかしながら、ユーザーは大抵、自由にオフィスインスタンスを起動できるので、そのような強制は大抵、困難であり、各アクション毎にオフィスインスタンスを起動および停止するのはとても非効率です。そうではなく、オフィスインスタンスをUNOサーバーとして使用し、そのUNOサーバーを操作する、自身のUNOクライアントを作りませんか?

自身のUNOクライアントを作るのは、一部の人が想像するかもしれないほど面倒なものではなく、私は、いくつかのUNOコンソールクライアントサンプル(Java版C++版C#版Python版)および1つのUNO GUIクライアントサンプル(Java版。他のプログラミング言語のUNO GUIクライアントサンプルは後に公開されます)を既に公開しております。

'soffice --convert-to'コマンドを自身のプログラムから呼ばれる方々が一部におられますが、そのコマンドはまさに本記事で説明されたように動作し、効率的、同時実行的に(加えて、機能的にも)それほど望ましくないかもしれません。LibreOfficeまたはApache OpenOfficeをファイルコンバーターとして最適に使用することについての記事(コンセプト, あるJava実装あるC++実装あるC#実装あるPython実装あるLibreOffice Basic実装)があります。


参考資料


<このシリーズの前の記事 | このシリーズの目次 | このシリーズの次の記事>