C#从DLL加载本机C ++ [英] C# form from DLL loaded by native C++

查看:134
本文介绍了C#从DLL加载本机C ++的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是一个由此线程引起的问题:

This a question arising from this thread: Native C++ use C# dll via proxy C++ managed dll

简而言之,我正在加载(我的)C#扩展到一个本机进程通过一个DLL 。扩展需要显示一个表单,以便用户可以控制它。我使用标准的.NET表单,没有第三方库或任何东西,我的表单没有显示。更糟糕的是,它挂起了目标进程。它不使用任何CPU,所以我得到等待一些功能返回的感觉,但从来没有。

In a nutshell, I'm loading (my) C# extension into a native process via a DLL. 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. 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.

另外感兴趣的是初始化方法消息框弹出,但不是测试消息框。我已经测试了我可以想到的所有东西(STAthread,线程,DisableThreadLibraryCalls,以及不同的代码位置),到每个星期天。我倾向于认为这是Win32 interop的一些晦涩的细节,但我找不到任何似乎会引起这些症状的东西。

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. 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.

看看我的代码,并指出问题是什么?

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


推荐答案

似乎目标本身是错的。它不是直接加载扩展,而是加载一个本机的exensionManager.dll,在那里,幸运的是,他们正在使用DllMain加载MY扩展名。换句话说,我正在尝试加载一个在loaderlock下的表单,并遇到一个死锁。 NET尝试加载其他程序集。

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. 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.

最后,我不得不诉诸于一个香草P / Invoke到CreateThread()直接,但窗体终于出现了。

In the end, I had to resort to a vanilla P/Invoke to CreateThread() directly, but the form is finally showing up.

这篇关于C#从DLL加载本机C ++的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆