COM相互運用、クライアントがアウトプロセスCOMでインターフェイスを見つけられない

.net c# com-interop delphi out-of-process
COM相互運用、クライアントがアウトプロセスCOMでインターフェイスを見つけられない

Microsoftのhttp://code.msdn.microsoft.com/CSExeCOMServer-f2a59967[CSExeCOMServer]をアウトプロセスCOMサーバーのセットアップのベースとして使用していますが、正常に機能していません。 サーバーは64ビットで、クライアントは32ビットです。

これがサンプルインターフェースです

[Guid(XXCryptService.InterfaceId), ComVisible(true)/*, InterfaceType(ComInterfaceType.InterfaceIsIUnknown)*/]
public interface IXXCryptService
{
  [DispId(1)] string Encrypt(string password, string key);
  [DispId(2)] string Decrypt(string password, string key);
}

そしてクラス

[ClassInterface(ClassInterfaceType.None)]
[Guid(XXCryptService.ClassId), ComVisible(true)]
public class XXCryptService : ReferenceCountedObject, IXXCryptService
{
    internal const string ClassId =
        "C5F6938B-5593-4872-B8C7-B47EE33EABCD";
    internal const string InterfaceId =
        "6990FF5F-22E2-4032-8B98-36115DBCEFFF";

    [EditorBrowsable(EditorBrowsableState.Never)]
    [ComRegisterFunction()]
    public static void Register(Type t)
    {
        try
        {
            COMHelper.RegasmRegisterLocalServer(t);
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
            throw ex;
        }
    }

    [EditorBrowsable(EditorBrowsableState.Never)]
    [ComUnregisterFunction()]
    public static void Unregister(Type t)
    {
        try
        {
            COMHelper.RegasmUnregisterLocalServer(t);
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
            throw ex;
        }
    }

    public string Encrypt(string password, string key)
    {
      return "Encrypted";
    }

    public string Decrypt(string password, string key)
    {
      return "Decrypted";
    }

}

プログラムは実行されますが、サーバーがObjectClassFactoryでCreateInstanceをトリガーし、Marshal.GetComInterfaceForObject(new XXCryptService()、typeof(IXXCryptService))でppvObjectにオブジェクトを返し、0を返した後、クライアントが接続するとクライアントでクラッシュします。

NETでクライアントを実行すると、「タイプ ‘COMTest.XXCryptService’のCOMオブジェクトをインターフェイスタイプ ‘COMTest.IXXCryptService’にキャストできません」がトリガーされます。 IID ‘\ {6990FF5F-22E2-4032-8B98-36115DBCEFFF}’を持つインターフェイスのCOMコンポーネントでのQueryInterface呼び出しが次のエラーのために失敗したため、この操作は失敗しました:要素が見つかりません。 (HRESULTからの例外:0x8002802B(TYPE_E_ELEMENTNOTFOUND))。」
[Guid("6990FF5F-22E2-4032-8B98-36115DBCEFFF")]
//[InterfaceType(ComInterfaceType.InterfaceIsDual)]
interface IXXCryptService
{
  [DispId(1)] string Encrypt(string password, string key);
  [DispId(2)] string Decrypt(string password, string key);
}

[ComImport, Guid("C5F6938B-5593-4872-B8C7-B47EE33EABCD")]
class XXCryptService
{
}

class Program
{
  static void Main(string[] args)
  {
    XXCryptService cs = new XXCryptService();
    IXXCryptService ics = (IXXCryptService) cs;
    Console.WriteLine(ics.Encrypt("Test","Test"));
    Console.ReadKey();
  }
}

Delphiでクライアントを実行すると、EIntfCastErrorで例外がトリガーされ、「Interface not supported」というメッセージが表示されます。 COMは「タイプライブラリのインポート」でインポートされ、このように使用されます。

procedure TForm1.FormCreate(Sender: TObject);
begin
  FCrypter := CoXXCryptService.Create;
end;

TLBインターフェースは次のようになります

IXXCryptService = interface(IDispatch)
  ['{6990FF5F-22E2-4032-8B98-36115DBCEFFF}']
  function Encrypt(const password: WideString; const key: WideString): WideString; safecall;
  function Decrypt(const password: WideString; const key: WideString): WideString; safecall;
end;

// *********************************************************************//
// DispIntf:  IXXCryptServiceDisp
// Flags:     (4416) Dual OleAutomation Dispatchable
// GUID:      {6990FF5F-22E2-4032-8B98-36115DBCEFFF}
// *********************************************************************//
IXXCryptServiceDisp = dispinterface
  ['{6990FF5F-22E2-4032-8B98-36115DBCEFFF}']
  function Encrypt(const password: WideString; const key: WideString): WideString; dispid 1;
  function Decrypt(const password: WideString; const key: WideString): WideString; dispid 2;
end;

レジストリを確認しましたが、すべてが適切に登録されているようですので、なぜこの問題が発生するのか理解できません。

ここの誰もが何が問題であるかについての手がかりを持っていますか?

編集:64ビットでクライアントをコンパイルし、それは正常に動作しています。 また、間違ったパスを参照していましたが、調整した後、.NET x86クライアントで別のエラーが発生しました

IID ‘\ {6990FF5F-22E2-4032-8B98-36115DBCEFFF}’を持つインターフェイスのCOMコンポーネントでのQueryInterface呼び出しが次のエラーのために失敗したため、この操作は失敗しました:タイプライブラリ/ DLLの読み込みエラー。 (HRESULTからの例外:0x80029C4A(TYPE_E_CANTLOADLIBRARY))

  4  1


ベストアンサー

これは、登録の問題であり、アセンブリがregasmと同じターゲットを持つ場合にのみregasmが実行されるという事実でした。 IngasmServer32の代わりにLocalServer32を登録し、64ビットシステムの32ビットと64ビットの両方に登録するには、regasmに「/ com_oopまたは何か」パラメーターが必要です。

これを回避するには、実行可能ファイル(同じパス)を一時的に32ビットにコンパイルし、32ビットregasm(/ tlb:..)を実行してから、64ビットにコンパイルし直して64bit regasm(/ tlb:…​ 再び)、そして今では64ビットの実行可能ファイルに対して32ビットと64ビットの両方で適切に動作します。

CSExeComServerには、InprocServer32キーを手動で削除してLocalServer32を追加するregisterおよびunregisterメソッドがあります。 これが適切に機能することを確認するために、これを変更し、64ビットシステムで登録されているかどうかを検出し、そこで適切に登録します。 完了したら、registerメソッドに加えた変更を投稿します。

1


この問題もおそらくこれで解決します(同じ問題がありましたが、64ビットクライアントから32ビットサーバーにアクセスする場合は、代わりにCLSCTX_ACTIVATE_32_BIT_SERVERを使用できます)。

HRESULT hr = CoCreateInstance(CLSID_ZZZ, NULL, CLSCTX_LOCAL_SERVER | CLSCTX_ACTIVATE_64_BIT_SERVER, IID_IZZZ, (void ** )&l_IZZZ);

1


[ClassInterface(ClassInterfaceType.AutoDispatch)]または[
[ClassInterface(ClassInterfaceType.AutoDual)] depending on your needs to
インターフェースIXXCryptService

[ClassInterface(ClassInterfaceType.AutoDual)]
[Guid(XXCryptService.InterfaceId), ComVisible(true)/*, InterfaceType(ComInterfaceType.InterfaceIsIUnknown)*/]
public interface IXXCryptService

0


COMを介した32ビットプロセスと64ビットプロセスの混合は、すべての場合に失敗すると思います。

32ビットのDelphiプロセスからアクセスするには、DotNetアセンブリをx86としてコンパイルする必要があります(つまり、 x64としてではなく、32ビットモードで)。

AFAIK COMは32/64ビットの境界を越えません。

64ビットと32ビットの間で通信するには、https://stackoverflow.com/questions/339848/is-it-possible-to-access-a-64-bit-dll-で公開されているような別のトリックが必要です。 from-a-32-bit-application#6148647 [32ビットアプリケーションから64ビットdllにアクセスできますか?]

0


タイトルとURLをコピーしました