.NET窗体打开时,Visual Basic 6.0应用程序不会关闭。而是显示消息“无法退出”

时间:2009-08-10 15:10:35

标签: c# vb6 interop shutdown

我有一个Visual Basic 6.0应用程序,它使用.NET中编写的几个组件。当Windows关闭时,应用程序必须正常关闭。问题是,如果代码的.NET部分显示窗口,则应用程序显示消息"Cannot Quit"并且无法退出。 (然后由操作系统终止。)

我已经设法在简化的应用程序中重现了这一点。

.NET代码创建一个WPF窗口并使用ShowDialog()显示它:

[Guid("5F3D0B23-2196-4082-B9DE-B208C61FE89F")]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface IComShutdownTest
{
    [DispId(1)]
    void RunTest();
}

[Guid("E6613EDD-D51B-42c0-AA5B-5961AB28D063")]
[ClassInterface(ClassInterfaceType.None)]
[ProgId("ShutdownTest")]
public class ShutdownTest : IComShutdownTest
{
    public ShutdownTest() 
    {  }

    public void RunTest()
    {
        TestWindow testWindow = new TestWindow();
        bool? dialogResult = testWindow.ShowDialog();
    }
}

正如你可以看到.NET调用块(并且在GUI线程上),我怀疑这可能是问题的根源,但我无法绕过使所有调用无阻塞。我会假设当操作系统关闭时,所有打开的应用程序窗口都会终止。

Visual Basic 6.0应用程序通过单击按钮加载并显示.NET表单。

Private Sub ButtonTest_Click()

    LogEventToFile "Starting"
    Dim dotNetTestObject As ShutdownTest

    LogEventToFile "Creating"
    Set dotNetTestObject = New ShutdownTest

    LogEventToFile "Running"
    dotNetTestObject.RunTest

    LogEventToFile "Done"

End Sub

如果您在屏幕上显示.NET表单时尝试关闭PC,则会失败。 “无法退出”消息框显示like this

要重新创建此项,您必须将程序集标记为COM可见(在文件assemblyinfo.cs中):

[assembly: ComVisible(true)]

您必须将Project-> Properties> Build标签设置为“Register for COM interop”

我还注册了编译的程序集:

regasm ShutdownTestLibrary.dll /tlb ShutdownTestLibrary.tlb

如何解决此问题?

3 个答案:

答案 0 :(得分:1)

如果在任何窗口上调用ShowDialog(),它会在该窗口上阻塞,直到窗口关闭(来自用户或代码)。

您可能必须在COM接口上创建一个方法来关闭.NET中的窗口,或以某种方式在Visual Basic中获取窗口的句柄以关闭窗口。

答案 1 :(得分:0)

以下其中一项应解决您的问题:

  • 确保您的.NET窗口设置了文本/名称属性。我知道这有时会引起这样的问题。
  • 将.NET窗口的所有者设置为Visual Basic窗口。使用user32.dll中的SetParent函数。
  • 在.NET库中挂钩进入Microsoft.Win32.SystemEvents.SessionEnding并关闭窗口。

答案 2 :(得分:0)

您可以尝试将父窗口作为.NET方法的参数,这样当父级尝试关闭时,.NET组件会收到通知。

public void RunTest(IWin32Window owner)
{
    TestWindow testWindow = new TestWindow();
    bool? dialogResult = testWindow.ShowDialog(owner);
}

在Visual Basic 6.0代码中:

Call dotNetTestObject.RunTest(Me.hWnd)