简体   繁体   English

来自本机C ++加载的DLL的C#表单

[英]C# form from DLL loaded by native C++

This a question arising from this thread: Native C++ use C# dll via proxy C++ managed dll 这个问题来自这个线程: Native C ++通过代理C ++管理的dll使用C#dll

In a nutshell, I'm loading (my) C# extension into a native process via a DLL. 简而言之,我通过DLL将(我的)C#扩展加载到本机进程中。 The extension needs to show a form so that the user can control it. 扩展程序需要显示一个表单,以便用户可以控制它。 I'm using standard .NET forms, no 3rd party librarys or anything, and my form is not showing up. 我正在使用标准的.NET表单,没有第三方图书馆或任何东西,我的表单没有出现。 Worse yet, it hangs the target process. 更糟糕的是,它挂起了目标进程。 It's not using any CPU, so I get the feeling its waiting for some function to return, but never does. 它没有使用任何CPU,所以我感觉它等待某些功能返回,但从来没有。

Also of interest is that the "Initialize method" message box pops up, but not the "Test" message box. 同样令人感兴趣的是弹出“初始化方法”消息框,但不弹出“测试”消息框。 I've tested everything I can think of (STAthread, threads, DisableThreadLibraryCalls, plus different code locations), every way to Sunday. 我已经测试了我能想到的所有东西(STAthread,threads,DisableThreadLibraryCalls,加上不同的代码位置),每一个星期日都是这样。 I'm inclined to think it's some obscure detail of Win32 interop, but I can't find anything that would seem to cause these symptoms. 我倾向于认为它是Win32互操作的一些模糊细节,但我找不到任何似乎会导致这些症状的东西。

Can one of you experts take a look at my code and point out what the issue is? 你们其中一位专家可以看看我的代码并指出问题所在吗?

/// <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();
   }
}

It seems that the target itself was at fault. 看来目标本身就是错误的。 It wasn't loading the extensions directly, but instead loading a native "exensionManager.dll", where, as luck would have it, they were using DllMain to load up MY extension. 它没有直接加载扩展,而是加载一个原生的“exensionManager.dll”,幸运的是,他们正在使用DllMain来加载我的扩展。 In other words, I was trying to load a form under loaderlock and ran into a deadlock as. 换句话说,我试图在加载器锁下加载一个表单并遇到死锁。 NET tried to load other assemblies. NET试图加载其他程序集。

The answer was simple, I had to show the form on a new thread. 答案很简单,我必须在新线程上显示表单。 However, .NET's threading was also hanging, as it, too, required a library load which deadlocked. 但是,.NET的线程也悬而未决,因为它也需要一个陷入僵局的库加载。

In the end, I had to resort to a vanilla P/Invoke to CreateThread() directly, but the form is finally showing up. 最后,我不得不直接使用香草P / Invoke到CreateThread(),但表格终于出现了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM