2019年6月9日日曜日

14: 'やあ、コンソールC# UNOクライアントたち'サンプル

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

VB.NETでも同様。あなたのプログラムをLibreOffice/OpenOfficeインスタンスに接続する、オフィスドキュメントを読み書きしたりインスタンスを操作したりするために。

話題


About: UNO (Universal Network Objects)
About: LibreOffice
About: Apache OpenOffice
About: .NET Framework

この記事の目次


開始コンテキスト



ターゲットコンテキスト



  • 読者は、外部コンソール.NET FrameworkプログラムをUNOサーバー(例えば、LibreOfficeまたはApache OpenOfficeのインスタンス)に接続する方法を知る。
ト書き
Hypothesizer 7、Objector 14A、Objector 14Bがコンピューターの前にいる。


オリエンテーション


Hypothesizer 7
この記事では、コンソールC# UNOクライアントサンプルを取得、ビルド、実行、理解します。

当サンプルはC#のものですが、代わりに、どの.NET Frameworkプログラミング言語も使用できるはずです。

Objector 14B
...どうやって?

Hypothesizer 7
マダム、サンプルを、任意の.NET Frameworkプログラミング言語へ翻訳すればよいだけです。

Objector 14B
「すればよいだけ」と言われても...

Hypothesizer 7
何か問題がありますか?

Objector 14B
...あなたが翻訳するほうが、私たちのそれぞれが個別に翻訳するより効率的でしょう。

Hypothesizer 7
私が?何にですが?

Objector 14B
VB.NETによ、もちろん。

Objector 14B
実のところ、私には「私たち」というのは見えてなくて、あなたしか見えていないのですよ。...そうですね、VB.NET版への投票が十分あれば、私が作りましょう。

Objector 14B
「投票」?どうやって投票したらいいの?

Hypothesizer 7
えーと、何らかの方法で。...どこかでそう述べてください、このページにリンクして。こちらで気付きますよ。

Objector 14B
...

Microsoftが提供しているツールがあって、それでMicrosoft形式ドキュメントファイルを読み書きできるって聞いたけど、あなたの方法はそれとどう違うわけ?

Hypothesizer 7
ああ、私もそういうツールのことは聞いたことがあります、名前は覚えていませんが。私が覚えている限りでは、そのツールはそうしたファイルを直接に読み書きするものであって、私が念頭に置いている方法は、LibreOfficeまたはApache Officeのインスタンス(以後、'オフィスインスタンス'と呼びます)を操作するものです。

Objector 14B
分かりません。

Hypothesizer 7
オフィスインスタンスを操作するということは、そのオフィスインスタンスに接続し、そのオフィスインスタンスに諸々の事をするよう依頼することを意味します(Microsoft形式ドキュメントファイルを読み書きすることは、その2例にすぎません)。

Objector 14B
私のプログラムは、ドキュメントファイルを読み書きする以外に他にどんなことを頼めるわけ?

Hypothesizer 7
実際のところ、LibreOfficeまたはApache Officeの機能の内のほとんど何でもです。

Objector 14B
例えば?

Hypothesizer 7
例えば、あなたのプログラムは、あるディレクトリ内のファイル群の各々の内容をスペルチェックし、問題のあるファイルだけを各々表示し、ミススペルの各単語にカーソルを自動的に移すことができます。

Objector 14B
ああ、確かに、それは、ストレージ内に保存されているファイルを読み書きするだけのプログラムには出来ないわね。

Objector 14A
その'開始コンテキスト'に挙げられてる記事は本当に全部読まんといかんかね?

Hypothesizer 7
サー、前提知識と前提環境をお持ちであればそれでよいのです: 既にそれらをお持ちでしたら、何も読む必要はありません。それら事前想定されたコンテキストを明確に定めたのは、それが、いやしくもまっとうなテクニカルドキュメントならばどれも果たさなければならない責務だからです。


本体


1: コンソールC# UNOクライアントサンプルを取得してビルドする


Hypothesizer 7
ここに、コンソールC# UNOクライアントサンプルがあります。このシリーズに挙げられている任意のサンプルプロジェクトをビルドする方法は過去の記事に記載されています。

MONOも.NET Coreも使用できない(私が知る限り)ことにご注意ください。正真正銘の.NET Frameworkが求められます。

そのZIPファイルを展開した後、'hiConsoleCsharpUnoClients'が、サンプルプログラムのプロジェクトディレクトリです。他2つのディレクトリは様々なプロジェクトから共通に使われるプロジェクトのものです。

開発環境を構築する方法は、過去の記事(Linux用はこちらで Windows用はこちら)で説明されています。

ト書き
Hypothesizer 7はターミナルを開いてサンプルプロジェクトをビルドする。


2: サンプルプログラムを実行する


Hypothesizer 7
サンプルプログラムを実行する前に、LibreOfficeまたはApache OpenOfficeのインスタンスを、クライアントからのコネクションを受け付ける状態で開始しておかなければなりません(その方法は、過去の記事で知ることができます)。

ト書き
Hypothesizer 7は、LibreOfficeのインスタンスをポート番号'2002'で開始する。

Hypothesizer 7
サンプルプログラムは、カレントディレクトリをサンプルプロジェクトディレクトリに位置させ、ファイルURLを環境に合わせて、以下のようにして実行できます。

@bash or cmd ソースコード
gradle i_executeCsharpExecutableFileTask -Pc_commandLineArguments="socket,host=localhost,port=2002,tcpNoDelay=1;urp;StarOffice.ComponentContext file://${HOME}/myData/development/hiConsoleCsharpUnoClients/execution/HiConsoleCsharpUnoClientsTests.odt"

ト書き
Hypothesizer 7は、カレントディレクトリをサンプルプロジェクトディレクトリに位置させて、上記コマンドをターミナルで実行する。Writer文書がオープンし、その後、すぐにクローズする。

Objector 14A
ドキュメントがディスプレイに表示されてほしくないんだが...

Hypothesizer 7
サー、それは、サンプルプログラムがオフィスインスタンスに正常に接続できたことを示すデモンストレーションにすぎません。ファイルをディスプレイ上に表示させずに開きたければ、容易にそうすることができます。

Objector 14A
おお、それならいい。

Hypothesizer 7
'URE_BOOTSTRAP'という環境変数が、LibreOfficeまたはApache OpenOfficeの'fundamental.ini'ファイルのURL値で設定されていることにご注意ください。

LibreOfficeまたはApache OpenOfficeのインスタンスがリモートホストにいる場合は、ホスト名を'localhost'から変更すればよいです、勿論、ファイアウォールが通信をブロックしなければですが。


3: サンプルプログラムを理解する


Hypothesizer 7
コンソールC# UNOクライアントサンプルの説明は、コンソールJavaUNOクライアントサンプルのそれとほとんど同じであって、その過去記事内の一部の記述とほとんど同じ記述をここで行なうことなく、その過去記事の一部のサブセクションを引用して、違いだけを示します。


3-1: プロジェクト群構造を理解する


Hypothesizer 7
3つのプロジェクト、'coreUtilitiesToBeDisclosed'、'unoUtilitiesToBeDisclosed'、'hiConsoleCsharpUnoClients'があります。'coreUtilitiesToBeDisclosed'には、あらゆる種類のプロジェクトで共用されるように想定されているユーティリティコードが含まれています。'unoUtilitiesToBeDisclosed'には、UNOプログラムのプロジェクト群で共用されるように想定されているユーティリティコードが含まれています。'hiConsoleCsharpUnoClientsは、サンプルプロジェクトです。

サンプルプログラムは、'unoUtilitiesToBeDisclosed'をただ使う以外のことはあまり行なわないので、私たちの外部コンソールC#プログラムをUNOサーバーに接続させる方法を学ぶには、'unoUtilitiesToBeDisclosed'プロジェクトの中身を見る必要があります。

それらユーティリティプロジェクトにはJavaコードとC++コードも含まれていますが、'source/java'および'source/cplusplus'というディレクトリは削除してもかまいません、それらが JavaやC++のUNOコード用になっていないあなたの環境に何か問題を起こすようでしたら。

Objector 14A
...なんで、そんな不要なものを取り除いた状態でサンプルを提供しない?

Hypothesizer 7
えーと、プロジェクトのそのような派生バージョンを作りたくないのです、なぜなら、コードベースの管理が複雑になってしまいますから。そもそも、不要なコードは無視されるだけのはずです、'commonVolatileProperties.gradle'ファイルが、本サイトの任意のサンプルプロジェクトをビルドすることについての以前の記事に記述されているとおりに適切に設定されていれば。ああしたディレクトリを削除することについて言及したのは、その適切な設定を万が一しそこなった場合のためにすぎません。

Objector 14A
...


3-2: 当ユーティリティプロジェクト群を使用してUNOサーバーに接続した後にしなければならないこと


Hypothesizer 7
当ユーティリティプロジェクト群を万が一そのままご使用になるという場合のために、当ユーティリティプロジェクト群を使用してUNOサーバーにコネクトした後にしなければならないことを見ておきましょう。

実際には、C#ユーティリティクラス・インターフェイス群の構造はJavaユーティリティクラス・インターフェイス群のそれに準拠しているため、以前の記事のこのサブセクションの記述が、そのまま当てはまります。


3-3: UNOオブジェクト群コンテキストのラッパー


Hypothesizer 7
'unoUtilitiesToBeDisclosed'プロジェクトの'theBiasPlanet.unoUtilities.connectionsHandling.UnoObjectsContext'クラスは、UNOオブジェクト群コンテキストのラッパーです。

このラッパーについての以前の記事のこのサブセクションの記述が、そのまま、ここに当てはまります。


3-4: ローカルUNOオブジェクト群コンテキストを生成する(ブートストラッピング)


Hypothesizer 7
'ブートストラッピング'のコンセプトについての以前の記事のこのサブセクションの記述は、ここに当てはまりますが、ローカルUNOオブジェクト群コンテキストを生成する方法は、C#では異なります。

以下が、ローカルUNOオブジェクト群コンテキストを生成する方法です、'theBiasPlanet.unoUtilities.programsHandling.UnoProcessEnvironment'クラスのコンストラクターに見られるとおり。

@C# ソースコード
			using uno.util;
			using unoidl.com.sun.star.uno;
			
						XComponentContext l_originalLocalObjectsContext = Bootstrap.defaultBootstrap_InitialComponentContext ();


3-5: UNOサーバーに接続する


Hypothesizer 7
UNOサーバーに接続することについての以前の記事のこのサブセクションの記述が、1つの注意点を除いて、ここに当てはまります。

接続がTCP/IPソケットを介して行われる場合、Windowsソケット機能が、あなたのプログラムによって明示的に初期化・終了化されなければなりません。

以下が、サンプル内でそうされている方法です。

theBiasPlanet/coreUtilities/programsHandling/ProcessEnvironment.cs

@C# ソースコード
namespace theBiasPlanet {
	namespace coreUtilities {
		namespace programsHandling {
			~
			using System.Runtime.InteropServices;
			~
			
			public class ProcessEnvironment {
				~
				[StructLayout (LayoutKind.Sequential)]
				internal struct WSAData {
					public short wVersion;
					public short wHighVersion;
					[MarshalAs (UnmanagedType.ByValTStr, SizeConst=257)]
					public string szDescription;
					[MarshalAs (UnmanagedType.ByValTStr, SizeConst=129)]
					public string szSystemStatus;
					public short iMaxSockets;
					public short iMaxUdpDg;
					public int lpVendorInfo;
				}
				[DllImport ("ws2_32.dll", CharSet=CharSet.Ansi, SetLastError=true)]
				internal static extern int WSAStartup (
					[In] short wVersionRequested,
					[Out] out WSAData lpWSAData
				);
				[DllImport ("ws2_32.dll", CharSet=CharSet.Ansi, SetLastError=true)]
				internal static extern int WSACleanup ();
				private const int c_windowsSocketStartupSuccessStatus = 0;
				private const short c_windowsSocketVersion = 0x0202;
				~
				
				public static void windowsSocketStartup () {
					WSAData l_windowsSocketData;
					int l_windowsSocketStartupStatus = WSAStartup (c_windowsSocketVersion, out l_windowsSocketData);
					if (l_windowsSocketStartupStatus != c_windowsSocketStartupSuccessStatus) {
						throw new System.Exception (String.Format ("WSAStartup failed: return code = {0:D}", l_windowsSocketStartupStatus));
					}
				}
				
				public static void windowsSocketCleanup () {
					WSACleanup ();
				}
			}
		}
	}
}

theBiasPlanet/hiConsoleCsharpUnoClients/programs/HiConsoleCSharpUnoClients.cs

@C# ソースコード
namespace theBiasPlanet {
	namespace hiConsoleCsharpUnoClients {
		namespace programs {
			~
			using System;
			using theBiasPlanet.coreUtilities.programsHandling;
			
			public class HiConsoleCSharpUnoClients {
				static void Main (String [] a_argumentsArray) {
					try {
						~
						ProcessEnvironment.windowsSocketStartup ();
						~
						ProcessEnvironment.windowsSocketCleanup ();
					}
					catch (Exception l_exception) {
						~
					}
				}
			}
		}
	}
}


3-6: コネクションを切断する


Hypothesizer 7
コネクションを切断することについての以前の記事のこのサブセクションの記述が、そのまま、ここに当てはまります。


4: オフィスインスタンスに接続する、より単純な方法があるが...


Hypothesizer 7
実は、オフィスインスタンスに接続する、より単純な方法があります、しかし、その方法にはいくつか制限があり、それらは、ある種のケースにおいて致命的です。

以前の記事のこのセクションの議論が、ここに、そのまま、当てはまります。


5: 結びとその先


Hypothesizer 7
これで、コンソールC# UNOクライアントから、任意のUNOサーバーにコネクトすることができます。

当サンプルを'コンソール'クライアントと特に断わったのは、GUI C# UNOクライアントサンプルを将来の記事で紹介するからです。

GUI C# UNOクライアントは、UNO上、コンソールC# UNOクライアントと違う必要がないように思われるかもしれませんが、1つ違いがあります。UNOクライアントが長い間動作し続けると想定されるため、UNOサーバーまたはネットワークによって引き起こされるコネクション切断を検知することがより適切となります。


参考資料


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