Il semble qu'à partir des versions de Windows postérieures à Windows 7 (non vérifié, mais d'après mon expérience la dernière est Windows Server 2012 R2), le Gestionnaire de contrôle des services (SCM) est plus strict.
Alors que sur Windows 7 il se contentait de lancer un autre processus, il vérifie maintenant si le processus du service est toujours présent et peut renvoyer l'erreur ERROR_SERVICE_MARKED_FOR_DELETE (1072) pour toute appel ultérieur à CreateService/DeleteService même si le service semble être arrêté.
Je parle ici de code de l'API Windows, mais je tiens à expliciter clairement ce qui se passe, donc cette séquence peut entraîner l'erreur mentionnée :
SC_HANDLE hScm = OpenSCManager(nullptr, nullptr, SC_MANAGER_ALL_ACCESS);
SC_HANDLE hSvc = OpenService(hScm, L"Service fictif", SERVICE_STOP | SERVICE_QUERY_STATUS | DELETE);
SERVICE_STATUS ss;
ControlService(hSvc, SERVICE_CONTROL_STOP, &ss);
// ... attendre que le service signale son état SERVICE_STOPPED
DeleteService(hSvc);
CloseServiceHandle(hSvc);
hSvc = nullptr;
// toutes les appels ultérieurs à CreateService/DeleteService échoueront
// si le processus du service est toujours actif
La raison pour laquelle un processus de service est toujours actif après avoir signalé son état SERVICE_STOPPED n'est pas surprenante. Il s'agit d'un processus régulier, dont le thread principal est 'bloqué' dans son appel à l'API StartServiceCtrlDispatcher
, il réagit d'abord à une action de contrôle d'arrêt, puis doit exécuter sa séquence de code restante.
Il est un peu dommage que le SCM/Système d'exploitation ne gère pas correctement cela pour nous. Une solution programmable est plutôt simple et précise : obtenir le handle du processus exécutable du service avant d'arrêter le service, puis attendre que ce handle soit signalé.
Si l'on aborde le problème d'un point de vue administratif système, la solution est également d'attendre que le processus du service disparaisse complètement.
5 votes
Un redémarrage devrait normalement résoudre tout état persistant.
23 votes
Je sais. Mais j'ai envisagé une solution moins radicale. Redémarrer trente fois par jour ne sera pas une solution acceptable dans mon cas.
1 votes
Pourtant, pirater dans le registre 30 fois par jour est acceptable ? Et pourquoi supprimez-vous des services aussi régulièrement ?
64 votes
"pourquoi supprimez-vous régulièrement des services?" : J'écris un service Windows. Chaque fois qu'il est compilé, il doit être redémarré. "Mais pirater dans le registre 30 fois par jour est acceptable?" : totalement. Supprimer une clé du registre ne m'oblige pas à tout sauvegarder, fermer chaque application ouverte, attendre une minute, puis tout rouvrir.
52 votes
J'ai écrit des services Windows. À moins que vous ne modifiez le code réel qui effectue l'enregistrement, il n'est pas nécessaire de le désinstaller et de le réinstaller à chaque fois que vous effectuez une construction. Tant que le chemin est le même, les informations d'enregistrement plus anciennes seront toujours valides.
0 votes
En fait, ce n'est pas une déclaration vraie. @Damien_The_Unbeliever Microsoft a un bug de compilation qui existe depuis toujours. Vous ne pouvez pas reconstruire et déployer si c'est x64. Vous devez modifier le msi, donc vous devez pirater le registre si l'état devient corrompu. Si MS avait une installation MSI réellement fiable, ce ne serait pas un problème.
4 votes
@NickTurner - lien vers tout rapport de bug? Quel que soit le bogue auquel vous faites référence, je ne l'ai pas rencontré. Et je ne suis pas sûr de la manière dont un MSI est impliqué puisque nous parlons probablement de la construction et de l'exécution de services sur une machine de développement (qui semble du moins être le contexte de cette question vieille de 5 ans)
0 votes
@Nick Turner: Il existe un problème bien connu : si le package MSI est mal écrit, alors il bloquera la désinstallation (y compris la mise à niveau en utilisant une version plus récente, car cela implique d'exécuter l'ancien package MSI pour le désinstaller) ; alors à peu près la seule solution est de supprimer l'application et ses composants MSI en éditant directement le registre. Et si l'on contourne le package MSI, il est facile de faire une erreur ; il est beaucoup mieux de le reconstruire par exemple en utilisant Wix.