[.net2] obtenir les processus actifs de tous les comptes

Soyez le premier à donner votre avis sur cette source.

Vue 13 872 fois - Téléchargée 839 fois

Description

Par l'intermédiaire d'un service Windows je devais surveiller toute les x secondes si un processus tourné toujours.
Hors mon service s'éxecutant sous le compte LocalSystem, il m'était impossible de voir les processus tournant entre autres sur le compte de l'utilisateur courant.

Après plusieurs essais via différentes approches par API, j'ai fini par découvrir dans la précieuse MSDN la fonction WTSEnumerateProcesses. Et la c'est le miracle....

Ma démo vous montre donc comment utiliser cette fonction et ainsi obtenir la liste de tout les processus actifs tout comptes confondus + quelques infos basics sur ceux-ci.

Voici un extrait de la classe de wrapper.

Source / Exemple :


#region 'Variables'

        private static bool _HasGettedProcesses;
        private static List<ProcessInfo> _ProcessInfoCollection = new List<ProcessInfo>();
        private static string _MatchProcessName;
        private static int _MatchProcessID;

        #endregion

        #region 'Méthodes'

        /// <summary>
        /// Récupére les processus de tout les comptes.
        /// </summary>
        /// <returns>Un tableau d'objet ProcessInfo</returns>
        public static ProcessInfo[] GetAllAccountProcesses()
        {
            List<ProcessInfo> piList = new List<ProcessInfo>();     //Collection recevant les objets ProcessInfo
            IntPtr ptWTSPI = IntPtr.Zero;                           //Pointeur sur l'adresse mémoire du 1er bloc de données WTS_PROCESS_INFO
            int iCount = -1;                                        //Nombre de processus

            //Obtient l'adresse du 1er bloc de données WTS_PROCESS_INFO + nombre de processus
            bool bret = WTSEnumerateProcesses((IntPtr)WTS_CURRENT_SERVER_HANDLE, 0, 1, ref ptWTSPI, ref iCount);

            //Si tout va bien
            if (bret)
            {
                //Itération sur l'ensemble des processus.
                for (int i = 0; i < iCount; i++)
                {
                    WTS_PROCESS_INFO PrcInfo = new WTS_PROCESS_INFO();  //Nouvelle instance WTS_PROCESS_INFO recevant le bloc de données

                    //Récupération des données du bloc à l'adresse du pointeur.
                    PrcInfo = (WTS_PROCESS_INFO)Marshal.PtrToStructure(ptWTSPI, typeof(WTS_PROCESS_INFO));

                    int iPID = PrcInfo.ProcessId;                   //ID du processus
                    int iPSession = PrcInfo.SessionId;              //ID de la session
                    string szAccount = "", szDomain = "";           //Compte et domaine du SID
                    SID_NAME_USE sidCat = new SID_NAME_USE();       //Type du SID

                    //Récupération du nom du processus.
                    string szProcessName = Marshal.PtrToStringAuto(PrcInfo.pProcessName);

                    //Récupération du compte + domaine + type du SID.
                    InfoFromSID(PrcInfo.pUserSid, ref szAccount, ref szDomain, ref sidCat);

                    //Ajoute à la collection un objet ProcessInfo contenant les infos précédentes.
                    piList.Add(new ProcessInfo(iPID, iPSession, szProcessName, szAccount, szDomain, sidCat.ToString()));

                    //Avance le pointeur vers l'adresse du bloc de données suivant.
                    ptWTSPI = (IntPtr)(ptWTSPI.ToInt32() + Marshal.SizeOf(typeof(WTS_PROCESS_INFO)));
                }
            }

            //Libère la mémoire allouée
            WTSFreeMemory(ptWTSPI);

            //Remplie la collection globale
            _ProcessInfoCollection = piList;

            //Flag à true indiquant que la liste à été récupérer au moins une fois
            _HasGettedProcesses = true;

            //Retourne un tableau ProcessInfo
            return piList.ToArray();
        }

        /// <summary>
        /// Récupère les informations sur un processus à partir de son nom.
        /// </summary>
        /// <param name="processname">Nom du processus.</param>
        /// <returns>Objet ProcessInfo.</returns>
        public static ProcessInfo RetrieveProcessInfo(string processname)
        {
            if (!_HasGettedProcesses)
                GetAllAccountProcesses();

            _MatchProcessName = processname;

            return _ProcessInfoCollection.Find(MatchInfoFromProcessName);
        }

        /// <summary>
        /// Récupère les informations sur un processus à partir de son PID.
        /// </summary>
        /// <param name="processname">PID du processus.</param>
        /// <returns>Objet ProcessInfo.</returns>
        public static ProcessInfo RetrieveProcessInfo(int pid)
        {
            //Si pas encore récupéré la liste des processus
            if (!_HasGettedProcesses)
                GetAllAccountProcesses();

            _MatchProcessID = pid;

            return _ProcessInfoCollection.Find(MatchInfoFromPID);
        }

        #endregion

        #region 'Méthodes privées'

        /// <summary>
        /// Cherche l'objet ProcessInfo suivant son nom de processus.
        /// </summary>
        /// <param name="pi">Objet ProcessInfo de recherche.</param>
        /// <returns>True si trouvé; False si non.</returns>
        private static bool MatchInfoFromProcessName(ProcessInfo pi)
        {
            if (pi.ProcessName.Equals(_MatchProcessName))
                return true;
            else
                return false;
        }

        /// <summary>
        /// Cherche l'objet ProcessInfo suivant son PID.
        /// </summary>
        /// <param name="pi">Objet ProcessInfo de recherche.</param>
        /// <returns>True si trouvé; False si non.</returns>
        private static bool MatchInfoFromPID(ProcessInfo pi)
        {
            if (pi.Pid.Equals(_MatchProcessID))
                return true;
            else
                return false;
        }

        /// <summary>
        /// Obtient des infos sur un SID
        /// </summary>
        /// <param name="SID">Pointeur SID.</param>
        /// <param name="account">Retourne le nom du compte.</param>
        /// <param name="domain">Retourne le domaine.</param>
        ///<param name="category">Retourne le type du SID.</param>
        private static void InfoFromSID(IntPtr SID, ref string account, ref string domain, ref SID_NAME_USE category)
        {
            //Recevra le compte et le domaine.
            StringBuilder szbName = new StringBuilder();
            StringBuilder szbDomain = new StringBuilder();

            //Longeur des chaines retournées.
            int iSizeName = 0;
            int iSizeDomain = 0;

            //Recevra le type de SID.
            SID_NAME_USE sidUse = new SID_NAME_USE();

            //1er appel afin d'obtenir la longeur des chaines de caractères du compte et du domaine.
            bool bret = LookupAccountSid(null, SID, szbName, ref iSizeName, szbDomain, ref iSizeDomain, out sidUse);

            //Nouvelle instances des StringBuilder dimensionnées.
            szbName = new StringBuilder(iSizeName);
            szbDomain = new StringBuilder(iSizeDomain);

            //2nd appel pour remplir szbName, szbDomain et sidUse
            bret = LookupAccountSid(null, SID, szbName, ref iSizeName, szbDomain, ref iSizeDomain, out sidUse);

            //Retourne les valeurs
            account = szbName.ToString();
            domain = szbDomain.ToString();
            category = sidUse;
        }

        #endregion

Conclusion :


Commentaires, notes
merci de juger :)

Bon dév.

Codes Sources

A voir également

Ajouter un commentaire

Commentaires

Messages postés
25
Date d'inscription
vendredi 5 février 2010
Statut
Membre
Dernière intervention
24 février 2010

Ton programme me sauve la vie, après quasiment trois jours de recherche intensive :)
Messages postés
2375
Date d'inscription
jeudi 12 juillet 2001
Statut
Modérateur
Dernière intervention
15 décembre 2018
20
Si bien sur et tu as de nombreuses infos supplémentaire mais rien ne te renseigne sur le compte executant le processus, ni le domaine du compte.
Messages postés
11
Date d'inscription
vendredi 17 décembre 2004
Statut
Membre
Dernière intervention
25 mai 2007

Je dis surement une connerie parce que je n'ai pas pris le temps de vérifier, mais ne peut ont pas faire cela en WMI? genre avec Win32_process connecté sur le pc distant? bien sûr, cela requiert je pense d'avoir un domaine qui ne soit pas trop vieux (genre NT4 SP6 minimum et sans millenium et 98 et 95)
Messages postés
4936
Date d'inscription
lundi 17 février 2003
Statut
Modérateur
Dernière intervention
14 février 2014
32
nickel :)
Messages postés
2375
Date d'inscription
jeudi 12 juillet 2001
Statut
Modérateur
Dernière intervention
15 décembre 2018
20
Efforts fait. Source mise à jour.
Voila j'attend vos nouveaux commentaire maintenant sur la classe de wrapper :)
Afficher les 8 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.