COM/DCOM は Adobe ColdFusion(2025 リリース)で削除されました
アプリケーションページでコンポーネント内のメソッドを呼び出したりプロパティを割り当てたりする前に、cfobject タグまたは CreateObject 関数を使用して、ColdFusion 内に COM オブジェクト(コンポーネント)のインスタンスを作成します。
例えば、次のコードでは、cfobject タグを使用して、メールを送信するための Windows CDO(Collaborative Data Object)for NTS の NewMail オブジェクトをを作成します。
action="Create" |
次の行に、CFScript で対応する CreateObject 関数を使用する方法を示します。
Mailer = CreateObject("COM", "CDONTS.NewMail"); |
このドキュメントのいくつかの例では、このオブジェクトを使用しています。
メモ:CDO は、Microsoft SMTP サーバーがインストールされているすべての Windows NT および 2000 オペレーティングシステムにデフォルトでインストールされています。Windows NT Server 環境では、Option Pack 4 セットアップに SMTP サーバーが含まれています。 Windows 2000 Server および Workstation 環境では、オペレーティングシステムにバンドルされています。 |
メモ : CDO for NTS の NewMail コンポーネントには、さまざまなメール処理タスクを行うためのメソッドやプロパティが用意されています。 (OLE/COM オブジェクトビューアでは、メソッドとプロパティがグループ化されるので、最初は区別するのが困難な可能性があります)。
CDO for NTS の NewMail オブジェクトには、次のプロパティがあります。
Cc[ String ] |
これらのプロパティを使用して、メールメッセージの各要素を定義できます。CDO for NTS の NewMail オブジェクトには、メッセージを送信するためのオプション引数を持つ send メソッドもあります。
COM オブジェクトへの接続
cfobject タグの action 属性では、COM オブジェクトへの接続方法として、次のいずれかを指定できます。
- Create メソッド(cfobject action="Create")COM オブジェクト(通常は DLL)をインスタンス化して、メソッドの実行やプロパティの設定を行えるようにします。
- Connect メソッド(cfobject action="Connect")サーバー上で既に実行されているオブジェクト(通常は実行可能ファイル)にリンクします。オプションの cfobject context 属性を使用して、オブジェクトコンテキストを指定できます。コンテキストを指定しない場合は、レジストリの設定が使用されます。次の表で、context 属性値について説明します。
属性値 |
説明 |
---|---|
InProc |
ColdFusion などの、呼び出しプロセスと同じプロセス領域で実行されている in-Process サーバーオブジェクト(通常は DLL)。 |
local |
ColdFusion プロセス領域の外で実行されているが、同じサーバー上でローカルに実行されている out-of-process サーバーオブジェクト(通常は EXE ファイル)。 |
remote |
ネットワーク上でリモートに実行されている out-of-process サーバープロジェクト(通常は EXE ファイル)。remote を指定する場合は、オブジェクトの場所を識別する server 属性も使用します。 |
プロパティの設定とメソッドの実行
次の例では、サンプルの Mailer COM オブジェクトを使用して、メールメッセージにプロパティを割り当てる方法を示します。さらに、コンポーネントのメソッドを実行してメールメッセージを処理する方法を示します。
この例では、メソッドパラメーターやプロパティ(受信者の名前やメールアドレスなど)がフォーム変数に保存されているものとしています。
<cfobject type="COM" <br>
action="Create" <br>
name="Mailer" <br>
class="CDONTS.NewMail"> |
メモ:COM オブジェクトで発生する例外を処理するには、cftry および cfcatch タグを使用します。例外処理の詳細については、Handling runtime exceptions with ColdFusion tagsを参照してください。 |
COM オブジェクトの解放
デフォルトでは、Java ガベージコレクタが COM オブジェクトをクリーニングすると、COM オブジェクトのリソースが解放されます。オブジェクトが不要になった場合は、ReleaseCOMObject 関数を使用してすぐにリソースを解放できます。
ReleaseCOMObject 関数を使用すると、外部プロセスとして起動された Microsoft Excel などの COM オブジェクトを解放できます。 ガベージコレクタでは、プロセスのクリーニングが実行されるまでに時間がかかることがあります。その結果、複数の外部プロセスが存在して、システムリソースが浪費されることがあります。
COM オブジェクトに、プログラムを終了するメソッドがある場合は、ReleaseComObject 関数を呼び出す前にそのメソッドを呼び出します。 使用中のオブジェクトに対して ReleaseComObject 関数を使用すると、正常に完了する前にオブジェクトが解放されて、アプリケーションで例外が発生します。
例
次の例では、Microsoft Excel アプリケーションオブジェクトを作成して使用した後に、不要になったオブジェクトを解放します。
<h3>ReleaseComObject Example</h3> |
COM オブジェクトに関する一般的な注意事項
COM オブジェクトを使用する場合は、エラーを回避および解決するために、次の事項を考慮する必要があります。
- スレッドへの対応
- in 引数および out 引数の使用
- COM 関連の一般的なエラーメッセージの理解
スレッドへの対応
ColdFusion で COM オブジェクトを使用する場合、スレッドへの対応が不適切であると、重大な問題が発生することがあります。 オブジェクトはスレッドセーフであることが必要です。スレッドセーフとは、複数のプログラミングスレッドから同時に呼び出されても、オブジェクトの処理が正常に実行されることをいいます。
Visual Basic の ActiveX DLL は、通常スレッドセーフではありません。このような DLL を ColdFusion で使用する場合は、OLE/COM オブジェクトビューアを使用して、オブジェクトのスレッド処理モデルを Apartment モデルに変更することで、スレッドセーフにすることができます。
COM オブジェクトへの参照を Application、Session、または Server スコープに保管する場合は、Apartment スレッド処理モデルを使用しないでください。Apartment スレッド処理モデルは、単一のリクエストのみを処理するモデルです。 これらのスコープにオブジェクトを保管する必要がある場合は、オブジェクトのスレッド処理モデルを Both のままにし、cflock を使用したコードのロックの説明に従って、そのオブジェクトにアクセスするコードをすべてロックします。
COM オブジェクトのスレッド処理モデルの変更
- OLE/COM オブジェクトビューアを起動します。
- 左ペインの [Object Classes] の下にある [All Objects] を選択します。
- 対象の COM オブジェクトを探します。 左ペインにオブジェクトの名前がリストされます。
- 対象のオブジェクトを選択します。
- 右ペインの [Implementation] タブを選択します。
- [App ID] フィールドの下にある [Inproc Server] タブを選択します。
- [Threading Model] ドロップダウンリストから、[Apartment] または [Both] のいずれか適切なほうを選択します。
in 引数および out 引数の使用
COM オブジェクトメソッドの in 引数は、値渡しです。 COM オブジェクトには変数値のコピーが渡されるので、ColdFusion 変数は引用符で囲まずに指定できます。
COM オブジェクトメソッドの out 引数は、参照渡しです。呼び出しページの変数が COM オブジェクトによって変更されるので、呼び出しページでその値を使用することができます。 参照によって変数を渡すには、既存の ColdFusion 変数を引用符で囲みます。 引数が数値型である場合は、呼び出しを行う前に、その変数に有効な数値を代入します。 例:
<cfset outNumericArg=0> |
オブジェクトの calculate メソッドに文字列 "Hello Object" が in 引数として渡され、 outNumericArg の値が数値に設定されます。
COM 関連の一般的なエラーメッセージの理解
次の表で、COM オブジェクトの使用時に発生する可能性があるエラーメッセージについて説明します。
エラー |
原因 |
---|---|
Error Diagnostic InformationError trying to create object specified in the tag.COM error 0x800401F3. Invalid class string. |
COM オブジェクトが登録されていないか、または存在しません。 |
Error Diagnostic InformationError trying to create object specified in the tag.COM error 0x80040154. Class not registered. |
COM オブジェクトが登録されていないか、または存在しません。 このエラーは通常、以前は存在していたオブジェクトが削除された場合に発生します。 |
Error Diagnostic InformationFailed attempting to find "SOMEMETHOD" property/method on the object COM error 0x80020006.Unknown name. |
COM オブジェクトは正常にインスタンス化されましたが、指定されたメソッドが存在しません。 |
Java プロキシによる複合 COM オブジェクトへのアクセス
ColdFusion では、COM オブジェクトにアクセスするための Java プロキシがサポートされています。 Java プロキシが事前に作成されていない場合は、ColdFusion がダイナミックに COM インターフェイスを検出する必要があります。 これには、次のような 2 つの短所があります。
- ダイナミックな検出には時間がかかり、複雑な COM オブジェクトを頻繁に使用する場合はサーバーのパフォーマンスが低下することがあります。
- ダイナミックな検出では IDispatcher インターフェイスを使用して COM オブジェクトの機能が認識されるので、複雑な COM インターフェイスは処理されないことがあります。
ColdFusion には、この問題を解決するために、COM オブジェクト用のスタティックな Java スタブプロキシクラスを作成する "com2java.exe" というユーティリティが用意されています。 ColdFusion は、この Java スタブを使用することで、ダイナミックにプロキシを作成するよりも効率的に COM オブジェクトにアクセスすることができます。 また、com2java.exe ユーティリティでは、ダイナミックプロキシジェネレータでは認識されないような機能のスタブも作成できます。
ColdFusion には、Windows XP、Windows 2000、および Windows 97 版の Microsoft Excel、Microsoft Word、および Microsoft Access に対応する、生成済みのスタブが用意されています。これらのスタブは自動的に使用されるように設定されています。
COM オブジェクトの Java スタブファイルを作成する場合は、COM オブジェクトを作成する場合と同様に、cfobject タグの type 属性に値 COM を指定するか、CreateObject 関数の最初の引数に COM を指定し、ColdFusion で COM オブジェクトにアクセスする場合と同様にオブジェクトのプロパティやメソッドにアクセスします。
"com2java.exe" ユーティリティを使用するには、次の手順に従います。 この手順では、Microsoft Outlook を例として使用しています。
COM オブジェクトの Java スタブファイルを作成するには :
- システムを次のように構成します。
- JDK(Java Development Kit)が正しくインストールされていることを確認します。例えば、CLASSPATH やコマンドプロンプト PATH 変数が正しく設定されていることを確認します。
- CLASSPATH に ”ColdFusion のルートディレクトリ ¥lib¥jintegra.jar" を追加します。
次の例のように、Java スタブファイルのための新しいディレクトリを作成します。
mkdir C:\src\outlookXP
このディレクトリは一時的なものでかまいません。 このディレクトリのファイルは、ColdFusion JAR ファイルに追加されます。
- コマンドラインまたは Windows のスタートメニューから、"ColdFusion のルートディレクトリ¥Jintegra¥bin¥com2java.exe" プログラムを実行します。ウィンドウが表示されます。
- COM クラスに、同じ名前のメソッドを持つ複数のインターフェイスが実装されている場合は、[Options] メニューアイテムを選択して、[Implement interfaces that may conflict] オプションをオフにします。 生成された Java スタブクラスが、競合する複数のインターフェイスを実装することはありません。 生成された getAsXXX メソッドを使用すれば、インターフェイスにアクセスすることができます。 Java ファイルに生成されたコメントを確認します。
- 「SELECT」ボタンをクリックします。
- COM オブジェクトのタイプライブラリまたは DLL を選択します。このファイルは、Windows XP の Microsoft Outlook の場合、通常は "Program Files¥Microsoft Office¥Office10¥MSOUTL.OLB" にあります。
com2java ダイアログボックスの「Java package」フィールドに、パッケージ名(outlookXP など)を入力します。 このパッケージには、COM オブジェクトの Java スタブに対するすべてのクラスが含まれます。
メモ:Microsoft Excel、Microsoft Word、および Microsoft Access 用の生成済みの Java スタブが含まれているパッケージは、名前が coldfusion.runtime.com.com2java で始まります。例えば、Microsoft Word XP 用の Java スタブクラスが含まれているパッケージの名前は coldfusion.runtime.com.com2java.wordXP になります。したがって、msapps.jar ファイルにおける wordXP クラスのパスは、このパッケージ名の階層に従って、coldfusion¥runtime¥com¥com2java¥wordXP¥className.class になります。この命名規則は必須ではありませんが、多くの COM オブジェクトを使用する場合は、わかりやすくするために同様のパッケージ命名規則を使用することを検討してください。
-
- [Generate Proxies] ボタンをクリックして、ファイルブラウザを表示します。 手順 2 で作成したディレクトリを選択し、ファイルブラウザの [OK] ボタンをクリックしてスタブファイルを生成します。
- 「閉じる」をクリックして、com2java.exe ユーティリティを閉じます。ディレクトリに生成されるファイルには次のものが含まれます。
- 各 COM インターフェイスの Java インターフェイスとプロキシクラス
- 各 COM クラスの Java クラス
- 各 ENUM (一連の定数定義) の Java インターフェイス
- Java コードをコンパイルします。 コマンドプロンプトで、次の作業を行います。
- Java スタブが含まれているディレクトリ(この例では C:¥src¥outlookXP)を作業ディレクトリにします。
次の行を入力します。
javac -J-mx100m -J-ms100m *.java
コンパイラスイッチで、必要なファイルをすべてコンパイルするために十分なメモリがあることを確認します。
メモ:手順 1b で CLASSPATH に "jintegra.jar" を含めなかった場合は、スイッチ -classpath:/ColdFusion のルートディレクトリ/lib/jintegra.jar をコマンドに追加します。ColdFusion のルートディレクトリは、ColdFusion がインストールされているディレクトリです。
- ColdFusion サーバーが停止していることを確認します。 ColdFusion サーバーを停止するには、[サービス] コントロールパネルを開き、ColdFusion アプリケーションサーバーを選択して、[停止] をクリックします。
- 次の操作を行って、.class ファイルを ColdFusion Microsoft アプリケーションの Java スタブファイルに追加します。
- Windows のコマンドプロンプトで、クラスファイルが含まれているディレクトリの親ディレクトリを、作業ディレクトリにします。次の例では、手順 4 のコマンドプロンプトで cd .. と入力して、c:\src を作業ディレクトリにします。
次のコマンドを入力します。
jar -uvf cf_root\lib\msapps.jar directoryName\*.class
ColdFusion のルートディレクトリは、ColdFusion がインストールされているディレクトリです。ディレクトリ名は、クラスファイルが含まれているディレクトリの名前です。OutlookXP の例では、次の行を入力します。
jar -uvf C:\CFusion\lib\msapps.jar outlookXP\*.class
"ColdFusion のルートディレクトリ/lib/neo-comobjmap.xml" ファイルのリストにオブジェクト定義を追加します。オブジェクト定義は、次の行で構成されます。
<string>PackageName.mainClass</string>
</var>これらの行では、次の値を使用します。
- ProgID OLE/COM オブジェクトビューアに表示される、COM オブジェクトの ProgID。
- PackageName 手順 3c で指定したパッケージ名。
mainClass COM オブジェクトのメインクラス。メインクラスには、呼び出すメソッドが含まれています。 多くの Microsoft アプリケーションでは、メインクラスは Application です。 一般に、手順 4 で作成される最大のクラスファイルがメインクラスです。 例えば、outlookXP を "neo-comobjmap.xml" に追加するには、次の太字で示されている行を </struct> 終了タグの上に追加します。
<string>coldfusion.runtime.com.com2java.access2k.Application</string>
</var>
<var name="outlook.application.10">
<string>outlookXP.Application</string>
</var>
</struct>この例では、outlook.application.10 が Outlook COM オブジェクトの ProgID、outlookXP が手順 3c で指定したパッケージ名、Application が COM オブジェクトのメインクラスです。
- ColdFusion サーバーを再起動します。[サービス] コントロールパネルを開き、ColdFusion アプリケーションサーバーを選択して [開始] ボタンをクリックします。
- スタブのインストールが終わったら、手順 2 で作成したディレクトリとその内容をすべて削除できます。
Application スコープの使用による COM パフォーマンスの向上
COM オブジェクトインスタンスを作成する Java 呼び出しには、かなりの時間がかかることがあります。 そのため、ColdFusion で COM オブジェクトを作成すると、ColdFusion 5 を使用したときよりも大幅に時間がかかる場合があります。 たとえば、システムによっては、ColdFusion を使用して Microsoft Word アプリケーションオブジェクトを作成すると 1 秒以上かかり、一方、同じシステムで Word オブジェクトを作成したときのオーバーヘッドは約 200 ミリ秒になることがあります。
したがって、Application スコープの単一の COM オブジェクトをすべてのページで共有すれば、COM のパフォーマンスを向上させることができます。
このテクニックは、次の条件がすべて満たされる場合にのみ使用します。
- リクエストまたはセッションごとに COM オブジェクトを作成する必要がない。 セッション固有のオブジェクトの場合は、Application スコープの代わりに、ここで説明するテクニックを Session スコープで使用することを検討してください。
- COM オブジェクトが共有に対応している。
オブジェクトは複数のページやセッションから同時にアクセスされることがあるので、スレッド処理やロックに関する次のような問題を考慮してください。
- 最高のパフォーマンスを得るには、オブジェクトをマルチスレッド対応にします。 マルチスレッドに対応していない場合、オブジェクトに同時にアクセスできるリクエストは 1 つのみです。
- 共有データにアクセスするコードや、共有データを変更するコードをロックします。 共有オブジェクトのデータを変更するコードのうち、複数のリクエストで共有されていないデータ(書き込み可能なプロパティやファイルの内容などを含む)を変更するコードは、一般にロックしなくてかまいません。ただし、実際にロックが必要かどうかは、COM オブジェクトのセマンティクス、インターフェイス、および実装によって異なります。
- Application スコープのロックを使用している、アプリケーション内のすべての cflock タグは、1 つのロックを共有します。したがって、Application スコープのロックを使用して頻繁にアクセスされる COM オブジェクトがある場合は、そのオブジェクトにアクセスするコードがボトルネックになり、そのオブジェクトを使用するページが多数のユーザーによってリクエストされるとスループットが低下することがあります。 COM オブジェクトを使用するコードを名前付きロックの中に入れることで、一部の競合を回避できる場合もあります。 オブジェクトを作成するコードは、Application スコープロックの中に入れる必要があります。
メモ:上記のJava プロキシによる複合 COM オブジェクトへのアクセスの説明のように、Java スタブを作成することで一部の COM オブジェクトのパフォーマンスを向上させることもできます。Java スタブを使用する方法は、COM オブジェクトを共有する方法ほどパフォーマンスは向上しませんが、すべての COM オブジェクトで使用できます。 また、COM IDispatcher インターフェイスからは適切に利用できない機能がある複雑な COM オブジェクトに正しくアクセスするには、Java スタブを生成します。 したがって、この 2 つの方法を組み合わせれば、パフォーマンスを最大限に向上させ、問題を未然に防ぐことができます。 |
例 1 : FileSystem オブジェクトの使用
次の例では、Application スコープで Microsoft FileSystem スクリプトオブジェクトを使用します。 このコードでは、システム上のすべてのハードドライブの名前と空き容量が列挙された構造体を返すユーザー定義関数を作成します。
|
例 2 : Microsoft Word アプリケーションオブジェクトの使用
次の例では、Application スコープで Microsoft Word アプリケーションの COM オブジェクトを使用して、Word ドキュメントを HTML に変換します。 コメントに記述されているように、この例は Word 2000 用です。 Word 97 で使用するには、"Val(8)" を "Val(10)" に変更します。
この例では、Application スコープロックを使用して、他のページによってオブジェクトの作成が中断されないようにしています。Word オブジェクトが存在する場合は、名前付きのロックを使用して、変換するファイルが同時にアクセスされないようにしています。
<!--- アプリケーションスコープからオブジェクトを削除する必要がある場合は、 次の行のコメントを解除します ---> <!--- <cfset structdelete(Application, "MyWordObj")> ---> <!--- GetTickCount 関数を使用して、合計処理時間を表示するために使用される 現在の時間インジケーターを取得します。---> <cfset start = GetTickCount()> <!--- 必要に応じて、Word.application オブジェクトを作成し、 Application スコープに配置します ---> <cfset WordObj_is_initialized = False> <cflock scope="application" type="readonly" timeout=120> <cfset WordObj_is_initialized = StructKeyExists(application, "MyWordObj")> </cflock> <cfif not WordObj_is_initialized > <cflock scope="Application" type="exclusive" timeout="120"> <cfif not StructKeyExists(application, "MyWordObj")> <!--- まず既存の Word オブジェクトに接続してみます ---> <cftry> <cfobject type="com" <br> action="connect" <br> class="Word.application" <br> name="Application.MyWordobj" <br> context="local"> <cfcatch> <!--- オブジェクトが存在しません。作成してください ---> <cfobject type="com" <br> action="Create" <br> class="Word.application" <br> name="Application.MyWordobj" <br> context="local"> </cfcatch> </cftry> <cfset Application.mywordobj.visible = False> </cfif> </cflock> </cfif> <!--- temp.doc の Word ドキュメントを temp.htm の HTML ファイルに変換します。---> <!--- この例では固定ファイル名を使用しているので、複数のページが同時に ファイルを使用しようとする可能性があります。ロックにより、入力ファイルの読み取り から出力ファイルのクローズまでのすべてのアクションが単一の「アトミック」操作 となり、現在のページの処理がすべて完了するまで次のページはファイルに アクセスできなくなります。 ロックの競合を減らすには、アプリケーションスコープロックの代わりに名前付きロックを使用します。---> <cflock name="WordObjLock" type="exclusive" timeout="120"> <cfset docs = application.mywordobj.documents()> <cfset docs.open("c:\CFusion\wwwroot\temp.doc")> <cfset converteddoc = application.mywordobj.activedocument> <!--- Val(8) は Word 2000 で動作します。 Word 97 では Val(10) を使用します ---> <cfset converteddoc.saveas("c:\CFusion\wwwroot\temp.htm",val(8))> <cfset converteddoc.close()> </cflock> <cfoutput> Conversion of temp.htm Complete<br> Execution Time: #int(getTickCount()-start)# milliseconds<br> </cfoutput> |