Blog ENI : Toute la veille numérique !
🎁 Jusqu'au 31/12, recevez notre
offre d'abonnement à la Bibliothèque Numérique. Cliquez ici
🎁 Jusqu'au 31/12, recevez notre
offre d'abonnement à la Bibliothèque Numérique. Cliquez ici

Des exemples pour le quotidien

Introduction

Dans ce chapitre, nous allons vous partager quelques scripts et fonctions toutes prêtes pour utilisation, permettant de réaliser différentes tâches qui sont utiles au quotidien.

Génération de fichier de log

Le script suivant permettra de créer un fichier de log pour vos scripts puis d’y ajouter du contenu avec par exemple un statut et la date avec l’heure.

Ci-dessous le script :

Function Write_Log 
    { 
           param( 
           $Log_Path, 
           $Message_Type, 
           $Message 
           ) 
 
           If(!(test-path $Log_Path)){new-item $Log_Path -type file -force} 
           $Date = "[{0:MM/dd/yy} {0:HH:mm:ss}]" -f (Get-Date) 
           Add-Content $Log_Path  "$Date - $Message_Type :  $Message" 
           write-host  "$MyDate - $Message_Type : $Message" 
    } 

Celui-ci comporte trois paramètres :

  • $Log_Path : chemin du fichier de log.

  • $Message_Type : INFO, SUCCESS, ERROR ou ce que vous souhaitez....

Fonction de création de clé de registre

Cette fonction permettra de créer une clé de registre ou une valeur facilement.

Ci-dessous le script :

Function Set_Reg 
    { 
           param( 
           $Location, 
           $Name, 
           $Value, 
           $Type, 
           $Scope 
           ) 
 
           $Full_Reg_Key_Location = "$Scope" + ":\" + "$Location" 
           If(!(test-path $Full_Reg_Key_Location)){New-Item  
-Path $Full_Reg_Key_Location | out-null} 
 
           Try 
           { 
                 New-ItemProperty -Path $Full_Reg_Key_Location 
-Name $Name -Type $Type -Value $Value -Force -ea silentlycontinue...

Vérifier la validité d’un lien web

Il peut être utile de récupérer des informations depuis un site internet ou télécharger du contenu et donc de vérifier si ce site est fonctionnel et joignable.

L’idée sera de tester si un site web répond, un peu comme on pourrait le faire avec un ping sur un poste ou une adresse IP. Le lien du fichier que nous souhaitons vérifier est le suivant : https://github.com/damienvanrobaeys/ServiceUI/blob/main/ServiceUI.exe

Pour vérifier la connectivité, nous utiliserons la cmldet Invoke-WebRequest :

$Check_URL = invoke-webrequest $URL -UseBasicParsing 

ou :

$Check_URL = wget $URL -UseBasicParsing 

Nous vérifierons ensuite la valeur de la propriété StatusCode.

$Status = $Check_URL.StatusCode 
If($Status -eq 200){write-host "OK"}Else{write-host "KO"} 

Si la réponse est 200, alors le lien est valide.

Nous pouvons également utiliser le code suivant :

$Check_URL = [System.Net.WebRequest]::Create($URL) 
$Status = ($Check_URL.GetResponse()).StatusCode 

Ajoutons un caractère dans l’URL pour vérifier le résultat.

La réponse en erreur indique que le lien n’est pas joignable et donc non valide.

images/RI36_img1.png

Nous pouvons créer une fonction rapide qui nous permet de tester la validité d’une URL.

Function Get_URLStatus ...

Télécharger un fichier depuis Internet

Après avoir vérifié la validité d’un site web, la prochaine étape est donc de télécharger du contenu, tel qu’un fichier EXE ou autre.

L’URL sera toujours la même et nous devrons spécifier le chemin d’export du fichier.

$Fichier = "C:\ENI\ServiceUI.exe" 

Nous testerons deux méthodes.

Invoke-WebRequest

Nous allons utiliser la cmdlet Invoke-WebRequest en spécifiant l’URL et la sortie du fichier.

Invoke-WebRequest -Uri $URL -OutFile $Fichier 

Avec un objet

Procédez comme ci-dessous :

 Créez un objet WebClient.

$WebClient = New-Object System.Net.WebClient 

 Téléchargez le fichier avec la méthode DownloadFile.

$WebClient.DownloadFile($URL,$Fichier) 

Faire des captures d’écrans avec PowerShell

Et pourquoi pas faire des captures d’écrans avec PowerShell ? Cela peut être utile par exemple pour récupérer un message d’erreur depuis un script.

Nous utilisons cette fonctionnalité chez un client lors d’un déploiement de Task Sequence avec MECM. Si une erreur survient, une interface graphique s’affiche et permet au technicien de faire une capture d’écran même dans un environnement Windows PE (sans système d’exploitation ni applications).

La capture d’écran se fera avec le code suivant :

$Fichier = "C:\ENI\Capture.png" 
Add-Type -AssemblyName System.Windows.Forms 
Add-type -AssemblyName System.Drawing 
$Screen = [System.Windows.Forms.SystemInformation]::VirtualScreen 
$Width = $Screen.Width 
$Height = $Screen.Height 
$Left = $Screen.Left 
$Top = $Screen.Top 
$bitmap = New-Object System.Drawing.Bitmap $Width, $Height 
$graphic = [System.Drawing.Graphics]::FromImage($bitmap) 
$graphic.CopyFromScreen($Left, $Top, 0, 0, $bitmap.Size) 
$bitmap.Save($Fichier) 

Zipper et dézipper

Dans cette section nous allons créer des fichiers, des dossiers compressés (ZIP), mais également décompresser des éléments de manière automatisée.

Zipper du contenu

Dans l’exemple suivant, nous allons zipper le dossier C:\ENI.

La cmdlet utilisée pour créer un fichier ZIP est Compress-Archive. Il faudra spécifier le chemin du contenu à zipper et le chemin du fichier ZIP de sortie.

$A_zipper = "C:\ENI" 
$ZIP_Path = "C:\ENI\MonZIP.zip" 
Compress-Archive -Path $A_zipper -DestinationPath $ZIP_Path -Force 

Dézipper du contenu

La cmdlet utilisée pour extraire une archive est Expand-Archive. Il faudra spécifier le chemin du contenu à extraire et le chemin de destination de l’extraction. 

$UnZIP_Path = "C:\ENI\ZIP" 
Expand-Archive -LiteralPath $ZIP_Path -DestinationPath $UnZIP_Path 

Créer un journal d’évènements et ajouter un évènement

Lors de l’exécution d’une action au travers d’un script qui touche le système, la partie applicative, il peut être très utile de créer un fichier de log afin de savoir plus tard ce qui a été fait. Outre la création d’un fichier, il est également possible de créer une nouvelle entrée dans le gestionnaire Windows, comme le font déjà nativement Windows et de nombreuses applications.

Créer un nouveau journal

L’observateur d’évènements Windows contient différents journaux dont les plus utilisés sont :

  • Journaux Windows

  • Journaux des applications et des services

Nous allons ici créer un nouveau journal pour les application et les services.

Celui-ci sera un journal dédié à l’exécution de notre ou nos scripts.

L’idée sera donc que tous les scripts exécutés dans notre contexte d’entreprise puissent enregistrer les actions et statuts dans le journal que nous allons créer. Cherchons donc les cmdlets disponibles dans PowerShell permettant de gérer les journaux d’évènements.

Comme mentionné dans le chapitre Quelques bonnes pratiques, il faut prendre l’habitude d’utiliser la cmdlet Get-Command pour chercher...

Exporter un journal d’évènements

Nous souhaitons exporter le contenu d’un journal d’évènements sous la forme d’un fichier. Cela pourra être utile pour dépanner des utilisateurs à distance et récupérer les différentes sources d’informations pour trouver le problème.

Le script à utiliser est le suivant :

Function Export_EventLog 
    { 
           param( 
           $Log, 
           $Output, 
           $File 
           ) 
 
           If(!(test-path $Output)){new-item $Output -Type  
Directory -Force | out-null} 
           Write_Log -Message_Type "INFO" -Message "Récupération 
du journal: $Log" 
           Try 
                 { 
                        WEVTUtil...

Générer un GUID

Parfois, il est utile d’utiliser quelque chose pour identifier une ressource, un objet… Pour cela, il faut que cet identificateur soit unique. Nous utiliserons un GUID (Globally Unique IDentifier), qui est un terme générique pour désigner un identifiant sous forme de chiffres.

En PowerShell, il est facilement possible de générer des GUID à l’aide de la cmdlet suivante :

New-Guid 

Pour obtenir directement le GUID :

(New-Guid).guid 

Ci-dessous le résultat obtenu en exécutant cette cmdlet :

images/36RI07.png

Il est également possible de générer un GUID en utilisant la classe [guid].

[guid]::NewGuid() 

Pour obtenir directement le GUID :

[guid]::NewGuid().guid 

Générer un mot de passe

Nous allons voir ici différentes manières de générer un mot de passe à réutiliser.

Dans ce premier exemple, nous allons utiliser la classe nommée System.Web.Security.Membership. Celle-ci est incluse de base dans votre système d’exploitation Windows.

Pour charger cette classe, nous utiliserons le code ci-dessous :

Add-Type -AssemblyName System.Web 

Pour générer le mot de passe, nous utiliserons la méthode nommée GeneratePassword incluse dans cette classe.

[System.Web.Security.Membership]::GeneratePassword() 

La méthode GeneratePassword utilise deux paramètres pour générer le mot de passe :

  • Param1 : longueur du mot de passe, nombre de caractères contenus dans votre mot de passe.

  • Param2 : nombre de caractères spéciaux à intégrer dans votre mot de passe.

Cela s’utilisera de la manière suivante :

[System.Web.Security.Membership]::GeneratePassword(Param1,Param2) 

Dans l’exemple suivant, nous allons créer un mot de passe contenant cinq caractères avec cinq caractères spéciaux :

[System.Web.Security.Membership]::GeneratePassword(5,5) 

Ci-dessous le résultat obtenu :

images/36RI08.png

Dans l’exemple suivant, nous allons créer un mot de passe contenant dix caractères avec quatre caractères spéciaux :...

Chercher une chaîne dans l’observateur d’évènements

Nous souhaitons ici parcourir l’observateur d’évènements à la recherche d’un évènement comportant un mot précis.

Nous allons tout d’abord vérifier si ce mot précis existe dans un journal d’évènements donné.

Ici, nous allons rechercher les éléments suivants :

  • Journal d’évènements : Sécurité

  • Mot à rechercher : Administrators

Nous utiliserons la cmdlet Get-EventLog pour effectuer notre recherche.

Get-EventLog Security -InstanceId 4732 -ea silentlycontinue |  
Format_List 

Ci-dessous le résultat :

images/RI36_img4.png

Il est également possible d’utiliser la cmdlet Get-WinEvent, tel que ci-dessous :

Get-WinEvent -LogName Security | where {$_.Id -eq 4732} |  
Select-String -InputObject {$_.message} -Pattern 'Administrators' 

Identifier les comptes administrateurs locaux

Dans l’exemple suivant, nous allons utiliser PowerShell afin de vérifier les postes pour lesquels un compte utilisateur a été ajouté en tant qu’administrateur local, c’est-à-dire dans le groupe Administrateurs. En effet, il n’est pas vraiment recommandé de laisser les utilisateurs être administrateurs de leur poste si ce poste est géré par une entreprise. Cela permettra d’éviter de nombreux problèmes tels qu’un utilisateur qui a installé ou désinstallé une application, un driver ou autre. S’il s’agit du poste personnel de l’utilisateur, c’est bien entendu différent.

Nous définirons un compte qui aura le droit d’être dans le groupe Administrateurs. Notre script effectuera les actions suivantes :

  • Vérifier les comptes localisés dans le groupe Administrateurs du poste.

  • Comparer ces comptes avec le compte autorisé.

  • Afficher les comptes non autorisés.

Ci-dessous le script concerné :

$Get_Local_AdminGroup = Gwmi win32_group -Filter "Domain= 
'$env:computername' and SID='S-1-5-32-544'" 
$Get_Local_AdminGroup_Name = $Get_Local_AdminGroup.Name 
$Get_Administrator_Name = $Get_Local_AdminGroup_Name -replace ".$" 
$Authorized_Accounts += $Get_Administrator_Name ...

Obtenir la date de dernier redémarrage

Il s’agit ici de la date de dernier redémarrage ou, autrement dit, la date depuis laquelle le poste est allumé. Lorsqu’un utilisateur rencontre un problème, il arrive régulièrement qu’un simple redémarrage de la machine le résolve, car trop souvent le poste n’est pas redémarré régulièrement. Il peut donc être utile d’obtenir la date de dernier redémarrage avec PowerShell.

Il est possible de l’obtenir simplement en interrogeant la classe WMI Win32_OperatingSystem et la propriété LastBootUpTime.

PS C:\Users\damien.vanrobaeys> (Get-CimInstance -ClassName  
Win32_OperatingSystem).LastBootUpTime 
 
jeudi 20 octobre 2022 09:06:49 

Cependant, cette méthode a une limite et peut parfois retourner la mauvaise date. En effet, si l’option de démarrage rapide de Windows est activée sur le poste, la date de dernier redémarrage utilisant LastBootUpTime peut être fausse. Dans ce cas, si l’utilisateur éteint son poste au lieu de le redémarrer, la commande mentionnée plus haut retournera quand même que le poste n’a pas été redémarré depuis x jours ou heures. La propriété LastBootUpTime attendra véritablement un vrai redémarrage pour changer la date. Nous obtenons également le même résultat dans la partie Performances du Gestionnaire des tâches.

Quel peut être l’impact ?

Prenons l’exemple suivant : nous souhaitons planifier tous les trois jours un script permettant d’afficher une notification de redémarrage à l’utilisateur (si le poste n’a pas été redémarré depuis plus de deux jours).

Si l’option démarrage rapide est activée et que l’utilisateur a l’habitude d’éteindre son poste tous les jours, il risque de recevoir régulièrement la notification alors que, pour lui, un arrêt du poste est identique à un redémarrage.

Comment résoudre cela ?

Il faudra pour cela :

  • vérifier si le démarrage rapide est activé,

  • si non, nous vérifierons...

Vérifier qu’un script s’exécute en administrateur

Bien souvent, des scripts doivent s’exécuter dans un contexte administrateur afin d’effectuer diverses actions.

Afin de vérifier que c’est bien le cas, nous utiliserons le code suivant en début de script :

$Run_As_Admin = ([Security.Principal.WindowsPrincipal]  
[Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole 
([Security.Principal.WindowsBuiltInRole]::Administrator) 
If($Run_As_Admin -eq $False) 
    { 
           write-warning "non admin" 
           break 
    }