5

これは、このスレッドから生じる質問です: Native C++ use C# dll via proxy C++ managed dll

簡単に言えば、(私の) C# 拡張機能を DLL 経由でネイティブ プロセスにロードしています。拡張機能は、ユーザーが制御できるようにフォームを表示する必要があります。標準の .NET フォームを使用していますが、サード パーティのライブラリなどは使用していません。フォームが表示されません。さらに悪いことに、ターゲット プロセスがハングします。CPU を使用していないので、関数が戻るのを待っているような気がしますが、戻りません。

また、「メソッドの初期化」メッセージ ボックスが表示されますが、「テスト」メッセージ ボックスは表示されないことも興味深い点です。考えられるすべて (STAthread、スレッド、DisableThreadLibraryCalls、およびさまざまなコードの場所) を、日曜日まですべてテストしました。これは Win32 相互運用性のあいまいな詳細だと思いがちですが、これらの症状を引き起こすと思われるものは何も見つかりません。

あなたの専門家の 1 人が私のコードを見て、問題が何であるかを指摘できますか?

/// <summary>
/// Provides entry points for native code
/// </summary>
internal static class UnmanagedExports
{
   [UnmanagedFunctionPointer(System.Runtime.InteropServices.CallingConvention.StdCall)]
   public delegate int SendRecv([MarshalAs(UnmanagedType.SafeArray)]byte[] ByteArray, UInt64 Len);

   [STAThread]
   [DllExport("Initialize", CallingConvention.StdCall)]
   public static int Initialize(IntPtr hInstance, SendRecv Send, SendRecv Recv)
   {
       return DLLinterface.Initialize(hInstance, Send, Recv);
   }

   [DllExport("Terminate", CallingConvention.StdCall)]
   public static void Terminate()
   {
       DLLinterface.Terminate();
   }
}

internal class DLLinterface
{
   static System.Threading.Thread uiThread;

   [STAThread]
   internal static int Initialize(IntPtr hInstance, UnmanagedExports.SendRecv Send, UnmanagedExports.SendRecv Recv)
   {
       MessageBox.Show("Initialize method");
       try
       {
           uiThread = new System.Threading.Thread(Run);
           uiThread.Start();
       }
       catch (Exception ex)
       {
           MessageBox.Show("Failed to load: " + ex.Message, "Infralissa error", MessageBoxButtons.OK, MessageBoxIcon.Error);
       }
       return 1;
   }

   [STAThread]
   private static void Run()
   {
       MessageBox.Show("Test");

       Application.EnableVisualStyles();
       Application.SetCompatibleTextRenderingDefault(false);
       Application.Run(new Form1());
   }

   internal static void Terminate()
   {
       MessageBox.Show("Terminating.");
       if (uiThread.IsAlive)
           uiThread.Abort();
   }
}
4

1 に答える 1

2

ターゲット自体が間違っていたようです。拡張機能を直接ロードするのではなく、ネイティブの「exensionManager.dll」をロードします。運が良ければ、DllMain を使用して MY 拡張機能をロードしていました。つまり、ローダーロックの下でフォームをロードしようとしていて、デッドロックに遭遇しました。NET が他のアセンブリを読み込もうとしました。

答えは簡単で、新しいスレッドでフォームを表示する必要がありました。ただし、.NET のスレッド化も、デッドロックするライブラリのロードを必要とするため、ハングしていました。

最終的に、CreateThread() へのバニラ P/Invoke を直接使用する必要がありましたが、最終的にフォームが表示されます。

于 2012-07-04T04:17:58.597 に答える