4

アウトプロセス COM サーバーをセットアップするためのベースとしてMicrosoft のCSExeCOMServerを使用していますが、正しく動作しません。サーバーは 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}' は次のエラーのために失敗しました: Element not found. (Exception from 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

4 に答える 4

1

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

これを回避するには、実行可能ファイルを (同じパスで) 一時的に 32 ビットにコンパイルし、32 ビット regasm を (/tlb:.. を使用して) 実行し、次に 64 ビットにコンパイルし直して、64 ビット regasm (/tlb:.. を使用して再度) を実行する必要がありました。 )、64 ビット実行可能ファイルに対して 32 ビットと 64 ビットの両方で適切に動作するようになりました。

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

于 2011-08-02T07:13:08.263 に答える
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);
于 2013-09-11T12:42:55.390 に答える
0

IXXCryptService とインターフェースする必要に応じて、[ClassInterface(ClassInterfaceType.AutoDispatch)] または [ClassInterface(ClassInterfaceType.AutoDual)] を追加してみてください。

[ClassInterface(ClassInterfaceType.AutoDual)] 
[Guid(XXCryptService.InterfaceId), ComVisible(true)/*, InterfaceType(ComInterfaceType.InterfaceIsIUnknown)*/]
public interface IXXCryptService
于 2011-08-01T13:26:52.523 に答える
0

COM 経由で 32 ビット プロセスと 64 ビット プロセスを混在させると、すべての場合に失敗すると思います。

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

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

64 ビットと 32 ビットの間で通信するには、 Is it possible to access a 64-bit dll from a 32-bit application? で公開されているような別のトリックが必要になります。

于 2011-08-01T13:26:55.440 に答える