2011-02-08 11 views
1

FortranのServerCom DLLがあります。私は自動的にtlbimpを使ってC#から直接参照できるServerCom.dllのMyFortran.dllを生成します。Fortran DLLを使用したNUnitテスト

C#クラスライブラリでは、MyFortran.dllを参照しています。

私は、MyFortran.dllを使用し、正しいマニフェストを生成したコンソールアプリケーションを作成しました(フリーインターオプトCOM環境を持つために)。

これはコンソールアプリケーションで完全に機能します。

今、私は簡単なNUnitテストを書いて、COM例外を得ました。

System.Runtime.InteropServices.COMException : Retrieving the COM class factory for component with CLSID {0FB0F699-4EF8-4732-B98E-C088825E3912} failed due to the following error: 80040154 Class not registered (Exception from HRESULT: 0x80040154 (REGDB_E_CLASSNOTREG)).

どうすればこの問題を解決できますか?

ありがとう、 Adrien。

答えて

3

はい、これは機能しません。レジストリフリーのCOMマニフェストは、COMサーバーを使用するEXEに埋め込む必要があります。あなたのコンソールアプリケーションには十分に簡単です。 EXEが単体テストランナーになっているのでNUnitを使用すると簡単ではありません。あなたはそれを混乱させることはできません。とにかく彼らの束があるので、やりにくい。

気にする必要はありません。これは、実行するテストとは関係のない展開の詳細です。テストを実行するマシンにregsvr32.exeを登録し、それを使ってサーバを登録するだけです。

0

この答えをチェックアウト:
How to do registration-free COM in a plug-in architecture

ユージンが、これは2つの方法のいずれかで可能であることを示しています
1は、DLLにマニフェストを埋め込むとISOLATION_AWARE_ENABLED
2.使用コンテキスト起動APIとコンパイル

4

これを実現するには、アクティベーションコンテキストAPIを使用できます。このblog postはすべての詳細を示します。

ここに概要があります。

がプロジェクトに(このためSpike McLartyのおかげで)次のコードを貼り付けます。

/// <remarks> 
/// Code from http://www.atalasoft.com/blogs/spikemclarty/february-2012/dynamically-testing-an-activex-control-from-c-and 
/// </remarks> 
class ActivationContext 
{ 
    static public void UsingManifestDo(string manifest, Action action) 
    { 
     UnsafeNativeMethods.ACTCTX context = new UnsafeNativeMethods.ACTCTX(); 
     context.cbSize = Marshal.SizeOf(typeof(UnsafeNativeMethods.ACTCTX)); 
     if (context.cbSize != 0x20) 
     { 
      throw new Exception("ACTCTX.cbSize is wrong"); 
     } 
     context.lpSource = manifest; 

     IntPtr hActCtx = UnsafeNativeMethods.CreateActCtx(ref context); 
     if (hActCtx == (IntPtr)(-1)) 
     { 
      throw new Win32Exception(Marshal.GetLastWin32Error()); 
     } 
     try // with valid hActCtx 
     { 
      IntPtr cookie = IntPtr.Zero; 
      if (!UnsafeNativeMethods.ActivateActCtx(hActCtx, out cookie)) 
      { 
       throw new Win32Exception(Marshal.GetLastWin32Error()); 
      } 
      try // with activated context 
      { 
       action(); 
      } 
      finally 
      { 
       UnsafeNativeMethods.DeactivateActCtx(0, cookie); 
      } 
     } 
     finally 
     { 
      UnsafeNativeMethods.ReleaseActCtx(hActCtx); 
     } 
    } 

    [SuppressUnmanagedCodeSecurity] 
    internal static class UnsafeNativeMethods 
    { 
     // Activation Context API Functions 
     [DllImport("Kernel32.dll", SetLastError = true, EntryPoint = "CreateActCtxW")] 
     internal extern static IntPtr CreateActCtx(ref ACTCTX actctx); 

     [DllImport("Kernel32.dll", SetLastError = true)] 
     [return: MarshalAs(UnmanagedType.Bool)] 
     internal static extern bool ActivateActCtx(IntPtr hActCtx, out IntPtr lpCookie); 

     [DllImport("kernel32.dll", SetLastError = true)] 
     [return: MarshalAs(UnmanagedType.Bool)] 
     internal static extern bool DeactivateActCtx(int dwFlags, IntPtr lpCookie); 

     [DllImport("Kernel32.dll", SetLastError = true)] 
     internal static extern void ReleaseActCtx(IntPtr hActCtx); 

     // Activation context structure 
     [StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Unicode)] 
     internal struct ACTCTX 
     { 
      public Int32 cbSize; 
      public UInt32 dwFlags; 
      public string lpSource; 
      public UInt16 wProcessorArchitecture; 
      public UInt16 wLangId; 
      public string lpAssemblyDirectory; 
      public string lpResourceName; 
      public string lpApplicationName; 
      public IntPtr hModule; 
     } 

    } 
} 

あなたはCOMオブジェクト(この例ではCOMObject)を作成する必要があるたびに、それを作成し、呼び出しをラップラムダ関数を使用し、UsingManifestDoに渡します。

+0

これは素晴らしい機能でした。ありがとう、サムエル! :) –

関連する問題