2009-08-10 4 views
4

J'ai une application Visual Basic 6.0 qui utilise plusieurs composants écrits en .NET. L'application doit s'éteindre gracieusement lorsque Windows est arrêté. Le problème est que si la partie .NET du code affiche une fenêtre, l'application affiche le message "Cannot Quit" et ne parvient pas à quitter. (Il est ensuite terminé par le système d'exploitation.)L'application Visual Basic 6.0 ne s'arrête pas lorsque le formulaire .NET est ouvert. Au lieu de cela, il affiche le message "Can not Quit"

J'ai réussi à reproduire cela dans une application simplifiée.

Le code .NET crée une fenêtre WPF et affiche à l'aide 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(); 
    } 
} 

Comme vous pouvez voir les blocs d'appel .NET (et est sur le fil GUI), et je soupçonne que cela peut être la racine du problème, mais je ne peux pas faire le tour de tous mes appels non bloquants. J'aurais supposé que lorsque le système d'exploitation se ferme, toutes les fenêtres d'application ouvertes sont terminées.

L'application Visual Basic 6.0 charge et affiche le formulaire .NET à partir d'un clic de bouton. Si vous tentez d'arrêter le PC alors que le formulaire .NET est à l'écran, il échoue. La boîte de message "Impossible de quitter" s'affiche like this.

Pour recréer cela, vous devez marquer l'assemblage comme COM visible (dans le fichier assemblyinfo.cs):

[assembly: ComVisible(true)] 

et vous devez définir les propriétés Projet->> Créer onglet "enregistrer pour COM Interop"

Je

également enregistré l'assembly compilé avec:

regasm ShutdownTestLibrary.dll /tlb ShutdownTestLibrary.tlb 

Comment puis-je résoudre ce problème?

Répondre

1

Si vous appelez ShowDialog() sur n'importe quelle fenêtre, il bloque sur ce thread jusqu'à ce que la fenêtre se ferme (de l'utilisateur ou du code).

Vous devrez probablement créer une méthode sur votre interface COM pour fermer la fenêtre dans .NET, ou en quelque sorte obtenir le handle de la fenêtre dans Visual Basic pour fermer la fenêtre.

+0

Mais le système d'exploitation ne doit pas fermer toutes les fenêtres ouvertes. (J'ai pensé qu'il a envoyé les messages QuerySessionEnd et SessionEnd à toutes les fenêtres ouvertes qui les feraient se fermer). Si vous créez une application .net pure avec 2 fenêtres et utilisez ShowDialog(), elle se fermera automatiquement quand le système d'exploitation s'arrêtera. –

+2

Le système d'exploitation envoie cette commande à toutes les fenêtres de niveau supérieur, qui à leur tour ferment leurs enfants. Puisque votre fenêtre de niveau supérieur est VB, elle ne sait probablement pas comment fermer votre fenêtre .Net. Il sait juste que le fil principal est bloqué. – jonathanpeppers

0

un des éléments suivants devrait résoudre votre problème:

  • Assurez-vous que votre fenêtre .NET a les propriétés Texte/Nom du jeu. Je sais que cela cause des problèmes comme ça parfois.
  • Définissez le propriétaire de la fenêtre .NET sur votre fenêtre Visual Basic. Utilisez la fonction SetParent dans user32.dll.
  • Accrochez-vous dans Microsoft.Win32.SystemEvents.SessionEndez dans votre bibliothèque .NET et fermez la fenêtre.
0

Vous pouvez essayer de prendre la fenêtre parent comme paramètre de la méthode .NET, de cette façon le composant .NET est averti lorsque le parent tente de se fermer.

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

Et dans votre Visual Basic 6.0 code:

Call dotNetTestObject.RunTest(Me.hWnd) 
Questions connexes