frog.raindrop.jp.knowledge > COM, COM+ プログラミング
COM, COM+, DCOMとか、その他その辺。

December 26, 2005

.NET の属性を使用して、Enum と Struct をタイプライブラリに含める方法

.NET で ATL を使用して COM DLL を作成しようとして・・・唖然としました。VC++ 6.0 で ATL COM ウィザード使ってたときと全く生成されるコードが違う・・・。一番の大きな違いは「属性」なるものが追加されたこと。宣言の前に大カッコでくくって指定するようです。

なんとか COM DLL を作り上げて、実装担当者に渡したところ、enum や struct をタイプライブラリにどうやって含めたのか聞かれました。これは私もドキュメントが見つけられず、試行錯誤ののち実装したもの。一応、以下のようにするとできますが、この方法で正しいのかわからない部分です。

#ifndef __EXPORTS__H
#define __EXPORTS__H

[
    export,         // タイプライブラリにエクスポートします
    v1_enum,        // 32bit 値の列挙型としてコンパイルします
    library_block,  // タイプライブラリの library ブロック内に配置します
    helpstring ("この enum は、タイプライブラリに含まれます。"),
]
enum ExportEnum
{
    nExportEnumValue1,
    nExportEnumValue2,
    nExportEnumValue3,
};

[
    export,         // タイプライブラリにエクスポートします
    library_block,  // タイプライブラリの library ブロック内に配置します
]
struct EXPORT_STRUCT
{
    long            nExportStructMember1;
    BYTE            ExportStructMember2 [10];
    VARIANT_BOOL    bExportStructMember3;
    BSTR            bstrExportStructMember4;
};


#endif  //__EXPORTS__H

February 20, 2005

WSH よりクリップボードを使う

最近のバージョンの IE ではセキュリティが厳しくなったためこの手法は使いづらくなりました。
[WSH よりクリップボード、次の手] も参照してみてください。(2010.10.08)

WSH よりクリップボードにアクセスすることはできない。しかし、調べてみたところ、Internet Explorer がクリップボードにアクセスするためのインターフェースを公開していることがわかった(常套手段?)。

そんなわけで、文字列をコピー & 取得する部分をクラス化した。

使い方はこんな感じで。

var clipboard = new Clipboard ();
var s = clipboard.getText ();
WScript.Echo (s);
clipboard.setText (s.replace (/my/gi, "Your"));
続きを読む...

December 21, 2004

IDL ファイルのコンパイル時に MIDL2039 の警告が出る

VC++6.0 (5.0もらしいけど) で、ATL COM AppWizard プロジェクトを作成し、挿入 - ATLオブジェクトの新規作成を選択して、何かコントロールを追加する。コントロールの設定で、ストックプロパティを追加するときに、Font を含めてみよう。

warning MIDL2039 : interface does not conform to [oleautomation] attribute : [ Parameter 'pFont' of Procedure 'putref_Font' ( Interface 'IMyControl' ) ]
warning MIDL2039 : interface does not conform to [oleautomation] attribute : [ Parameter 'pFont' of Procedure 'put_Font' ( Interface 'IMyControl' ) ]
warning MIDL2039 : interface does not conform to [oleautomation] attribute : [ Parameter 'ppFont' of Procedure 'get_Font' ( Interface 'IMyControl' ) ]

とまあ、警告がずらずら。この件は、MS のサポート技術情報にも、FIX: MIDL2039 Warning with IFontDisp/IPictureDisp Parameter Type として取り上げられている。

続きを読む...

October 29, 2004

Main Apartment Must Not Exit While Process Does OLE Work

Main Apartment Must Not Exit While Process Does OLE Work
Article ID
137630
Last Review
December 1, 2003
Revision
2.0
This article was previously published under Q137630
In OLE's apartment threading model, the main apartment of the process is the thread that first calls OleInitialize (or CoInitialize) either implicilty or explicitly. The main apartment must not exit until completion of all OLE work in the process.

December 6, 2003

OLE DB プロバイダ 'MSDAORA.1' のインターフェイスを作成できませんでした

実機セットアップのため、Windows 2000 Serverに、新たにMSDEとOracle Clientをインストールして、MSDEにデータベースを作成し、Oracleのリンクサーバを作成しました。

そして、MSDEから使用するためOracleの表をビューとして作成しようとするとこんなエラーが。

1>SELECT * FROM DB_SVR..USER_FOO.TABLE_BAR
2>GO
メッセージ 7302、レベル 16、状態 1、サーバー TESTSRV、行 1
OLE DB プロバイダ 'MSDAORA.1' のインターフェイスを作成できませんでした。
1>

インターフェースと言う言葉から想像するに、COM回りのエラーであろうと想像は付くのですが(OLE DBってCOMですから)MDACの再インストールを行っても、MSDEの再インストールを行っても解決しませんでした。

一応、
280106 - [HOWTO] SQL Server で Oracle へのリンク サーバーのセットアップおよびトラブルシューティングを行う方法[support.microsoft.com]
に情報がありますが、REGSVR32で確認する前にMDACの再インストールをしたので、あまり有用な情報とは思えませんでした。

だいぶん長いこと試したのですが、結局は、

  1. コントロールパネル→管理ツール→コンポーネント サービス を開く
  2. ツリーの コンポーネント サービス>コンピュータ>マイ コンピュータ を右クリックして、プロパティを表示する
  3. 規定のセキュリティ タブの、規定のアクセス許可 で、規定値の編集 を押下しレジストリ値のアクセス許可 ウインドウを表示する
    ちなみにWindows Xpでは、ここではディレクトリセキュリティを編集するみたいな画面が出てきた記憶があるが、2000系はちょっと違うらしい。
  4. 追加 を押下し、ユーザーとグループの追加 ダイアログでEveryoneを選択して追加を押下し、OKする

で、ビューが作成できるようになりました。Everyoneでなく、MSDEサービスがどのユーザの権限で実行されるのか調べて設定し直さなくてはいけないのですが、それはまたあとで。とりあえず原因は権限不足、だったみたいです。

2003.12.08 追記
SYSTEMアカウントに対し、権限を追加すればOKです。

November 30, 2003

外部シンボル "_main" は未解決です

ATL COM AppWizard でActiveX DLLを作成して、DebugでビルドしてVBで作ったチョンプロからコールしてOK、よし、Releaseビルドだ!と、アクティブな構成の設定で「Win32 Release MinDependency」を選択してビルドするとこんなエラーがでました。

LIBCMT.lib(crt0.obj) : error LNK2001: 外部シンボル "_main" は未解決です
ReleaseMinDependency/PrivateProfiles.dll : fatal error LNK1120: 外部参照 1 が未解決です。
link.exe の実行エラー

PrivateProfiles.dll - エラー 2、警告 0

Debugビルドでは通っていたので、なにかビルドの設定だろうとは思うのですが、よく分かりません。こういうときは、同じようなエラーの情報がないか、検索してみるに限ります。basp21のBabaさんのサイトにそのものズバリの情報がありました。以下はCOM プログラミング2[Baba Centerfolds]からの引用。

このエラーは、Cランタイム関数がリンクされていないときに発生します。
Cのランタイム関数をプロジェクト内で使っていると発生します。
ReleaseビルドのデフォルトではATL COM AppWizardは、Cランタイムをリンクしません。
これは、_ATL_MIN_CRTプリプロセッサ文字が指定されているためです。
対策としては:
●[プロジェクトの設定] -[C/C++]-[プリプロセッサの定義]で_ATL_MIN_CRTを削除
こうするとCのランタイムがリンクされてエラーが消えます。

ふむふむ。確かに、LocalFree関数を使っていました。早速プリプロセッサの定義を直し、解決しました。

November 19, 2003

ASPからコールするCOMコンポーネント

VBでASPからコールするActiveX DLLやActiveX EXEを作成する場合のポイントらしきものです。

  1. データ型

    ASPで使用するスクリプト言語は型がありません。したがって

    • 引数はByValで
    • ByRefで渡す引数はVariantに
    と言う感じにします。
  2. プロジェクトのプロパティ
    • 「対話型インターフェースの抑制」にチェック
    • 「メモリに保持」にチェック
    • スレッドモデル
      • スコープがApplication---シングル スレッド
      • スコープがSession-------アパートメントスレッド
      で作成します。このあたり、VC++で作成すると「Both」が選択できた気がしますが、VBでそれに当たるのはないのかな?
  3. ASP組み込みオブジェクトへのアクセス

    以下の2つに参照設定を行って、ASPからと同じように、Response.Writeでクライアントへの出力を行ったり、Request.ServerVariablesで環境変数を取得したりすることができます。

    • COM+ Services Type Library(Win2K以降の場合。9xやNTは)
    • Microsoft Active Server Pages Object Library

    ASP組み込みオブジェクトにアクセスするには、GetObjectContextメソッドを使います。Responseオブジェクトを例に取ると

    Dim aspResponse         As ASPTypeLibrary.Response
    
        Set aspResponse = GetObjectContext("Response")
        Call aspResponse.Write("Hello ASP!")
    		

    と言うような感じです。このとき、クラスのMTSTransactionModeプロパティが、"NotAnMTSObject"ではうまくいきませんでした。"Uses Transaction"にするとうまくいきましたが、どういう値であるべきかまでは調べていません。

    また、この処理を、Class_Initiarizeプロシージャに記述したオブジェクトを、Global.asa内で生成したり、アプリケーションスコープのobjectタグで宣言すると、うまく動作しないようです。

(04/01/24 追記)

Applicationスコープにするには、スレッドモデルがBothまたはNeutralのコンポーネントを作成する必要があります。つまり、VBで作成することはできません。