Powershell : remonter les utilisateurs par processus Query-app

Ludovic QUENEC'HDU
Ludovic QUENEC'HDU Ajouter un commentaire 7e lecture en min
Souvent quand on fait un audit d’un environnement nous avons besoin d’avoir les informations, combien d’utilisateurs utilisent une application serveur, par exemple dans une session Remote desktop ou Citrix. Selon la version du système de publication utilisé, bureau ou application les outils sont différents. Là je vous propose une fonction universelle qui vous permettra d’avoir une remontée sur tout système. Dans cette fonction nous aurons en entrée ordinateur requeté et application, puis en sortie ordinateur, application, utilisateur, mémoire utilisé, à quelle heure l’application à démarrer, l’heure de la requête et le chemin où se trouve l’application. Dans un premier temps nous allons utiliser le WMI avec la classe Win32_Process Exemple sur un processus :
Get-WmiObject -ComputerName localhost -class Win32_Process
get-app-1sur11 get-app-2sur11
Et toute suite nous avons des paramètres qui nous intéressent :
  • Name : pour le nom de l’application, pour cibler l’application il faudra utiliser le paramètre –query de la manière suivante :
Select * la classe Wmi ciblé Where : La propriété ciblée ici name, puis égale à la valeur recherchée
Get-WmiObject -ComputerName $server `
-Query "Select * from Win32_Process where name = 'powershell.exe'"
get-app-3sur11
  • Path : Pour savoir depuis ou l’application s’exécute
  • CreationDate : C’est la date de la création du processus, par contre il y aura un travail de remise en forme pour que ça soit plus compréhensible.
Pour ce faire on applique la méthode  .ConvertToDateTime :
Get-WmiObject -ComputerName $server `
-Query "Select * from Win32_Process where name = 'powershell.exe'" `
| select Name,Path,`
@{name='StartTime';expression={$_.ConvertToDateTime($_.CreationDate)}}
get-app-4sur11
  • WorkingSetSize : il nous sera peut être intéressant de remonter la consommation mémoire des applications à analyser. Ce paramètre est en en octet, exemple ci-dessous pour powershell_ise.exe
get-app-5sur11
  • pour finir qui a exécuté l’applicatif, nous ne l’aurons pas dans les propriétés directement.  Pour ça nous allons regarder les méthodes qui s’appliquent à la classe avec un get-member :
Get-WmiObject -ComputerName $server -class Win32_Process | Get-Member
get-app-6sur11 Là nous  récupérons la méthode GetOwner ce qui nous donne le résultat suivant une fois appliquée :
(Get-WmiObject -ComputerName $server -class Win32_Process).GetOwner()
get-app-7sur11 Là nous  récupérons la méthode GetOwner ce qui nous donne le résultat suivant une fois appliquée :
(Get-WmiObject -ComputerName $server -class Win32_Process).GetOwner()
    get-app-8sur11 Ce n’est pas mal, nous pouvons voir les résultats une fois en forme :
Get-WmiObject -ComputerName $server -class Win32_Process  `
| where {$_.path -ne $null}`
| select Name,@{Label='Owner';Expression={$_.GetOwner().User}}, 
WorkingSetSize,`
@{name='StartTime';expression={$_.ConvertToDateTime($_.CreationDate)}},`
Path `
| Format-Table
get-app-9sur11 Maintenant il nous reste plus qu’à mettre en forme notre script :
#variable
$servers = "127.0.0.1","localhost","localh"
$application = 'powershell.exe'

#create table
$result =@()
$n = 1


foreach ($server in $servers){

    #Test of connectivity
    try
    {
        $connection = Test-Connection -computername $Server -Count 1 -ErrorAction stop

        
    }
        catch [System.Net.NetworkInformation.PingException]
    {
        Write-Host "$Server offline"
        $connection = $False
             
    } 

    if($connection -ne $false)
        {
        try 
            {
                $results = Get-WmiObject -ComputerName $server `
                -Query "Select * from Win32_Process where name = '$application'" `
                | select PSComputerName,Name,@{Label='Owner';Expression={$_.GetOwner().User}}, 
                WorkingSetSize,`
                @{name='StartTime';expression={$_.ConvertToDateTime($_.CreationDate)}},`
                Path  -ErrorAction Stop
                write-host "test",$server
            }       
    #test if remote access is ok
        catch [System.UnauthorizedAccessException]
            {
                write-host "$server Not access"
                $QueryWMITest = $False
            }
        }


$QueryTime = Get-Date -format g
#Query WMI Win32_Process


#Processing result
            Foreach($fresult in $results)
            {
            
            $object = New-Object Psobject
            $object | Add-Member -Name "Server" -membertype Noteproperty -Value $null
            $object | Add-Member -Name "Application" -membertype Noteproperty -Value $null
            $object | Add-Member -Name "Memory" -membertype Noteproperty -Value $null
            $object | Add-Member -Name "Owner" -membertype Noteproperty -Value $null
            $object | Add-Member -Name "StartTime" -membertype Noteproperty -Value $null
            $object | Add-Member -Name "QueryTime" -membertype Noteproperty -Value $null
            $object | Add-Member -Name "Path" -membertype Noteproperty -Value $null

            $object.Server = $fresult.PSComputerName
            $object.Application = $fresult.Name
            $object.Owner = $fresult.Owner
            $object.Memory = ($fresult.WorkingSetSize)
            $object.StartTime = $fresult.StartTime
            $object.QueryTime = $QueryTime
            $object.Path = $fresult.Path 
            $result += $object 
              
            }
            $results = $null
                   
}
$result |ft -AutoSize
Voici un exemple avec les cibles suivantes:
$servers = "127.0.0.1","localhost","localh"
$application = 'powershell.exe'
get-app-10sur11 Nous avons maintenant nos deux paramètres pour une future fonction $server et$application. J’ai rajouté la date du query avec un J’ai créé aussi un objet : $object il nous sert à la mise en forme du résultat, lors de la boucle de traitement pour le $results puis elle est réinjectée dans  $result Voilà maintenant notre fonction :
<#
.Synopsis
   Query application by user
.DESCRIPTION
   Query application by user, Memory, Path
.EXAMPLE
   Query-app -ComputerName 'localhost' -Application 'powershell.exe'
#>
function Query-app
{
    Param
    (
        # Name of computer query
        $ComputerName,
        # Name of application
        $Application
    )

    Begin
    {
    }
    Process
    {
    $result =@()
    try
    {
        $connection = Test-Connection -computername $ComputerName -Count 1 -ErrorAction stop        
    }
        catch [System.Net.NetworkInformation.PingException]
    {
        Write-Host "$ComputerName offline"
        $connection = $False            
    } 
    if($connection -ne $false)
        {
        try 
            {
                $results = Get-WmiObject -ComputerName $ComputerName `
                -Query "Select * from Win32_Process where name = '$application'" `
                | select PSComputerName,Name,@{Label='Owner';Expression={$_.GetOwner().User}}, 
                WorkingSetSize,`
                @{name='StartTime';expression={$_.ConvertToDateTime($_.CreationDate)}},`
                Path  -ErrorAction Stop
            }       
        #test if remote access is ok
        catch [System.UnauthorizedAccessException]
            {
                write-host "$ComputerName Not access"
                $QueryWMITest = $False
            }
        }
        $QueryTime = Get-Date -format g
            #Processing result
            Foreach($fresult in $results)
            {
            
            $object = New-Object Psobject
            $object | Add-Member -Name "ComputerName" -membertype Noteproperty -Value $null
            $object | Add-Member -Name "Application" -membertype Noteproperty -Value $null
            $object | Add-Member -Name "Memory" -membertype Noteproperty -Value $null
            $object | Add-Member -Name "Owner" -membertype Noteproperty -Value $null
            $object | Add-Member -Name "StartTime" -membertype Noteproperty -Value $null
            $object | Add-Member -Name "QueryTime" -membertype Noteproperty -Value $null
            $object | Add-Member -Name "Path" -membertype Noteproperty -Value $null

            $object.ComputerName = $fresult.PSComputerName
            $object.Application = $fresult.Name
            $object.Owner = $fresult.Owner
            $object.Memory = ($fresult.WorkingSetSize)
            $object.StartTime = $fresult.StartTime
            $object.QueryTime = $QueryTime
            $object.Path = $fresult.Path 
            $result += $object 
              
            }
            return $result
    }
    End
    {
    }
}
Voici un exemple : get-app-11sur11                
ÉTIQUETÉ : PowerShell
Partager cet article
Par Ludovic QUENEC'HDU Expert en Virtualisation et Sécurité Informatique au Service de Grands Comptes et du Logiciel Libre
Ludovic QUENECHDU est un véritable virtuose de la virtualisation et de la sécurité informatique. Depuis son indépendance professionnelle en 2000, il a apporté son expertise à de prestigieux clients tels que Cameroun Telecom, Merryl Lynch, Ernst & Young, AXA, et bien d'autres. En parallèle, Ludovic s'engage régulièrement dans le démarrage de petites entreprises, notamment dans le domaine du logiciel libre, une passion qu'il chérit pour ses valeurs de partage et d'échange. Son parcours professionnel et sa passion pour la technologie en font un acteur incontournable de l'industrie informatique.
Laisser un commentaire