4

.NETで記述された複数のコンポーネントを使用するVisual Basic 6.0アプリケーションがあります。Windows がシャットダウンされると、アプリケーションは正常にシャットダウンする必要があります。問題は、コードの .NET 部分がウィンドウを表示している場合、アプリケーションが「終了できません」というメッセージを表示し、終了に失敗することです。(その後、OSによって終了されます。)

簡略化されたアプリケーションでこれを再現することができました。

.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 スレッド上にあります)、これが問題の原因であると思われますが、すべての呼び出しを非ブロックにすることはできません。OS がシャットダウンすると、開いているすべてのアプリケーション ウィンドウが終了すると想定していました。

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 をシャットダウンしようとすると、失敗します。「終了できません」というメッセージ ボックスは次のようになります

これを再作成するには、アセンブリをCOM可視としてマークする必要があります (ファイル内assemblyinfo.cs):

[assembly: ComVisible(true)]

Project->Properties>Build タブを「Register for COM interop」に設定する必要があります。

また、コンパイルされたアセンブリを次のように登録しました。

regasm ShutdownTestLibrary.dll /tlb ShutdownTestLibrary.tlb

この問題を解決するにはどうすればよいですか?

4

3 に答える 3

1

任意のウィンドウでShowDialog()を呼び出すと、ウィンドウが閉じるまで(ユーザーまたはコードから)そのスレッドでブロックされます。

おそらく、.NETでウィンドウを閉じるには、COMインターフェイスでメソッドを作成するか、VisualBasicでウィンドウのハンドルを取得してウィンドウを閉じる必要があります。

于 2009-08-10T16:39:23.820 に答える
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)
于 2009-09-11T11:22:53.587 に答える
0

次のいずれかで問題が解決するはずです。

  • .NETウィンドウに Text/Name プロパティが設定されていることを確認してください。これが時々このような問題を引き起こすことを私は知っています。
  • .NET ウィンドウの所有者を Visual Basic ウィンドウに設定します。で SetParent 関数を使用しuser32.dllます。
  • .NET ライブラリで Microsoft.Win32.SystemEvents.SessionEnding にフックし、ウィンドウを閉じます。
于 2009-08-11T13:12:25.820 に答える