Powershell : remonter les utilisateurs par processus Query-app

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

 

 

 

 

 

 

 

 

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *