Visual Basic 6.0应用程序在打开.NET表单时无法关闭。相反,它会显示“无法退出”消息。

4
我有一个使用多个由.NET编写的组件的Visual Basic 6.0应用程序。当Windows关闭时,该应用程序必须正常关闭。问题是,如果代码的.NET部分正在显示窗口,则应用程序会显示消息"无法退出"并无法退出。(然后被操作系统终止。)
我已成功地在简化的应用程序中重现了这个问题。
.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表单时尝试关闭计算机,将无法成功。"无法退出"消息框看起来 像这样
要重新创建此操作,您必须将程序集标记为COM可见(在文件assemblyinfo.cs中):
[assembly: ComVisible(true)]

你需要在“项目属性-构建”选项卡中设置“注册COM互操作”

我还使用以下方式注册已编译的程序集:

regasm ShutdownTestLibrary.dll /tlb ShutdownTestLibrary.tlb

我该如何解决这个问题?

3个回答

1
如果您在任何窗口上调用ShowDialog(),它将阻塞该线程,直到窗口关闭(由用户或代码关闭)。
您可能需要在.NET上为COM接口创建一个方法来关闭窗口,或者以某种方式获取Visual Basic中窗口的句柄来关闭窗口。

但是操作系统关闭时不应该关闭所有打开的窗口吗?(我认为它会向所有打开的窗口发送QuerySessionEnd和SessionEnd消息,导致它们关闭)。如果您使用ShowDialog()创建一个具有2个窗口的纯.NET应用程序,当操作系统关闭时它仍然会自动关闭。 - Simon P Stevens
2
操作系统向所有顶级窗口发送此命令,然后它们依次关闭其子窗口。由于您的顶级窗口是VB,它可能不知道如何关闭您的.Net窗口。它只知道它的主线程被阻塞了。 - jonathanpeppers

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)

0

以下任一方法都可以解决您的问题:

  • 确保您的 .NET 窗口已设置 Text/Name 属性。我知道有时这会导致此类问题。
  • 将 .NET 窗口的所有者设置为您的 Visual Basic 窗口。使用 user32.dll 中的 SetParent 函数。
  • 在您的 .NET 库中钩入 Microsoft.Win32.SystemEvents.SessionEnding 并关闭窗口。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接