Module complet d'arrêt machine à distance

Soyez le premier à donner votre avis sur cette source.

Snippet vu 12 722 fois - Téléchargée 20 fois

Contenu du snippet

En recherchant sur ce site et d'autres des sources pour à partir des API win32 arrêter une machine à distance, on trouve bcp de choses, mais souvent incomplet, ou ne permettant pas d'avoir le message d'erreur si l'appel de la fonction n'a pas aboutie. (Ou uniquement compatible vb6 mais pas vb.net).

On peut faire ca via la fonction shutdown.exe qui utilise la meme API et qui n'est pas dispo sur 2k/nt et ne permet pas d'avoir le code d'erreur de retour facilement.

J'avais besoin de faire ca en dotnet quelque soit l'os, et j'ai donc fait un petit module permettant de le faire via une fonction avec un retour d'erreur si l'appel n'a pas abouti.

Ce module est facilement incorporable dans une assembly dll par exemple histoire d'avoir une classe propre qui fasse tout ca proprement sans devoir forcement se poser la question avant de l'utiliser.

Pour Info, je recupere l'éventuel message d'erreur via marshal (system.interop), et je le traite via formatmessageA. (le declare le configure automatiquement, on peut aussi passer par un DLLImport avec getlasterror a true si on veut se separer de la visual basic compatibility (qui est inclu par defaut dans un nvo projet form dotnet 2003) et eviter ainsi d'utiliser un declare)

Le point d'entre de ce module (fonction friend) c'est UNE SEULE fonction qui permet à elle seule d'arrêter une machine, d'interrompre l'arrêt, de préciser le message, de forcer ou non la fermeture des appli, et le reboot après shutdown de la machine.

La seule chose qui manque c'est la recupération des privileges, personnellement je le fais via un shell "net use \\machine\ipc$ /user:user pass" avant d'excuter ma fonction.

En espérant que ca puisse aider.

Source / Exemple :


Option Strict On
Option Explicit On 

Module modAdvapi32

    'Constantes nécessaire au fonctionnement des fonctions de codes non managées
    'pour formatMessage
    Private Const FORMAT_MESSAGE_ALLOCATE_BUFFER As Short = &H100
    Private Const FORMAT_MESSAGE_IGNORE_INSERTS As Short = &H200
    Private Const FORMAT_MESSAGE_FROM_STRING As Short = &H400
    Private Const FORMAT_MESSAGE_FROM_HMODULE As Short = &H800
    Private Const FORMAT_MESSAGE_FROM_SYSTEM As Short = &H1000
    Private Const FORMAT_MESSAGE_ARGUMENT_ARRAY As Short = &H2000
    Private Const FORMAT_MESSAGE_MAX_WIDTH_MASK As Short = &HFF

    'pour le language des messages d'erreurs
    Private Const LANG_NEUTRAL As Short = &H0
    Private Const SUBLANG_DEFAULT As Short = &H1
    Private Const LANG_FRENCH As Short = &HC
    Private Const SUBLANG_FRENCH As Short = &H1

    'inclut les fonctions necessaires à l'arrêt de la machine
    '   on aurai pu passer par System.Runtime.InteropServices et DLLImport en mettant l'attribut setlasterror a true (comme en c#), mais en vb powa, il existe
    '   une fonction declare et elle le fait automatiquement et l'on pourra recuperer le message d'erreur via marshal getlastwin32error
    Private Declare Function InitiateSystemShutdown Lib "advapi32.dll" Alias "InitiateSystemShutdownA" (ByVal lpMachineName As String, ByVal lpMessage As String, ByVal dwTimeout As Integer, ByVal bForceAppsClosed As Integer, ByVal bRebootAfterShutdown As Integer) As Integer
    Private Declare Function AbortSystemShutdown Lib "advapi32.dll" Alias "AbortSystemShutdownA" (ByVal lpMachineName As String) As Integer

    'non utilisé dans le module mais par extension pour evolutions futures
    Private Function MAKELANGID(ByRef p As Object, ByRef s As Object) As Integer
        'MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
        Return CInt((CInt(s) * 4) Or CInt(p))
    End Function

    'inclut les fonctions necessaires à la récupération des messages d'erreur si une fonction win32 n'a pas aboutie
    Private Declare Function FormatMessageA Lib "kernel32" (ByVal dwFlags As Integer, ByRef lpSource As Object, ByVal dwMessageId As Integer, ByVal dwLanguageId As Integer, ByVal lpBuffer As String, ByVal nSize As Integer, ByRef Arguments As Integer) As Integer

    'surcharge de formatmessage a la sauce vb
    Private Function FormatMessage(ByVal dwMessageId As Integer) As String
        'On est obligé de passer par une variable qui sera "remplie" par la fonction win32, c'est après coup que la fonction renvoi le nombre de caracteres reellement utilise et qu'on pourra
        '   donc réajuster la taille de celle ci (999 est suffisant, vis a vis de ce qu'on peut trouver comme message d'erreur des API win32 (http://www.xs4all.nl/~rjg70/vbapi/ref/other/errorcodes.html)
        Dim buffer As String = Space(999)
        Dim realSize As Integer = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, 0, dwMessageId, LANG_NEUTRAL, buffer, 999, 0)
        buffer = Mid(buffer, 1, realSize)
        Return buffer
    End Function

    Friend Function MOD_remoteSystemShutdown(ByVal BoolAbortSystemShutdown As Boolean, ByVal IPaddress As String, Optional ByVal Message As String = "", Optional ByVal TimeOutInSecond As Integer = 0, Optional ByVal BoolForceAppsClosed As Boolean = True, Optional ByVal BoolRebootAfterShutdown As Boolean = False) As String
        'si AbortSystemShutdown=false, alors on envoi une init d'un system shutdown, les params par defaut sont arret immediat, sans message user, avec forcage fermeture appli et arret de la machine sans reboot
        'si AbortSystemShutdown=true, alors on envoi une annulation de la commande d'init d'un system shutdown, les autres parametres ne sont pas pris en compte

        Select Case BoolAbortSystemShutdown
            Case True
                'si la demande se passe bien on renvois "True" que le user de la fonction pourra facilement convertir en boolean
                'si la demande n'a pas aboutie, on renvois une chaine de caractere contenant le texte d'erreur dans la langue par defaut de la machine sur lequel on execute cette fonction
                '   (le user pourra try un cbool(return fonction) et en cas d'erreur traiter le message d'erreur comme bon lui semble)
                If AbortSystemShutdown(IPaddress) = 0 Then
                    'une erreur s'est produite, on la recupere, on la met en forme et on la renvoi
                    Return FormatMessage(System.Runtime.InteropServices.Marshal.GetLastWin32Error())
                Else
                    Return "True"
                End If
            Case False
                'si la demande se passe bien on renvois "True" que le user de la fonction pourra facilement convertir en boolean
                'si la demande n'a pas aboutie, on renvois une chaine de caractere contenant le texte d'erreur dans la langue par defaut de la machine sur lequel on execute cette fonction
                '   (le user pourra try un cbool(return fonction) et en cas d'erreur traiter le message d'erreur comme bon lui semble)
                If InitiateSystemShutdown(IPaddress, Message, TimeOutInSecond, CInt(BoolForceAppsClosed), CInt(BoolRebootAfterShutdown)) = 0 Then
                    'une erreur s'est produite, on la recupere, on la met en forme et on la renvoi
                    Return FormatMessage(System.Runtime.InteropServices.Marshal.GetLastWin32Error())
                Else
                    Return "True"
                End If
        End Select
    End Function

End Module

Conclusion :


bon codage :)

A voir également

Ajouter un commentaire

Commentaires

Messages postés
24
Date d'inscription
jeudi 21 février 2008
Statut
Membre
Dernière intervention
12 juillet 2010

salut ,
vous pouvez mettre une application qui s'execute on nous montrant le resultat ?
cordialement .
Messages postés
4
Date d'inscription
dimanche 20 avril 2003
Statut
Membre
Dernière intervention
20 février 2008

Est ce que tu as récupéré son retour ? (dans un messagebox par exemple pour voir). Tu as un message qui te dit si ça c'est bien passé ou non.

Tu as surement pas les droits sur la machine que tu veux arrêter. Comme je le disais dans ma description pour récupérer les droits tu peux utiliser un shell "net use \\machine\ipc$ /user:user pass" et ensuite executer la fonction. (Oubli pas de mettre wait à true, il faut un certain temp pour joindre la machine par netbios).
Messages postés
18
Date d'inscription
mercredi 7 février 2007
Statut
Membre
Dernière intervention
4 juillet 2008

Slt,

comment je peut utiliser cette fonction? J'avais mis tous dans un module et j'ai fait un appel à la fonction ,avec les paramètres demandés, par un clic sur bouton et rien ne ce passe.

Bon collaboration.
Messages postés
4
Date d'inscription
dimanche 20 avril 2003
Statut
Membre
Dernière intervention
20 février 2008

erf désole pour la double mise à jour
Messages postés
4
Date d'inscription
dimanche 20 avril 2003
Statut
Membre
Dernière intervention
20 février 2008

Bien sur que je suis sur qu'il ne releve pas d'exception, sinon je ne l'aurai pas posté :) Je l'ai testé et je l'utilise.

Sinon pour le case cela revient au même, mais je trouve plus lisible de faire un case. Je ne fais pas un test qui en fonction du résultat va donner lieu à du code ou sinon à un autre code. Je considère deux cas chacun correspondant à du code qui n'est pas lié.

En terme d'algorithmie, c'est plus lisible de cette manière, le code généré revu par le compilo sera assez proche de tout de facon quelque soit la manière de l'avoir écrit. Mais pour la lecture c'est mieux comme ca :)

voila voila, merci en tout cas pour ton commentaire.
Afficher les 6 commentaires

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.