2014-05-13 1 views
1

Je développe pour un serveur 2003 avec C# et .NET Framework 2.0GDI + fenêtre empêchant l'arrêt

Tant que le programme fonctionne, je ne peux pas arrêter ma machine. Rien ne se passe, mais quand alt + tabulation je peux voir une fenêtre appelée "GDI + Window". Dès que je ferme mon programme, je peux éteindre l'ordinateur correctement.

Cependant, sur mes autres ordinateurs (Windows XP Professionnel, Windows 8, Windows 8.1), cela n'arrive pas. Le programme extrait les données d'une base de données et les envoie à Internet, j'ai donc un Thread fonctionnant en arrière-plan. Cela pourrait-il être un problème?

Le code dans la classe principale est la suivante:

public partial class Form1 : Form 
{ 
    bool run = true; 
    //AutoStart autoS = new AutoStart(); 
    int interval; 
    //LogFileBuilder lfboom = new LogFileBuilder(true);*/ 

    public Form1() 
    { 
     InitializeComponent(); 
     /*OpenOnce(); 
     //autoS.EintragHinzufügen(); 
     WriteMe(); 
     LogFileBuilder lfb = new LogFileBuilder(); 
     lfb.writeLine("Programm gestartet"); 
     new Thread(Durchführung).Start();*/ 
    } 
} 

Bien sûr, il existe d'autres méthodes et gestionnaires d'événements sous la forme, mais ils ne sont pas pertinents, car ils ne sont pas appelés, lors de la reproduction de ce problème . Comme vous pouvez le voir, j'ai commenté tout mon code à l'exception de InitializeComponents(), mais le problème se produit tout de même.

étapes de la reproduction:
1. Ouvrez le programme
2. Arrêtez le serveur
3. Rien ne se passe, à l'exception de la nouvelle « GDI + fenêtre » dans le alt + liste onglet, qui ne peut être ouvert

+1

http://support.microsoft.com/kb/943453 –

+1

Je suggère reconsidérant si vous devez afficher une interface utilisateur pour un programme qui s'exécute en arrière-plan et extrait des informations d'une base de données et les envoie à Internet. Si vous ne créez aucun type d'interface utilisateur, vous n'initialiserez pas GDI +, et cette fenêtre ne sera pas créée. –

+0

J'ai pensé à l'interface utilisateur, mais c'est important, car je dois changer certaines données fréquemment, ce qui est tellement plus pratique et je peux afficher des informations structurées. J'ai inséré l'exemple de code de votre lien, mais j'ai une exception TypeLoadException. Informations complémentaires: Le type "MyProject.Form1" de l'assembly "MyProject, Version = 1.0.0.0, Culture = neutre, PublicKeyToken = null" n'a pas pu être chargé car la méthode "SetForegroundWindow" n'a pas d'implémentation (pas de RVA) . (librement traduit par moi) – HigHendHd

Répondre

1

Comme indiqué par Cody Gray, il existe une condition connue lorsque le sous-système GDI + initialise et reste ensuite la fenêtre de premier plan. La solution proposée dans le KB article 943453 est de définir explicitement la fenêtre de premier plan une fois que votre charge principale forme, comme ceci:

public partial class Form1 : Form 
{ 
    public Form1() 
    { 
     InitializeComponent(); 
    } 

    //using System.Runtime.InteropServices; 
    // tell the runtime to use the user32.dll for implementation of the next method 
    [DllImport("user32.dll")] 
    // what is returned by this method 
    [return: MarshalAs(UnmanagedType.Bool)] 
    // the methed to call in User32 
    // upper/lower case is important 
    static extern bool SetForegroundWindow(IntPtr hWnd); 

    private void Form1_Load(object sender, EventArgs e) 
    { 
     SetForegroundWindow(this.Handle); 
    } 
} 

Dans les commentaires que vous prétendez que vous avez essayé cela, mais été confronté à une exception typeload:

System.TypeLoadException was uncle Message: Une exception non gérée de type 'System.TypeLoadException' s'est produite dans mscorlib.dll
Informations supplémentaires: Impossible de charger le type 'App.Form1' à partir de l'assembly 'App, Version = 1.0.0.0, Culture = neutral, PublicKeyToken = null 'car la méthode' SetForegroun dWindow 'n'a pas d'implémentation (pas de RVA).

Cela est dû au fait que SetForegroundwindow n'a pas l'attribut [Dllimport] appliqué. Je peux reprocher cette exception en commentant la ligne avec [Dllimport]. Sans cela votre code compilera mais comme la méthode SetForegroundWindow n'aura aucune implémentation, le runtime refuse de charger votre type, d'où l'exception.

Dans un sens technique, le RVA représente Relative Virtual Address et est un décalage à l'adresse de base du module. En recherchant un élément RVA et en l'ajoutant à l'adresse de base, le pointeur de départ (méthode, données, etc.) sera renvoyé. S'il n'y a rien à rechercher car il n'y a rien à exécuter, le module ne peut pas être exécuté en toute sécurité. Voir https://msdn.microsoft.com/en-us/library/ms809762.aspx pour plus d'informations.

Donc, pour résumer, le code suivant lorsqu'il est appelé

[DllImport("user32.dll")] 
[return: MarshalAs(UnmanagedType.Bool)] 
static extern bool SetForegroundWindow(IntPtr hWnd); 

exécutera this unmanaged method in the WinAPI

+2

J'ai upvoted ceci parce qu'il y a mon nom dedans. –