2010-03-17 3 views
3

Lors de l'utilisation de la classe suivante dans une application de console et de l'exécution d'au moins une instance du Bloc-notes, GetWindowThreadProcessId renvoie correctement un ID de thread différent de zéro. Toutefois, si le même code est inclus dans un service Windows, GetWindowThreadProcessId renvoie toujours 0 et aucune exception n'est levée. Changer l'utilisateur du lancement du service pour qu'il soit le même que celui qui exécute l'application console n'a pas modifié le résultat. Quelles sont les causes GetWindowThreadProcessId pour renvoyer 0 même s'il est fourni avec un hwnd valide? Et pourquoi fonctionne-t-il différemment dans l'application console et le service? Note: Je cours sous Windows 7 32 bits et cible .NET 3.5.Pourquoi GetWindowThreadProcessId renvoie-t-il 0 lorsqu'il est appelé à partir d'un service?

public class TestClass 
{ 
    [DllImport("user32.dll")] 
    static extern uint GetWindowThreadProcessId(IntPtr hWnd, IntPtr ProcessId); 

    public void AttachToNotepad() 
    { 
     var processesToAttachTo = Process.GetProcessesByName("Notepad") 

     foreach (var process in processesToAttachTo) 
     { 
      var threadID = GetWindowThreadProcessId(process.MainWindowHandle, 
       IntPtr.Zero); 

      .... 
     } 
    } 
} 

Code de la console:

class Program 
{ 
    static void Main(string[] args) 
    { 
     var testClass = new TestClass(); 

     testClass.AttachToNotepad(); 
    } 
} 

Code de service:

public class TestService : ServiceBase 
{ 
    private TestClass testClass = new TestClass(); 

    static void Main() 
    { 
     ServiceBase.Run(new TestService()); 
    } 

    protected override void OnStart(string[] args) 
    { 
     testClass.AttachToNotepad(); 

     base.OnStart(args); 
    } 

    protected override void OnStop() 
    { 
     ... 
    } 
} 

Répondre

14

Un service s'exécute dans sa propre session, la tristement célèbre session 0 dans Vista et Win7. Cette session isole les services du bureau de l'utilisateur, elle s'exécute dans une autre session. Spécifiquement pour empêcher un service qui s'exécute généralement avec un compte très privilégié (comme LocalSystem) d'interagir avec l'utilisateur. Un trou de sécurité.

Par conséquent, un service ne peut pas voir les handles de fenêtre appartenant à une autre session.

Vous ne savez pas pourquoi, mais vous avez généralement besoin d'un programme d'assistance qui présente une interface utilisateur et communique avec le service via un mécanisme IPC tel que les canaux nommés, les sockets, le .NET remoting ou le WCF. Si vous utilisez un tube nommé, préfixez le nom du tube avec "Global\" afin que toutes les sessions puissent le voir.

+0

Merci pour la réponse détaillée. Une révision plus approfondie, c'est probablement une meilleure décision de conception pour exécuter mon code dans une application au lieu d'un service. – dcharles

0

Un service Windows n'a pas l'interface utilisateur, il n'a pas de fenêtre.

+0

Mais j'interroge l'ID de thread d'une instance de notepad.exe, pas le service lui-même. – dcharles

1

Vous pouvez également activer l'option "Autoriser le service à interagir avec le bureau" et voir si cela fonctionne. Sinon, je serais d'accord avec le commentaire onbugz ci-dessus.

+0

Merci pour la suggestion. J'ai essayé cela avant de poster et cela n'a pas semblé affecter mon scénario. – dcharles

Questions connexes