Aide pour un service windows

cs_eltchio Messages postés 3 Date d'inscription mercredi 29 octobre 2003 Statut Membre Dernière intervention 10 février 2010 - 5 févr. 2010 à 09:49
cs_eltchio Messages postés 3 Date d'inscription mercredi 29 octobre 2003 Statut Membre Dernière intervention 10 février 2010 - 10 févr. 2010 à 09:44
Bonjour à tous, j'essaye de créer un service windows qui a pour but de vérifier (toutes les 5 secondes) si une fenêtre est ouverte. Si c'est le cas, celui-ci lance un certain programme.

Je suis sous Windows XP et je développe en visual studio 2008.

Voici le code (Service1.vb):

Imports System.Timers

Public Class Service1


Private WithEvents montimer As System.Timers.Timer

Protected Overrides Sub OnStart(ByVal args() As String)
' Add code here to start your service. This method should set things
' in motion so your service can do its work.

montimer = New System.Timers.Timer(5000)
montimer.Start()
AddHandler montimer.Elapsed, AddressOf OnTimedEvent

End Sub

Protected Overrides Sub OnStop()
' Add code here to perform any tear-down necessary to stop your service.

montimer.Stop()

End Sub

Public Sub OnTimedEvent(ByVal source As Object, ByVal e As Timers.ElapsedEventArgs) Handles montimer.Elapsed

Dim objShell As Object
Dim hWnd As Integer
Dim Titre_Fenetre As String = Space(256)
Dim TitreFen As String
Dim j As Integer
Dim session_c As Integer
Dim auto_lock As Integer
Dim Connex As Integer
Dim bFlag As Boolean
Dim WinHandle As Integer
Dim testXFP As String
Dim Ret As Integer

Dim lngHandle As Integer
Dim lngStartButton As Integer

On Error Resume Next
objShell = CreateObject("WScript.Shell")

bFlag = False
hWnd = GetWindow(GetDesktopWindow(), 5)

Do While (Not IsDBNull(hWnd)) And (hWnd <> 0) 'Passe en revue chaque fenêtre
Titre_Fenetre = Space$(255)
Ret = GetWindowText(hWnd, Titre_Fenetre, 256)

If Titre_Fenetre <> Space$(255) Then
If IsWindowVisible(hWnd) = 1 Then
TitreFen = Titre_Fenetre
TitreFen = TitreFen.Substring(TitreFen, Ret)
j = j + 1

If Val(j) < 10 Then j = "0" & j

session_c = InStr(TitreFen, "La session courante d'XFP est bloquée")
Connex = InStr(TitreFen, "Connexion")
auto_lock = InStr(TitreFen, "E2S Auto Lock")

If (session_c 1) Or (Connex 1) Or (auto_lock = 1) Then
bFlag = True
End If

End If
End If
hWnd = GetWindow(hWnd, 2)
Loop

If bFlag = True Then

objShell.Run("c:\Dynamics\Switch_Module.exe")

End If

objShell = Nothing

End Sub


End Class


Ensuite Dans un module :

Module ModAPI
Public Declare Function GetWindow Lib "user32" (ByVal hWnd As Integer, ByVal wCmd As Integer) As Integer
Public Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hWnd As Integer, ByVal lpString As String, ByVal cch As Integer) As Integer
Public Declare Function IsWindowVisible Lib "user32" (ByVal hWnd As Integer) As Integer
Public Declare Function GetDesktopWindow Lib "user32" () As Integer
Public Declare Function ShowWindow Lib "user32" (ByVal hWnd As Integer, ByVal nCmdShow As Integer) As Integer
Public Const SW_MAXIMIZE = 3
End Module


Voila, forcement cela ne marche pas. Le service se lance bien, passe bien dans le timer. Mais maintenant comment réécrire le code de la sub OnTimedEvent ?
( par ex: le objShell = CreateObject("WScript.Shell") --> System.object )


Merci d'avance.

4 réponses

elguevel Messages postés 718 Date d'inscription jeudi 19 décembre 2002 Statut Membre Dernière intervention 22 novembre 2016 3
5 févr. 2010 à 13:27
Salut,

Déja je ne comprend pas ton probleme ?

Mais bon commentons quand meme ton code.

A première vu :

- Bravo pour l'import du System.Timers, beaucoup font l'erreur de mettre le composant Timer sur leur service.

Le start et le stop on l'air correct, mais toutefois il faudrait que tu ajoutes dans le Stop un truc du genre :

If (Not montimer Is Nothing) Then
montimer.Dispose()
End If

NB : Je met l'instanciation du Timer dans un Constructeur ... juste une histoire de gout.

Après pour ta méthode OnTimedEvent, là ya tout à revoir ... c'est plus du VB que du .Net :

* On Error Resume Next --> remplacer par des "Try ... Catch"
* objShell = CreateObject("WScript.Shell") --> Garde çà pour du VBScript uniquement
* Titre_Fenetre <> Space$(255) -> je pense que ce test sera toujours Vrai
* Val(j) --> çà sert à rien, J étant déja un Integer
* InStr --> A oublier, VB6 (cf. String.indexOf())
* Space$ --> idem
* IsDBNull(hWnd) -> ouai :-s
* TitreFen = TitreFen.Substring(TitreFen, Ret) --> TitreFen est une String ?? Ca ne peut pas marcher
* objShell.Run --> voir la class Process()
* j = "0" & j --> très sale, j est un entier et tu le transforme en chaine


En gros explique nous ton probleme, et pour ta fonction, reprend la ligne par ligne et vois comment tu peux faire çà en .Net
Si tu veux etre sur de ne pas utilisé de la syntaxe VB6, va dans les références de ton projet et décoche "Microsoft.VisualBasic"

Bon code ...
0
cs_eltchio Messages postés 3 Date d'inscription mercredi 29 octobre 2003 Statut Membre Dernière intervention 10 février 2010
5 févr. 2010 à 14:19
En gros mon problème n'est pas vraiment la retranscription des fonctions VB6 en .net (style InStr). C'est vrai que je n'ai pas été très clair dans ma question.

1. C'est sur, je vais retranscrire le code VB6 en .net
2. C'était aussi pour savoir si le module tel que je l'ai écrit est correcte. Car j'ai vu qu'il fallait utilisé ceci pour l'utilisation des dll :
- <dllImport("user32.dll", ... , ...)> _
Function Getwindow()
End Function
...
3. Le timer est correcte. Un bon point ^^
4. Vérifier si pas de problème niveau mémoire.
5. En bref, c'était pour voir les grosses erreurs que j'aurai pus commettre.

Donc je vais de suite retranscrire le code vb en .net, ensuite vous faire un feedback d'autre eventuel problème.

Merci, a vous.
0
elguevel Messages postés 718 Date d'inscription jeudi 19 décembre 2002 Statut Membre Dernière intervention 22 novembre 2016 3
5 févr. 2010 à 14:51
Mis à part tout ce VB6 ... je dirais qu'il n'y a pas de "Grosse Erreur".

Mais oui, commence par retranscrire çà en .Net sinon on ne pourra effectivement pas aller plus loin.

++
0
cs_eltchio Messages postés 3 Date d'inscription mercredi 29 octobre 2003 Statut Membre Dernière intervention 10 février 2010
10 févr. 2010 à 09:44
Bonjour, voilà le service fonctionne correctement. Même si j'ai laissé du code VB. Voici le code :

Imports System.Timers
Imports System.Diagnostics

Public Class Service1

    Private WithEvents montimer As System.Timers.Timer

    Protected Overrides Sub OnStart(ByVal args() As String)
        ' Add code here to start your service. This method should set things
        ' in motion so your service can do its work.

        montimer = New System.Timers.Timer(5000)
        montimer.Start()
        AddHandler montimer.Elapsed, AddressOf OnTimedEvent

    End Sub

    Protected Overrides Sub OnStop()
        ' Add code here to perform any tear-down necessary to stop your service.

        montimer.Stop()

        If (Not montimer Is Nothing) Then
            montimer.Dispose()
        End If

    End Sub

    Public Sub OnTimedEvent(ByVal source As Object, ByVal e As Timers.ElapsedEventArgs) Handles montimer.Elapsed

        Dim hWnd As Integer
        Dim Titre_Fenetre As String = Space(255)
        Dim TitreFen As String
        Dim session_c As Integer
        Dim auto_lock As Integer
        Dim Connex As Integer
        Dim bFlag As Boolean
        Dim Ret As Integer

        Try
        ' Si le programme est déjà lancé, on ne fait rien.
            If Not (Process.GetProcessesByName("Switch_Module").Length > 0) Then

                hWnd = GetForegroundWindow
                Ret = GetWindowTextLength(hWnd)
                GetWindowText(hWnd, Titre_Fenetre, (Ret + 1))

                If (InStr(Titre_Fenetre, "La session courante d'XFP est bloquée") <> 0) Or _
                   (InStr(Titre_Fenetre, "Connexion") <> 0) Or _
                    (InStr(Titre_Fenetre, "E2S Auto Lock") <> 0) Then


                    bFlag = False
                    hWnd = GetWindow(GetDesktopWindow(), 5)

                    Do While (Not IsDBNull(hWnd)) And (hWnd <> 0) 
                        Titre_Fenetre = Space$(255) 

                        Ret = GetWindowText(hWnd, Titre_Fenetre, 255)  

                        If Titre_Fenetre <> Space$(255) Then          
                            If IsWindowVisible(hWnd) = 1 Then                   
                                TitreFen Titre_Fenetre                                        TitreFen Left(TitreFen, Ret)  
                                session_c = InStr(TitreFen, "La session courante d'XFP est bloquée")
                                Connex = InStr(TitreFen, "Connexion")
                                auto_lock = InStr(TitreFen, "E2S Auto Lock")

                                If (session_c 1) Or (Connex 1) Or (auto_lock = 1) Then
                                    bFlag = True
                                End If

                            End If
                        End If
                        hWnd = GetWindow(hWnd, 2)                     Loop

                    If bFlag = True Then

                        Process.Start("c:\Dynamics\Switch_Module.exe")

                    End If
                End If
            End If

        Catch ex As Exception
            ' écriture dans le journal d'évènement
        End Try

    End Sub


End Class



J'ai laissé tourner le service pendant deux jours et pas de problème mémoire. (vu le peu de code, heureusement ^^).
Dans le catch je vais simplement écrire dans le journal d'évènement de windows (beaucoups d'exemple sur le net à ce sujet).
Maintenant si vous pouvez me faire part de votre expérience pour que le code soit plus professionnel, je suis preneur.

Merci à vous.
0