J'ai récemment hérité de quelques applications exécutées en tant que services Windows et je ne parviens pas à fournir une interface graphique (accessible à partir d'un menu contextuel dans la barre d'état système) avec les deux.
La raison pour laquelle nous avons besoin d'une interface graphique pour un service Windows est la possibilité de reconfigurer le comportement du (des) service (s) Windows sans recourir à l'arrêt/au redémarrage.
Mon code fonctionne bien en mode débogage, le menu contextuel s'affiche et tout se comporte correctement, etc.
Lorsque j'installe le service via "installutil" à l'aide d'un compte nommé (c'est-à-dire, pas d'un compte système local), le service fonctionne correctement, mais n'affiche pas l'icône dans la barre d'état système (je sais que ce comportement est normal car je ne l'utilise pas. avoir l'option "interagir avec le bureau").
Voici le problème cependant - lorsque je choisis l’option "LocalSystemAccount" et que je coche la case "interagir avec le bureau", le service met AGES à démarrer sans raison évidente, et je continue à obtenir
Impossible de démarrer le service ... sur l'ordinateur local.
Erreur 1053: le service n'a pas répondu à la demande de démarrage ou de contrôle dans les délais.
Incidemment, j’ai augmenté le délai d’expiration du service Windows de 30 secondes à 2 minutes par défaut via un hack de registre (voir http://support.Microsoft.com/kb/824344 , recherchez TimeoutPeriod dans la section 3), mais le le démarrage du service est toujours terminé.
Ma première question est la suivante: pourquoi la connexion au "compte système local" peut-elle prendre SOOOOO BEAUCOUP PLUS QUE lorsque le service se connecte avec un compte non-LocalSystemAccount, ce qui entraîne l'expiration du service Windows? Quelle est la différence entre ces deux facteurs pour provoquer un comportement si différent au démarrage?
Deuxièmement, tout ce que j'essaie de faire est de prendre du recul. Il s’agit simplement d’un service Windows qui fournit une interface graphique pour la configuration. Je serais très heureux de l’utiliser avec un compte système non local (avec l’utilisateur nommé/pwd), si je pouvais obtenir le service pour interagir avec le bureau (c'est-à-dire, avoir un menu contextuel disponible dans la barre d'état système). Est-ce possible, et si oui comment?
Tout pointeur sur les questions ci-dessus serait apprécié!
Après avoir combattu ce message pendant des jours, un ami m'a dit que vous devez utiliser la version Release. Lorsque j'installe la version de débogage, il donne ce message. La version Release commence bien.
Si vous continuez d'essayer de faire en sorte que votre service interagisse directement avec le bureau de l'utilisateur, vous perdez: même dans les meilleures circonstances (c'est-à-dire "avant Vista"), cela devient extrêmement délicat.
Windows gère en interne plusieurs stations de fenêtre , chacune avec son propre bureau. La station Windows assignée aux services s'exécutant sous un compte donné est complètement différente de la station Windows de l'utilisateur interactif connecté. L'accès aux stations entre fenêtres a toujours été désapprouvé, car cela pose un risque pour la sécurité. Alors que les versions précédentes de Windows permettaient certaines exceptions, celles-ci ont été en grande partie supprimées dans les systèmes d'exploitation Vista et ultérieurs.
La raison la plus probable pour laquelle votre service est suspendu au démarrage est qu'il tente d'interagir avec un bureau inexistant (ou suppose que l'Explorateur s'exécute dans la session de l'utilisateur système, ce qui n'est également pas le cas), ou attend une entrée d'un bureau invisible .
Le seulement Une solution fiable à ces problèmes consiste à éliminer tout le code de l'interface utilisateur de votre service et à le déplacer vers un exécutable distinct qui s'exécute dans la session utilisateur interactive (l'exécutable peut être démarré à l'aide du groupe de démarrage global, par exemple).
La communication entre votre code d'interface utilisateur et votre service peut être mise en œuvre à l'aide de n'importe quel mécanisme RPC: Les canaux nommés fonctionnent particulièrement bien à cette fin. Si vos besoins en communication sont minimes, l'utilisation de les commandes de Service Control Manager définies par l'application peut également faire l'affaire.
Cette séparation entre le code de l’interface utilisateur et le code de service nécessitera quelques efforts: c’est toutefois le seul moyen de rendre les choses fiables et de vous servir à l’avenir.
ADDENDUM, avril 2010: Depuis que cette question reste très populaire, voici un moyen de résoudre un autre scénario courant provoquant des erreurs "le service n'a pas répondu ...", impliquant des services .NET qui n'essaient pas de choses amusantes comme une interaction avec le bureau, mais faire utiliser les assemblys signés Authenticode: désactive la vérification de la signature Authenticode au moment du chargement afin de créer une preuve Publisher , en ajoutant les éléments suivants à votre fichier .exe.config:
<configuration>
<runtime>
<generatePublisherEvidence enabled="false"/>
</runtime>
</configuration>
La preuve Publisher est une fonctionnalité peu utilisée de Code Access Security (CAS): ce n'est que dans le cas peu probable où votre service s'appuiera réellement sur PublisherMembershipCondition qu'il sera désactivé, ce qui entraînera des problèmes. Dans tous les autres cas, les échecs de démarrage permanents ou intermittents disparaîtront en ne nécessitant plus du temps d'exécution pour effectuer des vérifications coûteuses des certificats (y compris des recherches dans la liste de révocation).
J'ai rencontré ce problème à cause d'un cadre manquant sur la boîte d'exécution de mon service. La boîte avait .NET 4.0 et le service était écrit sur .NET 4.5.
J'ai installé le téléchargement suivant sur la boîte, puis redémarré et le service démarré correctement: http://www.Microsoft.com/en-us/download/details.aspx?id=30653
Pour déboguer le démarrage de votre service, ajoutez ce qui suit en haut de la méthode OnStart()
de votre service:
while(!System.Diagnostics.Debugger.IsAttached) Thread.Sleep(100);
Cela bloquera le service jusqu'à ce que vous attaciez manuellement le débogueur Visual Studio à l'aide de Debug -> Attacher au processus ...
Remarque: En général, si vous souhaitez qu'un utilisateur interagisse avec votre service, il est préférable de scinder les composants de l'interface graphique en une application Windows distincte qui s'exécute lorsque l'utilisateur se connecte. autre forme de IPC pour établir la communication entre l’application graphique et votre service. C’est en fait la méthode uniquement qui est possible dans Windows Vista.
Dans la classe de service de la méthode OnStart n'effectuant pas une opération énorme, le système d'exploitation attend un court délai d'exécution du service, exécutez votre méthode à l'aide du thread thread start:
protected override void OnStart(string[] args)
{
Thread t = new Thead(new ThreadStart(MethodName)); // e.g.
t.Start();
}
Je tire à l'aveuglette ici, mais j'ai très souvent constaté que les longs retards dans les démarrages de services sont directement ou indirectement causés par des délais d'attente de fonction réseau, souvent lorsque vous tentez de contacter un contrôleur de domaine lors de la recherche des SID de compte, ce qui se produit très souvent indirectement GetMachineAccountSid()
que vous le réalisiez ou non, puisque cette fonction est appelée par le sous-système RPC.
Pour un exemple sur la façon de déboguer dans de telles situations, voir Le cas des délais de démarrage du processus sur le blog de Mark Russinovich.
Si vous utilisez le code de débogage comme indiqué ci-dessous dans votre service, le problème peut survenir.
#if(!DEBUG)
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new EmailService()
};
ServiceBase.Run(ServicesToRun);
#else
//direct call function what you need to run
#endif
Pour résoudre ce problème, pendant que vous créez votre service Windows, supprimez la condition #si car il ne fonctionnait pas tel quel.
Veuillez utiliser un argument pour le mode débogage à la place ci-dessous.
if (args != null && args.Length > 0)
{
_isDebug = args[0].ToLower().Contains("debug");
}
Je rencontrais un problème similaire avec un service que j'écrivais. Cela a bien fonctionné puis un jour, j'ai commencé à avoir le délai d'expiration des erreurs de démarrage. Cela s'est passé dans une version et/ou dans les versions Release et Debug en fonction de ce qui se passait. J'avais instancié un EventLogger à partir de System.Diagnostics, mais quelle que soit l'erreur que je voyais, cela devait se produire avant que le Logger ne puisse écrire ...
Si vous ne savez pas où chercher les EventLogs, dans VS, vous pouvez accéder à votre ordinateur sous l'explorateur de serveurs. J'ai commencé à fouiller dans d'autres EventLogs autres que ceux de mon service. Sous Application - .NETRuntime, j'ai trouvé les journaux d'erreur pertinents pour l'erreur au démarrage. Fondamentalement, il y avait quelques exceptions dans le constructeur de mon service (l'une d'elles s'est avérée être une exception lors de la configuration de l'instance EventLog - ce qui explique pourquoi je ne pouvais voir aucun journal dans mon service EventLog). Sur une version précédente, apparemment, il y avait eu d'autres erreurs (ce qui m'avait amené à apporter les modifications menant à l'erreur dans la configuration de EventLog).
Bref récit - la raison de l'expiration du délai peut être due à diverses exceptions/erreurs, mais l'utilisation des journaux d'événements Runtime peut simplement vous aider à comprendre ce qui se passe (notamment dans les cas où une construction fonctionne, mais pas une autre).
J'espère que cela t'aides!
Dans mon cas, la version de .net framework
manquait.
Mon service utilisé
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
Mais la version .net Framework
du serveur était 4, donc en modifiant 4.5 à 4 le problème résolu:
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0" />
</startup>
Copiez la version DLL ou récupérez la DLL en mode publication plutôt qu'en mode débogage et collez-la dans le dossier d'installation, elle devrait fonctionner.
J'ai eu ce problème et il m'a rendu fou pendant deux jours… Si votre problème est semblable au mien:
J'ai des paramètres «Paramètres utilisateur» dans mon service Windows, de sorte que le service puisse effectuer lui-même la maintenance, sans arrêter ni démarrer le service. Le problème vient des «paramètres utilisateur», où le fichier de configuration de ces paramètres est enregistré dans un dossier sous le profil utilisateur de l'utilisateur qui exécute le service Windows sous la version du fichier service-exe.
Ce dossier pour une raison quelconque a été corrompu. J'ai supprimé le dossier et le service recommence à fonctionner comme d'habitude…
Ce problème se produit généralement lorsqu'il manque des références sur votre assembly et que la liaison échoue généralement au moment de l'exécution.
pour déboguer mettre Thread.Sleep(1000)
dans la main()
. et mettre un point de rupture dans la ligne d'exécution suivante.
Puis démarrez le processus et attachez le débogueur au processus en cours de démarrage. Appuyez sur f5 après avoir atteint le point de rupture. Il jettera l'exception d'assemblage manquant ou de référence.
Espérons que cela résoudra cette erreur.
Une fois, essayez de lancer votre fichier exe. J'ai eu le même problème, mais quand je l'ai exécuté directement en double-cliquant sur le fichier exe, j'ai reçu un message sur la version du framework .Net, car j'ai reçu le projet de service avec un framework sur lequel il n'était pas installé.
Installez la version de débogage du service et attachez le débogueur au service pour voir ce qui se passe.
Je veux faire écho aux commentaires de mdb ici. Ne va pas dans cette voie. Votre service n'est pas censé avoir une interface utilisateur ... "Aucune interaction utilisateur" est comme la caractéristique déterminante d'un service.
Si vous devez configurer votre service, écrivez une autre application qui édite la même configuration que celle que le service lit au démarrage. Mais faites-en un outil distinct: lorsque vous souhaitez démarrer le service, vous démarrez le service. Lorsque vous souhaitez le configurer, vous exécutez l'outil de configuration.
Maintenant, si vous avez besoin d'une surveillance en temps réel du service, c'est un peu plus compliqué (et certainement quelque chose que j'ai souhaité avec les services). Vous parlez maintenant de devoir utiliser des communications interprocessus et d’autres maux de tête.
Pire encore, si vous avez besoin d'une interaction utilisateur, vous vous trouvez vraiment déconnecté, car les services n'interagissent pas avec l'utilisateur.
À votre place, je me retirais et demandais pourquoi cela doit-il être un service ? Et pourquoi a-t-il besoin d'une interaction de l'utilisateur ?
Ces deux exigences sont assez incompatibles et cela devrait déclencher des alarmes.
Mon problème était dû au cadre cible mentionné dans la configuration du service Windows:
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6"/>
</startup>
et mon serveur sur lequel j'ai essayé d'installer le service Windows n'était pas pris en charge pour cette version .Net.
En changeant lequel, j'ai pu résoudre le problème.
J'ai également fait face à un problème similaire et a constaté qu'il y avait un problème de chargement Assembly. Je recevais cette erreur immédiatement en essayant de démarrer le service.
Pour résoudre rapidement le problème, essayez d'exécuter le service exécutable à l'aide de la commande Invite à l'aide de ProcDump http://technet.Microsoft.com/en-us/sysinternals/dd996900 . Il doit fournir une indication suffisante sur l'erreur exacte.
http://bytes.com/topic/net/answers/637227-1053-error-trying-start-my-net-windows-service m'a beaucoup aidé.
Dans mon cas, c’était la permission de utilisateur compte dans AD . Après l’avoir défini correctement, cela fonctionne parfaitement.
La version de publication ne fonctionnait pas pour moi, cependant, j'ai parcouru le journal des applications et l'observateur d'événements pour constater que le service Windows générait une exception de sécurité lorsqu'il tentait de créer un journal des événements. J'ai résolu ce problème en ajoutant manuellement la source d'événements avec un accès administrateur.
J'ai suivi ce guide de Microsoft:
L'ajout de 127.0.0.1 crl.Microsoft.com au fichier "Hosts" a résolu notre problème.
Le compte système local et le service local ne fonctionnaient pas pour moi. Je l'ai ensuite défini sur Service réseau, ce qui a bien fonctionné.
ouvrez la fenêtre des services en tant qu'administrateur, puis essayez de démarrer le service. Cela a fonctionné pour moi.
Si un formulaire Windows est utilisé pour les tests, assurez-vous que l'objet de démarrage est toujours le service et non le formulaire Windows.
J'ai eu ce problème similaire, les arrêts que j'ai suivis
Mon problème n'était pas dû à une erreur. J'ai eu un BlockingCollection.GetConsumingEnumerable () dans le chemin. Cela a fait attendre le service Windows.
Dans mon cas, j'ai eu ce problème en raison d'une erreur réelle. Avant l'appel du constructeur de service, un constructeur statique de variable membre échouait:
private static OracleCommand cmd;
static SchedTasks()
{
try
{
cmd = new OracleCommand("select * from change_notification");
}
catch (Exception e)
{
Log(e.Message);
// "The provider is not compatible with the version of Oracle client"
}
}
En ajoutant le bloc try-catch, j'ai constaté que l'exception se produisait à cause d'une mauvaise version d'Oracle. L'installation de la base de données correcte a résolu le problème.
Cela a fonctionné pour moi. En gros, assurez-vous que l’utilisateur d’ouverture de session est bien configuré. Cependant, cela dépend de la configuration de l’infrastructure du compte. Dans mon exemple, il utilise les informations d'identification de l'utilisateur du compte AD.
Dans la boîte de recherche du menu de démarrage, recherchez «Services» -In Services trouve le service requis -right cliquez sur et sélectionnez l'onglet Connexion -Sélectionnez 'Ce compte' et entrez le contenu/informations d'identification requis -Ok et lance le service comme d'habitude
Nous avons Log4Net configuré pour se connecter à une table de base de données. La table était devenue si vaste que le service était en retard, essayant de consigner des messages.
J'ai eu ce problème également. Je l'ai fait fonctionner en changeant le compte de connexion sur le compte système local. Dans mon projet, je l'avais configuré pour fonctionner en tant que compte de service local. Ainsi, lorsque je l'ai installé, il utilisait par défaut le service local. J'utilise .net 2.0 et VS 2005. L'installation de .net 1.1 SP1 n'aurait donc pas aidé.
Au bail, cela fonctionne pour moi.