.net 长挂

.net 长挂,.net,winapi,vb6,interop,pinvoke,.net,Winapi,Vb6,Interop,Pinvoke,为什么SetWindowLong(myForm.hWnd,GWL\u hwndpent,parentHwnd)hang 我可以通过这三个步骤不断地重现这个问题 创建.NET表单 初始化WaitWindow COM对象,在传递.NET窗体句柄时调用COM对象上的ShowWindow 在VB6中调用SetWindowLong方法 C#Windows应用程序(挂起) C#控制台应用程序(不挂起) VB6代码段 Public Sub ShowWindow(ByVal parentHwnd As Long

为什么
SetWindowLong(myForm.hWnd,GWL\u hwndpent,parentHwnd)
hang

我可以通过这三个步骤不断地重现这个问题

  • 创建.NET表单
  • 初始化WaitWindow COM对象,在传递.NET窗体句柄时调用COM对象上的ShowWindow
  • 在VB6中调用SetWindowLong方法
  • C#Windows应用程序(挂起)

    C#控制台应用程序(不挂起)

    VB6代码段

    Public Sub ShowWindow(ByVal parentHwnd As Long, ByVal language As Language)
    
        SetWindowLong(myForm.hWnd, GWL_HWNDPARENT, parentHwnd)  'Hangs Here
        CenterWindow (parentHwnd)
    
        myForm.ShowRetrieving (language)
        myForm.Show (vbModal)
    End Sub
    
    非常感谢您的帮助:)

    编辑

    我确实理解不应该调用SetWIndowLong来更改父级,但我试图理解为什么只有在使用.NET表单句柄时它才会挂起

    EDIT2


    我现在相信这个问题与SetWindowLong无关,而是与实际句柄本身有关。我仍在调查,但当我从.NET调用VB6代码时,它似乎创建了一个RPC线程。我还不确定,但我感觉这与交叉线程问题有关。

    MSDN文档清楚地说明了这一点

    不能使用GWL_HWNDPARENT索引调用SetWindowLong来更改子窗口的父窗口。相反,请使用SetParent函数


    您是否在64位系统中运行此功能?您的VB6应用程序是32位应用程序吗?如果您陷入这种情况,它将解释为什么创建RPC调用,以及为什么您的非法黑客it无法工作。如果是这样的话,坏消息是现在有办法让它发挥作用


    您还应该知道.net控件的下划线窗口句柄。关于这件事的讨论,请参见SO中的内容。

    我设法弄清楚到底发生了什么以及如何解决问题。我没有用[StatThread]属性指定我的主入口点,所以它默认为MTA。这意味着当我调用VB6代码时,它创建了一个RPC回调线程,而没有将调用打包到UI执行的主线程

    Peter Mortensen为此写了一篇文章:

    STA模型用于非线程安全的COM对象。那个 意味着它们不处理自己的同步。常用 这是一个UI组件。因此,如果另一个线程需要与 对象(如按下表单中的按钮)则消息 编组到STA线程上。窗口形成消息泵 系统就是一个例子


    我确实读了文档,虽然它没有说明为什么不应该调用它。我忘了提到我无法修改VB6代码,因为它是许多模块引用的现有代码。我很好奇为什么它能工作,除非我给它一个.NET表单句柄。可能是因为这会导致发送消息。尝试使用windbg为每个线程获取堆栈转储。另请参见MS不需要解释您不能这样做。他们告诉你不要这样做,所以不要。注意:我无法更新代码中的VB6部分,因为这是现有系统的一部分,并且在这种特定情况下一直工作“良好”。感谢上帝,我在Windows XP SP3 32位中运行所有程序。。。他的项目已经够让人头疼的了:p。谢谢你的建议。
    private static void Main(string[] args)
    {
          IntPtr handle = Process.GetCurrentProcess().MainWindowHandle;     
    
          Interop.WaitWindow waitWindow = new Interop.WaitWindow();
          waitWindow.ShowWindow(handle.ToInt32(), Language.RISEnglish);
    }
    
    Public Sub ShowWindow(ByVal parentHwnd As Long, ByVal language As Language)
    
        SetWindowLong(myForm.hWnd, GWL_HWNDPARENT, parentHwnd)  'Hangs Here
        CenterWindow (parentHwnd)
    
        myForm.ShowRetrieving (language)
        myForm.Show (vbModal)
    End Sub