問題タブ [regfreecom]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
c++ - 登録不要の COM とドラッグ アンド ドロップ機能の間にどの関係が存在するか知っている人はいますか?
登録不要の COM とドラッグ アンド ドロップ機能の間にどの関係が存在するか知っている人はいますか?
具体的には、多数の EXE と数百の DLL で構成される巨大な C++ CAD/CAM アプリケーションがあります。それらの多くは、COM サーバー (インプロセスとアウトプロセスの両方) および/またはクライアントとして機能し、ActiveX コントロールも実装します。
ほとんどの ActiveX コントロールと、CMDIFrameWnd
いずれかの EXE のメイン ベースのウィンドウは、ドラッグ アンド ドロップ機能を実装しています。ActiveX コントロールは、ドロップ ソースとドロップ ターゲットの両方を実装します。メイン ウィンドウは、特に Windows エクスプローラーからのファイルのドロップ ターゲットのみです。
COleDataSource
ドラッグ アンド ドロップの実装は非常に標準的で、それぞれドロップ ソースとCOleDropTarget
ドロップ ターゲットから派生した 2 つのデータ メンバーに基づいています。COleDropTarget
派生メンバーは、ウィンドウのメソッドでそれぞれのウィンドウに登録されますOnCreate
。OnDragEnter
、OnDragOver
およびOnDrop
メソッドも同様にオーバーライドします。つまり、システムが提供COleDataObject
するパラメータに特定の形式 (特に CF_HDROP) を尋ね、肯定的な回答の場合、データ (ファイル パスなど) をクリップボードから抽出します。コードは次のようになります。
ドロップ ソースの実装も簡単で、次のようになります。
ここで、関数はドラッグされたデータを収集し、パックして、オブジェクトのインターフェイスからメソッドをprv_BeginDrag()
呼び出してクリップボードに置きます。SetData
m_pOleDataSource
IDataObject
アプリケーション全体を登録不要にすることが決定されるまで、これらすべては完全に機能していました。マニフェストを埋め込み、アウトプロセス COM サーバーをオンデマンドで起動し、いくつかのクラスの CLSID を変更して、起動された同じサーバーのインスタンスを別のサーバーから分離することにより、アプリケーションを (COM コンポーネントの登録なしで) 強制的に分離して実行するのに 3 か月かかりました。フォルダ。ついに機能し始めましたが、私の変更に触れていなかったにもかかわらず、ドラッグ/ドロップ機能はありませんでした。
ドロップ ターゲット側では、Windows エクスプローラーからファイルをドラッグすると、上の呼び出しでCOleDataObject::IsDataAvailable
false が返されますが、変更前は true が返されます。同時に、メイン ウィンドウの OnCreate メソッドに 1 行のコード " " を追加すると、標準の CFrameWnd のメッセージ ハンドラDragAcceptFiles();
を介してドラッグ アンド ドロップが機能し始めます。WM_DROPFILE
ドロップ ソース側では、ドラッグされたデータは正常にパックされてクリップボードに配置されますが、 MFC 実装内の API への呼び出しが REGDB_E_CLASSNOTREG "クラスが登録されていません" という結果を返すCOleDataSource::DoDragDrop
ため、メソッドは失敗します。::DoDragDrop
これは、COM アクティベーションの変更が何らかの形でドラッグ/ドロップ動作に影響することを意味します。どのように?
PS 1) Windows エクスプローラーからファイルをドラッグする EXE のプロジェクト プロパティには、「UAC 実行レベル = asInvoker」があります。私が理解している限りでは、ファイルをダブルクリックして起動すると、EXE が Windows エクスプローラーと同じ UAC レベルで実行されることがわかります。
2) 非常に驚くべきことに、ドラッグ アンド ドロップは上記の症状で機能しなくなりましたが、コピー アンド ペーストは、両方のテクノロジの実装が類似しているにもかかわらず、引き続き正常に機能します。
3) ::DoDragDrop API がいつ「クラスが登録されていません」というエラーを返すのか、どのクラスを探しているのかがわかれば、問題を解決できると思います。
助けてくれてありがとう、イリア。
c# - Regfree COM イベントが他のスレッドから失敗する
イベントを公開し、VB6 から使用される COM 可視 .NET クラスがあります。ここ数日間、これを regfree COM で動作させようとしましたが、成功しませんでした。
- イベントが元のスレッドから起動されると、VB6 イベントは regfree モードで実行されます。
- VB6 イベントは、typelib が登録されているときに別のスレッドから発生したときに実行されます。(regasm /tlb /codebase の後に regasm /codebase /unregister が続きます。後者は tlb の登録を解除しません)
regfree モードで別のスレッドから起動すると、例外がスローされるため、VB6 イベント コードは実行されません。
考えられるシナリオは 2 つあります。1) マニフェストに tlb 登録に関連する何かが欠落している、または 2) 新しいスレッドの作成時にアクティベーション コンテキストが失われている。残念ながら、どちらが原因なのか、または別の原因である可能性があるかどうかを確認する方法がわかりません。
以下は、私の問題を示す基本的な例です。
マニフェスト (VB6 実行可能ファイル)
マニフェスト (C# DLL)
C# (プラットフォーム ターゲット: x86)
VB6
com - side-by-side アセンブリに対する VB6 コンパイル
C# で記述された DLL があり、COM の可視性が設定されています。サイド バイ サイド アセンブリとしてセットアップし、アプリケーションをクライアント PC に登録なしで正常に展開できます。私の質問は、開発用 PC に関するものです。同様の登録不要の方法で DLL に対してコンパイルすることは可能ですか、それとも開発マシンで登録が必要ですか? メニューからDLL を直接追加しようとしましたが、Project -> References
「特定のファイルへの参照を追加できません」というエラーが表示されます。DLL は .vbp ファイルと同じディレクトリにあり、クライアント アプリ マニフェストが存在する場合と存在しない場合の両方で DLL を追加しようとしました。
c# - 登録不要の COM マニフェストをネイティブ/マネージド環境で C# dll に埋め込む
私は現在、登録不要の COM を採用したネイティブ/マネージド アプリケーション チェーンの開発に取り組んでいます。次の図はこれを示しています。
C# ラッパー DLL は、tlbimp.exe ユーティリティを使用して作成されています。これにより、各 C# 実行可能ファイルが COM DLL のネイティブの型とメソッドにアクセスできるようになります。COM DLL 自体は、サーバー ベースの RegFree COM マニフェストを採用しています。
クライアント ベースの RegFree COM マニフェストが C# 実行可能ファイルに埋め込まれている場合、すべてが正常に機能します。ただし、これらのマニフェスト ファイルを C# DLL に移動して統合したいと考えています。これにより、バージョン情報の保守と同期が大幅に容易になります。
Visual Studio にはマニフェスト ファイルを C# クラス ライブラリに埋め込むオプションが用意されていないため、マニフェスト ツール (mt.exe) を使用して、DLL の既定のマニフェストを抽出、変更、および再埋め込みしようとしました。mt でクエリを実行すると、C# DLL が次のマニフェストを公開するようになったため、これはうまくいったようです。
ただし、実行可能ファイルは動作を拒否し、COM クラス ファクトリが欠落している COM モジュールを見つけることができないと不平を言っています。
ここで見落としているものはありますか?ありがとう。
c# - 登録不要の COM 相互運用性: ファイナライザーでアクティブ化コンテキストを非アクティブ化すると、SEHException がスローされる
現在、マネージド/ネイティブ ワーク チェーンが混在する作業を行っており、登録不要の COM サポート用のアクティベーション コンテキストを作成する必要があります (ネイティブ/マネージド環境で C# dll に登録不要の COM マニフェストを埋め込む を参照)。次のスニペットは、C# DLL 内のより大きなクラスの一部であり、COM ラッパーへの参照を保持し、必要なアクティベーション コンテキストを確立します。
問題は、メソッド内の pinvokedDeactivateActCtx()
関数にありDestroyActivationContext()
ます。呼び出されるとすぐにSEHException
、例外がスローされます: 外部コンポーネントが例外をスローしました。0x80004005。
Marshal.GetLastWin32Error()
関数を介して利用できるエラー コードはありません。これにより、妥当な情報が得られます。
私がこれまでに試したこと:
DestroyActivationContext()
関数をデストラクタからDispose
メソッドに、またはその逆に移動します。IDisposable
インターフェイスを完全に削除します。- 基になる COM オブジェクトのスレッド モデルを Apartment から Free に変更します。
- 入力引数として
DeactivateActCtx()
関数を提供します。DEACTIVATE_ACTCTX_FLAG_FORCE_EARLY_DEACTIVATION
IntPtr
インスタンスのタイプを に変更しますUIntPtr
。
残念ながら、これらのオプションはどれも役に立ちませんでした。前述のことに直面せずにアクティベーションコンテキストを無効にする方法はありますSEHException
か?
アップデート
ガベージコレクタのスレッドが問題の原因のようです。GC は常に独自のスレッドで実行され、他に指定する可能性は明らかではありません。DeactivateActCtx
この特定のスレッドからアクティベーション コンテキスト ( ) を非アクティブ化しようとすると、内部で何らかのアクセス違反が発生しているようです。したがって、ラップされた各呼び出しでアクティブ化コンテキストをアクティブ化および非アクティブ化する以外に、この厄介さに対処する簡単な方法はないと思います。そうでないことを証明する提案は、まだ大歓迎です。
com - 登録不要の COM と同じインターフェイスの複数のオファー
同じインターフェースのセットを提供する一連のコンポーネントがあります。登録不要の COM を使用するクライアント コードの可能性を調査しているときに、この問題に遭遇しました。ユーザーが提供する構成に応じて、1 つのクライアントが同じインターフェイスの異なる実装を使用する場合があります。したがって、これらのコンポーネントごとに依存関係を含める必要があります。これらの各コンポーネントには、エクスポートされたコンポーネント インターフェイスを登録する comInterfaceProxyStub 要素が含まれています。つまり、同じインターフェースのセットをエクスポートする comInterfaceProxyStub を持つ多くのコンポーネントがあり、それらはすべて実装されています。この事実がアクティベーション時にエラーを引き起こすようです。ststrace.exe は明確ではありませんが、「再登録」を拒否しているようです。何が欠けていますか?既に「登録済み」のインターフェイスの comInterfaceProxyStub 要素を使用して 2 番目のコンポーネントをアクティブ化しようとするとエラーになるのでしょうか?