Problème Service windows qui s'arrete!

Messages postés
216
Date d'inscription
mardi 5 avril 2005
Statut
Membre
Dernière intervention
17 septembre 2008
- - Dernière réponse : cs_coq
Messages postés
6352
Date d'inscription
samedi 1 juin 2002
Statut
Modérateur
Dernière intervention
2 août 2014
- 7 avril 2006 à 19:11
Bonjour tout le monde !
Bien alors voilà: j'ai fait mon premier service windows en C# cette semaine, sachant que je débute plus ou moins dans ce domaine de programmation et dans ce langage que je commence seulement à explorer... Il s'agit d'un petit programme qui doit surveiller si IE et/ou Firefox tourne(nt) sur la machine om il est installé, afficher une alerte (pour l'instant un vulgaire pop-up) au bout de 45min, puis réafficher au bout de 15min supplémentaires en tuant les 2 processus s'ils sont lancés. S'ils sont arrêtés on remet le tout à zéro...enfin je crois que c'est ce que j'ai fait...

Première installation avec une fenêtre DOS et InstallUtil.exe, plantage à la fin du démarrage: "Erreur 1053: le service n'a pas démarré car la machine n'a pas répondu assez vite" (à quelque chose près ^^)...Relecture du code et après avoir vu une erreur énormissime que je corrige:
j'avais mis une boucle continue dans le onStart()...ce qui n'est pas top...

En revanche, j'ai corrigé ça tout simplement en déplaçant le code dans une fonction que j'appelle dans le onStart()....sauf que maintenant à peine il démarre qu'il m'affiche l'erreur suivante :
"Le service sur ordinateur local a démarré puis s'est arrêté. Certains services peuvent s'arrêter automatiquement s'ils n'ont aucune tâche à effectuer, par exemple, le service des alertes et les journaux de performances."

Mon code n'est pas énorme ni même optimisé je pense. En fait il s'agissait là d'une ébauche vraiment basique pour voir si ça marchait avant de charger le code en performances...le voici : (mais jetez pas de cailloux hein)

using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.ServiceProcess;
using System.Timers;

namespace GoToWorkClock
{
public class GoToWorkClock : System.ServiceProcess.ServiceBase
{
/// <summary>
/// Variable nécessaire au concepteur.
/// </summary>
private System.ComponentModel.Container components = null;

// variables de la classe
private bool _FirefoxStrtd = false;
private bool _IEStrtd = false;
// public static Timer _clock = new Timer(2700000); // par défaut à 45min d'intervalle
public static Timer _clock = new Timer(60000); // test
public static Timer _lastclock = new Timer();

static int nbProcActifs = 0;
static bool stop = false;
static bool launched = false;
static TimeSpan elapsedTime;
static TimeSpan elapsedFinalTime;
static DateTime debut;

public GoToWorkClock()
{
// Cet appel est requis par le Concepteur de composants Windows.Forms.
InitializeComponent();

// TODO : ajoutez les initialisations après l'appel à InitComponent
}

// Le point d'entrée principal pour le processus
static void Main()
{
System.ServiceProcess.ServiceBase[] ServicesToRun;

// Plusieurs services utilisateurs peuvent s'exécuter dans le même processus. Pour ajouter
// un autre service à ce processus, modifiez la ligne suivante
// afin de créer un second objet service. Par exemple,
//
// ServicesToRun = New System.ServiceProcess.ServiceBase[] {new Service1(), new MySecondUserService()};
//
ServicesToRun = new System.ServiceProcess.ServiceBase[] { new GoToWorkClock() };

System.ServiceProcess.ServiceBase.Run(ServicesToRun);
}

/// <summary>
/// Méthode requise pour la prise en charge du concepteur - ne modifiez pas
/// le contenu de cette méthode avec l'éditeur de code.
/// </summary>
private void InitializeComponent()
{
components = new System.ComponentModel.Container();
this.ServiceName = "GoToWorkClock";
_clock.Elapsed += new ElapsedEventHandler(onTimedEvent);
_lastclock.Elapsed += new ElapsedEventHandler(lastTimedEvent);
}

/// <summary>
/// Nettoyage des ressources utilisées.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if(components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}

/// <summary>
/// Démarrage du service.
/// </summary>
protected override void OnStart(string[] args)
{
System.Windows.Forms.MessageBox.Show("Service démarré avec succès!");
launcher(); // appel de la fonction qui contient le code...
}

/// <summary>
/// Arrêt du service.
/// </summary>
protected override void OnStop()
{
// TODO : ajoutez ici le code pour effectuer les destructions nécessaires à l'arrêt de votre service.
Dispose();
}

/// <summary>
/// Fonction appelée après la 1ère alerte. Dernier laps de temps avant le shoot.
/// </summary>
/// le timer passé en paramètre

/// marge qu'on pourra réglé dans une version ultérieure. Appel en dur pour l'instant

protected void lastTime(double marge)
{
_lastclock.Interval = marge;
_lastclock.AutoReset = true;
_lastclock.Start();

while (!stop)
{
// liste des processus actifs sur la machine locale
Process[] tabProcs = Process.GetProcesses();
nbProcActifs = tabProcs.Length;

// On regarde si les processus 'firefox.exe' et 'iexplorer.exe' sont dans la liste
foreach(Process proc in tabProcs)
{
if("firefox.exe" == proc.ProcessName.ToLower())
{
_FirefoxStrtd = true;
}
else
{
_FirefoxStrtd = false;
}
if("explorer.exe" == proc.ProcessName.ToLower())
{
_IEStrtd = true;
}
else
{
_IEStrtd = false;
}
}

if(!_FirefoxStrtd && !_IEStrtd)
{
// s'ils ne tournent pas ou plus, alors on arrête les compteurs et on affiche
// le temps total passé en ligne s'ils étaient lancés (launched était = true)
_lastclock.Stop();
_lastclock.Close();
_lastclock.Dispose();

launched = false;
elapsedFinalTime += elapsedTime;
debut = DateTime.Now;
// pop-up pour dire cb de temps a été passé
System.Windows.Forms.MessageBox.Show("Temps passé TOTAL = " + elapsedFinalTime.ToString());
}
}
}

/// <summary>
/// fonction appelée au démarrage du service
/// </summary>
private void launcher()
{
while (!stop)
{
// liste des processus actifs sur la machine locale
Process[] tabProcs = Process.GetProcesses();
nbProcActifs = tabProcs.Length;

// On regarde si les processus 'firefox.exe' et 'iexplorer.exe' sont dans la liste
foreach(Process proc in tabProcs)
{
if("firefox.exe" == proc.ProcessName.ToLower())
{
_FirefoxStrtd = true;
}
else
{
_FirefoxStrtd = false;
}
if("explorer.exe" == proc.ProcessName.ToLower())
{
_IEStrtd = true;
}
else
{
_IEStrtd = false;
}
}

// S'ils y sont, c'est qu'on est connecté à Internet
if(_FirefoxStrtd || _IEStrtd)
{
//s'ils viennent d'être lancés on active le Timer
launched = true;
debut = DateTime.Now;
_clock.AutoReset = true;
_clock.Start();
}
else
{
// s'ils ne tournent pas ou plus, alors on arrête le compteur et on affiche
// le temps total passé en ligne s'ils étaient lancés (launched était = true)
_clock.Stop();
_clock.Close();
_clock.Dispose();

if(launched)
{
launched = false;
elapsedTime = DateTime.Now.Subtract(debut);
debut = DateTime.Now;
// pop-up pour dire cb de temps a été passé
System.Windows.Forms.MessageBox.Show("Temps passé = " + elapsedTime.ToString());
}
}
}
}

/// <summary>
/// Spécifie ce qu'il arrive lorsque l'événement est levé
/// </summary>
private void onTimedEvent(object sender, ElapsedEventArgs e)
{
// Pop-up pour dire qu'on a déjà passé X temps en ligne (45min par défaut)
System.Windows.Forms.MessageBox.Show("TEST");
// on laisse un délai de 15min pour finir
// lastTime(900000);
lastTime(30000); // test
}

private void lastTimedEvent(object sender, ElapsedEventArgs e)
{
// on récupère les processus 'iexplorer.exe' et 'firefox.exe' et on les tue
Process[] procs = Process.GetProcesses();
nbProcActifs = procs.Length;

foreach(Process proc in procs)
{
if("firefox.exe" == proc.ProcessName)
{
proc.Kill();
}
else if("iexplorer.exe" == proc.ProcessName)
{
proc.Kill();
}
}
}
}
}

Voilà j'ai essayé de faire ça au plus propre, mais je suis prêt à répondre à toutes les questions supplémentaires.

"Un seul Être vous manque, et tout est dépeuplé..."
Afficher la suite 

10 réponses

Messages postés
495
Date d'inscription
dimanche 6 juillet 2003
Statut
Membre
Dernière intervention
9 novembre 2007
0
Merci
la derniere erreur qui s'affiche, c'est quand une exception est levée dans un service, evidement tu n'as pas de moyen de le savoir.

de plus, MessageBox est une fonction interdite dans un service, et le processus qui demarre les service la detecte, met cette fonction en commentaire et tu devrais observer un changement (c'est une fonction bloquante, et une application service est censée ne jamais se bloquer, c'est pour ca)

de plus, d'avoir deplacé ta boucle sans fin du Start vers une autre fonction qui est ensuite appelée dans Start... cela ne change strictement rien.

ce que je te recommande, c'est d'utiliser un timer (celui du namespace System.Timers et surtout pas celui de System.Windows.Forms) et sur chaque "Tick" tu appel ta fonction launcher, en ayant evidement prealablement enlevé le while en entrée
Commenter la réponse de sebseb42
Messages postés
216
Date d'inscription
mardi 5 avril 2005
Statut
Membre
Dernière intervention
17 septembre 2008
0
Merci
Salut seb !
d'abord merci pour ta réponse et pour ton aide !
Je vais essayer de suivre tes conseils, et voir pour me dépatouiller, je reviens avec les nouvelles au plus vite ! ^^

(Je savais pas pour la messageBox qu'on pouvait pas l'utiliser....même avec une feinte genre un system.pause() ou un truc du genre(j'sais pas si ca existe en C#) pour faire une pause le temps de la popup ? parce qu'en fait j'ai l'intention de faire une alerte à la MSN mais en skinnée par la suite....:s)

"Un seul Être vous manque, et tout est dépeuplé..."
Commenter la réponse de sphaxslayer
Messages postés
6352
Date d'inscription
samedi 1 juin 2002
Statut
Modérateur
Dernière intervention
2 août 2014
75
0
Merci
Par défaut un service n'est pas autorisé à interagir avec le bureau.

/*
coq
MVP Visual C#
*/
Commenter la réponse de cs_coq
Messages postés
216
Date d'inscription
mardi 5 avril 2005
Statut
Membre
Dernière intervention
17 septembre 2008
0
Merci
ah.....c'est embêtant...
mais je garde une lueur d'espoir "

Par défaut un service n'est pas autorisé à interagir avec le bureau. "
est-ce que ça sous-entend qu'on peut lui en donner l'autorisation Maître Coq ?

"Un seul Être vous manque, et tout est dépeuplé..."
Commenter la réponse de sphaxslayer
Messages postés
6352
Date d'inscription
samedi 1 juin 2002
Statut
Modérateur
Dernière intervention
2 août 2014
75
0
Merci
Oui.
Tu vois notamment la CheckBox qui va bien dans les paramètres du service.
Ca doit être faisable via l'installeur du service.

Mais avant de te lancer là dedans renseigne toi plus sur les effets de bord éventuels, notammement côté sécurité.
Il serait peut être mieux de s'orienter vers quelquechose du genre client/serveur, avec le "serveur" en service et le "client" lancé pour chaque session utilisateur censé recevoir les messages. Enfin, ce n'est qu'une idée.

/*
coq
MVP Visual C#
*/
Commenter la réponse de cs_coq
Messages postés
216
Date d'inscription
mardi 5 avril 2005
Statut
Membre
Dernière intervention
17 septembre 2008
0
Merci
oui enfin venant de toi, j'pense qu'elle peut être meilleure que les miennes hein ! j'débute seulement moi ^^
Ceci dit, si tu pouvais m'éclairer un peu plus: la machine est donc une windows, XP pro si ca aide mais j'en doute, de même qu'il n'y a qu'un utilisateur qui se loggue donc automatiquement évidemment et j'aimerais simplement surveiller les processus firefox.exe et iexplorer.exe...
Donc en architectuer client/serveur, comment "répartir" les tâches...? Je vois pas comment faire en fait...ça me parait une solution abordable pourtant, juste j'arrive pas à concevoir la séparation, vu qu'il n'y a que 2 choses à faire finalement:
- surveillance des processus firefox.exe et iexplorer.exe
- affichage des alertes passées le timer

OU ALORS !
refonte du projet
Etant donné que j'essaierai dans un futur de faire un truc plus avancé, notamment avec un choix graphique du mode d'utilisation, d'un réglage des temps des timers par l'user...Est-ce que c'est pas plus pratique finalement de faire une simple application windows....? Bien que je préfèrerais avoir un service qui tourne, mais bon, si l'IHM n'est pas possible...

"Un seul Être vous manque, et tout est dépeuplé..."
Commenter la réponse de sphaxslayer
Messages postés
6352
Date d'inscription
samedi 1 juin 2002
Statut
Modérateur
Dernière intervention
2 août 2014
75
0
Merci
Je n'ai jamais trop pousser du coté des services non plus...
Le refonte me parait une bonne idée.
L'intérêt d'un service est entre autre dans le fait qu'il peut tourner sans session utilisateur ouverte, hors toi ça ne seras jamais le cas visiblement :-)

/*
coq
MVP Visual C#
*/
Commenter la réponse de cs_coq
Messages postés
216
Date d'inscription
mardi 5 avril 2005
Statut
Membre
Dernière intervention
17 septembre 2008
0
Merci
Oui oui ça c'est sûr...le contexte, c'est que ma copine passe beaucoup de temps sur internet et elle a du mal à gérer son temps car elle le voit pas du tout passer...j'lui ai donc proposé un petit truc...seulement, pour faire ça un peu plus "proprement" j'voulais faire un service pour que le programme tourne en arrière plan et qu'elle n'ait pas qu'à le fermer par simple clic ou un CTRL+ALT+SUPPR => Fin de tâche (ses connaissances s'arretant là: elle ne saura pas arrêter le processus dans la liste ni arrêter un service...)

Enfin bon...je pense que ça sera moins prise de tête...

"Un seul Être vous manque, et tout est dépeuplé..."
Commenter la réponse de sphaxslayer
Messages postés
216
Date d'inscription
mardi 5 avril 2005
Statut
Membre
Dernière intervention
17 septembre 2008
0
Merci
Bon...en fait j'ai fouiné un peu et j'ai trouvé un tuto sur comment faire pour que le service intéragisse avec le bureau...mais c'est un code en VB, donc je vais voir si c'est faisable en C#...auquel cas je pourrais rester sur mon idée d'un service, quitte à lui metter une petite IHM pour choisir le laps de temps...Je teste ça et je reviens donner plus d'infos...

(Voilà le lien si ça peut servir à des gens plus tard qui passeront pas là => Intéraction d'un service Windows avec le bureau)

"Un seul Être vous manque, et tout est dépeuplé..."
Commenter la réponse de sphaxslayer
Messages postés
6352
Date d'inscription
samedi 1 juin 2002
Statut
Modérateur
Dernière intervention
2 août 2014
75
0
Merci
Du .Net c'est du .Net, et c'est plutôt dans l'autre sens que l'adaptation de code était difficile.
Avec par exemple les surcharges d'opérateurs (résolu avec VB 2005)

/*
coq
MVP Visual C#
*/
Commenter la réponse de cs_coq