.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
我可以通过这三个步骤不断地重现这个问题
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