À placer au début du script (en dessous de Param).
# Renforce les règles de vérification et créé une erreur si elles ne sont pas respectéesSet-StrictMode-Version Latest
# Stop le script à la première erreur (par défaut à Continue)$ErrorActionPreference = "Stop"# en ligne de commande: .\MyScript.ps1 -ErrorAction Stop# Force tous les Cmdlet à s'arrêter à la première erreur$PSDefaultParameterValues['*:ErrorAction'] = 'Stop'
# commentaire<# commentaires
commentaires #># multilines command
command -option1 `
-option2# multiple commands on 1 line
command1; command2
# tester une commande: affiche le résultat mais n’exécute pas la commande
Commande -WhatIf# exécuter un fichier depuis la console cmd.exe
powershell -file MonFichier.ps1
# exécuter une commande depuis la console cmd.exe
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -command"& 'C:\dossier\script.ps1' args"# appeler un autre script powershell
& 'C:\dossier\script.ps1' args
# Supprimer l'attribut Read-Onlysp file.txt IsReadOnly $false# ouvrir explorer (Invoke-Item)ii .
# lancer internet explorer$ie = New-Object-ComObject InternetExplorer.Application
$ie.Navigate2("http://www.google.com")
$ie.Visible = $true# tester si la console est en mode admin
[bool](([System.Security.Principal.WindowsIdentity]::GetCurrent()).groups -match"S-1-5-32-544")
# installed version$PSVersionTable
# installation du module (console administrateur)Install-Module-Name PSWriteColor
Import-Module PSWriteColor
Write-Color"Red ", "Green ", "Yellow "-Color Red, Green, Yellow
wc "Red ", "Green ", "Yellow "-C Red, Green, Yellow
# -StartTab 1 ajoute une tabulation avant d'afficher le texte# -LinesBefore 1 passe une ligne avant d'afficher le texte# -LinesAfter 1 passe une ligne après avoir afficher le texte# -LogFile "C:\log.txt" écrit dans un fichier de log [YYYY-MM-DD HH:mm:ss]Texte
Read input
# lire l'entrée clavier$input = Read-Host'Question?'# Press any key to continueWrite-Host-NoNewLine'Press any key to continue...';
$null = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown');
GridView
# afficher une fenêtre avec une grilleNew-Object Net.Webclient | Get-Member | Out-GridView# permettre de séléctionner des éléments dans la grille et de s'en servir comme paramètres d'entréeGet-Service |
Where Status -eq Stopped |
Out-GridView-PassThru |
Start-Service
Types
String
echo"Escape `"double-quotes`" `$1"# "double-quotes" $1echo"Retour à la ligne `r`n"# concaténation de stringecho'Text1 - ' + "Text2: $Var1, $(Var2.Prop1)"echo"Text: $(command)"# here-string: multiline string @""@ @''@echo@"
First line
Second line
"Quotes don't need to be escaped"
Plus, you can include variables: $MyVar
"@# has to be at the beginning of a new line'ABC'-replace'B','X'# AXC'ABC'-replace'\w$','X'# ABX'ABC'-replace'^(\w)(.+)(\w)$','$3$2$1'# CBA'ABC'-replace'^(?<first>\w)(.+)(?<last>\w)$','${last}$1${first}'# CBA'ABC'-replace'B'# AC'ABC'.replace('B', '') # AC'abc'.toupper() # ABC
Test string
$MyString-like'xxx*'# Returns true when string matches wildcard (-notlike)$MyString-match'xxx.+'# Returns true when string matches regex (-notmatch)$MyString.startswith('xxx')
if ($MyString) # not null and not emptyif (!$MyString) # null or empty
$nombre = 10if ($nombre-eq10) {
"Le nombre est 10."
}
elseif (($nombre-gt5) -and ($nombre-lt10) -or ($nombre-eq222)) {
"Le nombre est entre 5 et 10 ou égal à 222."
}
elseif (!($nombre-eq333)) {
"Le nombre est différent de 333."
}
else { "Surement 333" }
# parmi les résultats de command, n'affiche que UnePropriété (select = Select-Object)
command | select UnePropriété
# afficher seulement la valeur de UnePropriété (exp = expand = ExpandProperty)
(command).UnePropriété
command | select-exp UnePropriété
# parmi les résultats de command, n'affiche que les 10 premiers résultats
command | select-first10
La fonction doit être déclarée avant son utilisation.
Paramètres et Arguments
# doit se situer à la première ligne exécutable (au dessus de Set-StrictMode)param (
# avec une valeur par défaut
[string] $Name = "initial value",
# paramètre obligatoire# position permet de définir le paramètre sans son nom
[Parameter(Mandatory, Position = 0)]
[string] $Name,
# True par défaut. Valeurs: $true ou $false.
[Parameter(Position = 1)]
[bool] $BooleanValue,
# no parameter passed means false, and -SwitchValue means true
[switch] $SwitchValue,
# avec des alias (-e -ef)
[Alias('e','ef')]
[string] $excludeFolder
)
# utilisation avec les noms des paramètres
.\MonScript.ps1 -Name MyName -BooleanValue$false-SwitchValue# utilisation avec les positions
.\MonScript.ps1 MyName $false# test if a parameter has not been setif (!$PSBoundParameters.ContainsKey('excludeFolder')) { }
Mandatory , demande de manière interactive les paramètres s'ils ne sont pas spécifiés.
$args fonctionne avec les arguments passés à une fonction mais pas avec ceux passés à un script.
Validation
param (
[ValidateScript({ Test-Path$_ -PathTypeLeaf })] # run a command to validate the parameter
[string] $FilePath
)
Exclusive groups of mandatory elements
# ok: .\MyScript -Environment env1# ok: .\MyScript -Server srv1 -Database db1# ko: .\MyScript -Environment env1 -Server srv1 -Database db1
[CmdletBinding(DefaultParameterSetName='Env')] # by default, Env is usedParam (
[Parameter(ParameterSetName = 'Env', Mandatory = $true)]
[string] $Environment,
[Parameter(ParameterSetName = 'Srv', Mandatory = $true)]
[string] $Server
[Parameter(ParameterSetName = 'Srv', Mandatory = $true)]
[string] $Database
)
# to know which ParameterSetName has been usedecho$PSCmdlet.ParameterSetName # Env or Srv
[CmdletBinding()] # add this line at the top of the script fileParam ()
if ($PSBoundParameters['Verbose']) # test if Verbose has been passed as parameter
<#
.SYNOPSIS
A brief description.
.DESCRIPTION
A detailed description.
.EXAMPLE
PS> my-command -p value
output
A sample command, optionally followed by sample output and a description.
#>param (
# Description of the parameter. Equivalent to .PARAMETER help
[Alias('h')]
[switch] $help,
)
if ($help) {
get-help$MyInvocation.MyCommand.Path -detailedexit
}
# display the help content
MonScript.ps1 -hget-help MonScript.ps1 -detailedman MonScript.ps1 -detailed
# sort by namels C:\Dossier | sort# sort by LastWriteTime, last modified firstls C:\Dossier | sort-property LastWriteTime -Descending
Search by name
# look recursively for all the *.txt filesls-r-ErrorAction SilentlyContinue "*.txt"
Search by file content
# look recursively for files which contains xxxls-r C:\Dossier | sls"xxx" | group path | % name
# display all the occurences of xxx with 2 lines before and afterls-r C:\Dossier | sls"xxx"-context2# use quiet to return a boolean'123' | sls-quiet'2'# True
# return an array of newline-delimited strings$content = Get-Content .\file.txt
# return a string$content = Get-Content .\file.txt -raw# tail equivalent: display what is appended to the file in realtimeGet-Content .\file.txt -Wait-Tail1
(Get-Content .\file.txt) -replace'Text', 'Content' | Set-Content .\file.txt
(Get-Content .\file.txt) -replace'var=(\w+);', "var=$new_value;" | Set-Content .\file.txt
# multi-lines: remove <tag> and its content
(Get-Content .\file.txt -raw) -replace'(?s)<tag>.+</tag>' | Set-Content .\file.txt
# (?s) single line mode: add line breaks in the matching characters for .# using groups and new line
(Get-Content .\file.txt) -replace'(\d{3})', "`r`n`$1" | Set-Content .\file.txt
# use double quotes for `r`n and escape `$1# avoid Set-Content to add a new line by default at the end
(Get-Content .\file.txt -raw) -replace'regex', 'xxx'-join"`r`n" | Set-Content .\file.txt -NoNewline# force Set-Content to not add a new line and join all the read lines by new lines
XPath
$path = 'C:\file.xml'
[xml]$xml_content = Get-Content$path# get node contentselect-xml-path$path `
-xpath'/root/node[@attribute="value"]' `
| select-exp node `
| select value
# replace node content$node = $xml_content.SelectSingleNode('/root/node[@attribute="value"]')
$node.Value = 'xxx'$xml_content.save($path)
# display in the terminal$xml_content.save([Console]::Out)
# suppression d'un dossier et de son contenurm-r-fo C:\Dossier
# -r / -recurse# -fo / -force# -ErrorAction Continue# test before delete to avoid errorif (test-path C:\Dossier) { rm-r C:\Dossier }
# | Out-Null permet de masquer la sortieni C:\Dossier -type directory | Out-Null# -force écrase le fichier s'il existe déjà, pour un dossier cela permet juste d'éviter l'erreur « Item already exists »ni C:\Dossier -type directory -force
Alias de Remove-Item: del, erase, rd, ri, rm, rmdir
Alias de New-Item: ni
# copie de Fichier.txt dans Dossier2 sous le nom de Fichier2.txt# dans ce cas Dossier2 n'est pas créé s'il n'existe pascp C:\Dossier\Fichier.txt C:\Dossier2\Fichier2.txt
# copie récursive de Dossier dans Dossier2 (création de Dossier2 s'il n'existe pas)cp-recurse C:\Dossier C:\Dossier2
# copie récursive de l'arborescence de Dossier dans Dossier2 et copie des fichiers *.txt exclusivementcp C:\Dossier C:\Dossier2 -recurse-filter *.txt
# copie tous les *.txt en excluant les *.bak.txtcp C:\Dossier\*.txt C:\Dossier2 -exclude *.bak.txt
# copie récursive avec exclusion$from = convert-path (join-path$Path1'..\Dossier') # convert-path pour supprimer les ..ls-r$from-exclude *.pdb, *.xml | % {
cp$_.FullName (join-path$to$_.FullName.Substring($from.length))
}
Alias Copy-Itemcopycpcpi
Exclude ne fonctionne pas avec les répertoires
Measure / Count
ls | measure# Count : 8 # Average : # Sum : # Maximum : # Minimum : # Property : # compter le nombre d'éléments dans le dossier courant
(ls | measure).Count;
Log
# log in MyProgram.log in the same folderStart-Transcript-path$PSCommandPath.replace('.ps1', '.log')
# list processes by nameps | ? name -eq'firefox'Get-Process | ? { $_.ProcessName -like"*git*" }
# list processes by pathps | ? Path -match'firefox.exe$'# list processes which use a portGet-Process-Id (Get-NetTCPConnection-LocalPort135).OwningProcess
# test is a process is running$firefox = Get-Process firefox -ErrorAction SilentlyContinue
if ($firefox) {
echo'firefox is running'
}
# open a new powershell consolestart-process powershell -ArgumentList"-NoProfile -NoExit -Command echo $var"
# affiche l'état d'un serviceget-service'SQLBrowser'# Stopped / Running$ServiceName = 'MSSQL$SQLEXPRESS'if ((get-service$ServiceName).Status -eq'Stopped') {
# démarrer un service, nécessite les droits administrateurstart-service$ServiceName-PassThru# PassThru force l'affichage d'un message de sortie
}
else {
echo"$ServiceName est déjà démarré."
}
$RegKey ="HKCU:\Control Panel\Cursors"# Obtenir la valeur de la clé IBeamGet-ItemProperty-Path"HKCU:\Control Panel\Cursors" | select-ExpandProperty IBeam
# Changement de la valeur de la clé IBeamSet-ItemProperty-Path$RegKey-Name IBeam -Value"%SystemRoot%\cursors\beam_r.cur"
Use C# code
Add-Type-TypeDefinition@"
public class Compute {
public int Add(int n1, int n2) {
return n1 + n2;
}
}
"@# load an assemblyAdd-Type-Path C:\Folder\Compute.dll
$compute = New-Object Compute
$compute.Add(6, 4) # 10
Exemples
Recherche de texte dans tous les fichiers - rg - ripgrep
# C# wrapper around Windows API SystemParametersInfoAdd-Type-TypeDefinition@"
using System.Runtime.InteropServices;
namespace WinAPI {
public class DesktopWallpaper
{
public const int SetDesktopWallpaper = 0x14;
public const int UpdateIniFile = 0x01;
public const int SendWinIniChange = 0x02;
[DllImport("user32.dll", SetLastError=true, CharSet=CharSet.Auto)]
public static extern int SystemParametersInfo (int uAction,
int uParam,
string lpvParam,
int fuWinIni);
public static void SetWallpaper(string path)
{
SystemParametersInfo(SetDesktopWallpaper, 0, path, UpdateIniFile | SendWinIniChange);
}
}
}
"@
[WinAPI.DesktopWallpaper]::SetWallpaper('C:\image.jpg')
# ls | grep *.txtls | % fullname | findstr -i"\.txt\>"# -i Ignores the case of the characters when searching for the string# -v Prints only lines that do not contain a match# transforme la sortie objets en stream pour y faire une recherchels | out-string-stream | sls"\.txt"