« Powershell » : différence entre les versions
De Banane Atomic
Aller à la navigationAller à la recherche
(Page redirigée vers PowerShell) |
|||
(95 versions intermédiaires par le même utilisateur non affichées) | |||
Ligne 1 : | Ligne 1 : | ||
# | [[Category:Windows]] | ||
= Links = | |||
* [https://www.powershellgallery.com Powershell Gallery] | |||
* [https://docs.microsoft.com/en-us/powershell/dsc/overview DSC] | |||
* [[Powershell_configuration|Powershell configuration]] | |||
* [https://docs.microsoft.com/en-us/powershell/scripting/developer/cmdlet/approved-verbs-for-windows-powershell-commands Approved verbs] | |||
= Script template = | |||
À placer au début du script (en dessous de Param). | |||
<kode lang='ps'> | |||
# Renforce les règles de vérification et créé une erreur si elles ne sont pas respectées | |||
Set-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' | |||
</kode> | |||
* [https://docs.microsoft.com/en-us/powershell/module/Microsoft.PowerShell.Core/Set-StrictMode?view=powershell-5.1 Set-StrictMode] | |||
* [https://learn-powershell.net/2013/12/11/using-psdefaultparametervalues-in-powershell PSDefaultParameterValues] | |||
= Astuces = | |||
<kode lang=powershell> | |||
# 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-Only | |||
sp 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 | |||
</kode> | |||
= Variables = | |||
{{warn | Pas de {{boxx|-}} dans les noms des variables.}} | |||
<kode lang='ps'> | |||
$my_var = "value" | |||
</kode> | |||
== [https://ss64.com/ps/syntax-automatic-variables.html Environment Variables] == | |||
<kode lang='ps'> | |||
# list all environment variables | |||
dir env: | |||
# create an env variable. scopes are process, user, machine | |||
[System.Environment]::SetEnvironmentVariable('MyVar','value', 'user') | |||
[System.Environment]::SetEnvironmentVariable('MyVar','value', 'machine') | |||
</kode> | |||
{| class="wikitable wtp wtmono1" | |||
| $env:userprofile || C:\Users\<user> | |||
|- | |||
| $env:appdata || C:\Users\<user>\AppData\Roaming | |||
|- | |||
| $env:ProgramFiles || C:\Program Files | |||
|- | |||
| [environment]::getfolderpath("mydocuments") || C:\Users\<user>\Documents | |||
|} | |||
== [https://ss64.com/ps/syntax-automatic-variables.html Automatic Variables] == | |||
{| class="wikitable wtp wtmono1" | |||
|- | |||
| $_ || the current object in the pipeline | |||
|- | |||
| $home || C:\Users\<user> | |||
|- | |||
| $Pwd || full path of the current directory | |||
|- | |||
| $PSCommandPath || path of the script file that is being executed | |||
|- | |||
| $PSScriptRoot || path of the script directory that is being executed | |||
|} | |||
= echo, Write-Host = | |||
<kode lang='ps'> | |||
echo 'my text' | |||
# saut de ligne | |||
echo line1 line2 | |||
echo line1`nline2 | |||
echo line1([system.environment]::newline)line2 | |||
# colors | |||
Write-Host -foregroundcolor green -backgroundcolor black Mon Message | |||
# erreur | |||
Write-Error "Error!" | |||
</kode> | |||
{| class="wikitable wtp" | |||
|+ Couleurs disponibles | |||
| Black || Blue || Cyan || DarkBlue | |||
|- | |||
| DarkCyan || DarkGray || DarkGreen || DarkMagenta | |||
|- | |||
|DarkRed || DarkYellow || Gray || Green | |||
|- | |||
| Magenta || Red || White || Yellow | |||
|} | |||
{{info | {{boxx|echo}} is an alias of {{boxx|Write-Output}}}} | |||
== [https://evotec.xyz/hub/scripts/pswritecolor PSWriteColor] == | |||
<kode lang='powershell'> | |||
# 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 | |||
</kode> | |||
= Read input = | |||
<kode lang='ps'> | |||
# lire l'entrée clavier | |||
$input = Read-Host 'Question?' | |||
# Press any key to continue | |||
Write-Host -NoNewLine 'Press any key to continue...'; | |||
$null = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown'); | |||
</kode> | |||
= GridView = | |||
<kode lang='ps'> | |||
# afficher une fenêtre avec une grille | |||
New-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ée | |||
Get-Service | | |||
Where Status -eq Stopped | | |||
Out-GridView -PassThru | | |||
Start-Service | |||
</kode> | |||
= Types = | |||
== String == | |||
<kode lang='ps'> | |||
echo "Escape `"double-quotes`" `$1" # "double-quotes" $1 | |||
echo "Retour à la ligne `r`n" | |||
# concaténation de string | |||
echo '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 | |||
</kode> | |||
=== Test string === | |||
<kode lang='ps'> | |||
$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 empty | |||
if (!$MyString) # null or empty | |||
</kode> | |||
* [https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_comparison_operators About Comparison Operators] | |||
== Date == | |||
<kode lang='ps'> | |||
Get-Date -Format 'yyyy-MM' # 2020-01 | |||
</kode> | |||
== Tableau / array == | |||
<kode lang='ps'> | |||
$myArray = @() # empty | |||
$myArray = 1, 2, 3 # 1 2 3 | |||
$myArray += 4 # 1 2 3 4 | |||
$myArray.Length # 4 | |||
$myArray[1..2] # 2 3 sub array from index 1 to index 2 | |||
$myArray[-1] # 4 latest value of the array | |||
$myArray -ne 2 # 1 3 4 | |||
$myArray -gt 2 # 3 4 | |||
[array]::Reverse($myArray) # 4 3 2 1 | |||
$one, $two, $rest = $myArray # $one = 1, $two = 2, $rest = 3, 4 | |||
</kode> | |||
== [https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_hash_tables Hash table] == | |||
<kode lang='ps'> | |||
$myHashTable = @{} # empty | |||
$myHashTable = @{ | |||
Key1 = 'Value1' | |||
} | |||
$myHashTable = [ordered]@{ | |||
Key1 = 'Value1' | |||
} | |||
# add key and update value | |||
$myHashTable.Key1 = "Value1" | |||
$myHashTable["Key2"] = "Value2" | |||
echo $myHashTable | |||
# Name Value | |||
# ---- ----- | |||
# Key1 Value1 | |||
# Key2 Value2 | |||
$myValue = $myHashTable.Key1 | |||
$myValue = $myHashTable["Key1"] | |||
$myValue = $myHashTable.$myKey | |||
"All keys: $($myHashTable.keys)" | |||
"All values: $($myHashTable.values)" | |||
if (!$myHashTable.contains($myKey)) | |||
</kode> | |||
== PSObject == | |||
<kode lang='ps'> | |||
$obj = New-Object PSObject -Property @{ | |||
Prop1 = "Value1" | |||
Prop2 = "Value2" | |||
} | |||
</kode> | |||
= if else = | |||
<kode lang=powershell> | |||
$nombre = 10 | |||
if ($nombre -eq 10) { | |||
"Le nombre est 10." | |||
} | |||
elseif (($nombre -gt 5) -and ($nombre -lt 10) -or ($nombre -eq 222)) { | |||
"Le nombre est entre 5 et 10 ou égal à 222." | |||
} | |||
elseif (!($nombre -eq 333)) { | |||
"Le nombre est différent de 333." | |||
} | |||
else { "Surement 333" } | |||
</kode> | |||
{| class="wikitable wtp" | |||
! Opérateur | |||
! Description | |||
! Opérateur | |||
! Description | |||
|- | |||
| -eq || == || -ceq || == case senstivie | |||
|- | |||
| -ne || != | |||
|- | |||
| -lt || < || -le || <= | |||
|- | |||
| -gt || > || -ge || >= | |||
|- | |||
| -not ! || ! | |||
|- | |||
| -and || && || -or || <nowiki>||</nowiki> | |||
|- | |||
| -band || & || -bor || <nowiki>|</nowiki> | |||
|} | |||
== Test string == | |||
<kode lang=bash> | |||
if ([string]::IsNullOrEmpty($monString)) | |||
</kode> | |||
[https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-powershell-1.0/ee692804(v=technet.10) The String’s the Thing] | |||
= [https://kevinmarquette.github.io/2018-01-12-Powershell-switch-statement/#switch-statement switch] = | |||
<kode lang='powershell'> | |||
switch ($var) | |||
{ | |||
'value1' { echo $var } | |||
'value2' { echo $var } | |||
default { echo 'unknown value' } | |||
} | |||
$result = switch ($var) | |||
{ | |||
'Word1' { 'Value1' } | |||
'Word2' { 'Value2' } | |||
default { 'Default Value' } | |||
} | |||
</kode> | |||
= [http://technet.microsoft.com/en-us/library/ee176955.aspx Select] = | |||
<kode lang=powershell> | |||
# 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 -first 10 | |||
</kode> | |||
= [http://technet.microsoft.com/en-us/library/ee177028.aspx Where ?] = | |||
<kode lang=powershell> | |||
1..4 | ? {$_ % 2 -eq 0} # 2 4 | |||
</kode> | |||
{{info | Alias: {{boxx|Where-Object}} {{boxx|where}} {{boxx|?}}}} | |||
= ForEach % = | |||
<kode lang='ps'> | |||
1..4 | % { $_ * 2 } # 2 4 6 8 | |||
1..4 | % { # opening bracket has to be on the same line as percent sign | |||
$_ * 2 | |||
} | |||
</kode> | |||
= [https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_functions Fonctions] = | |||
<kode lang=powershell> | |||
function TestName { | |||
param( | |||
[Parameter(Mandatory=$true, ValueFromPipeline=$true)] | |||
[string] $nom | |||
) | |||
if ($nom -eq "moi") | |||
{ | |||
return $true | |||
} | |||
return $false | |||
} | |||
TestName "moi" | |||
# True | |||
</kode> | |||
{{info | La fonction doit être déclarée avant son utilisation.}} | |||
= Paramètres et Arguments = | |||
<kode lang=powershell> | |||
# 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 set | |||
if (!$PSBoundParameters.ContainsKey('excludeFolder')) { } | |||
</kode> | |||
{{info | {{boxx|1= Mandatory}} , demande de manière interactive les paramètres s'ils ne sont pas spécifiés.}} | |||
{{warn | {{boxx|$args}} fonctionne avec les arguments passés à une fonction mais pas avec ceux passés à un script.}} | |||
== [https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_functions_advanced_parameters?view=powershell-7.2#parameter-and-variable-validation-attributes Validation] == | |||
<kode lang='powershell'> | |||
param ( | |||
[ValidateScript({ Test-Path $_ -PathType Leaf })] # run a command to validate the parameter | |||
[string] $FilePath, | |||
[ValidateSet('jpg', 'png')] # validate against a list and add auto-completion | |||
[string] $ImageFileExtension | |||
) | |||
</kode> | |||
== Exclusive groups of mandatory elements == | |||
<kode lang=powershell> | |||
# 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 used | |||
Param ( | |||
[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 used | |||
echo $PSCmdlet.ParameterSetName # Env or Srv | |||
</kode> | |||
== [https://nancyhidywilson.wordpress.com/2011/11/21/powershell-using-common-parameters Common parameters] == | |||
{| class="wikitable wtp wtmono1" | |||
! Parameter | |||
|- | |||
| -Debug | |||
|- | |||
| -ErrorAction | |||
|- | |||
| -ErrorVariable | |||
|- | |||
| -OutBuffer | |||
|- | |||
| -OutVariable | |||
|- | |||
| -Verbose | |||
|- | |||
| -WarningAction | |||
|- | |||
| -WarningVariable | |||
|} | |||
<kode lang='ps'> | |||
[CmdletBinding()] # add this line at the top of the script file | |||
Param () | |||
if ($PSBoundParameters['Verbose']) # test if Verbose has been passed as parameter | |||
</kode> | |||
== Help content == | |||
* [https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_comment_based_help?view=powershell-7.1 About Comment-based Help] | |||
* [https://docs.microsoft.com/en-us/powershell/scripting/developer/help/examples-of-comment-based-help?view=powershell-7.1 Examples of Comment-Based Help] | |||
<kode lang=powershell> | |||
<# | |||
.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 -detailed | |||
exit | |||
} | |||
# display the help content | |||
MonScript.ps1 -h | |||
get-help MonScript.ps1 -detailed | |||
man MonScript.ps1 -detailed | |||
</kode> | |||
= Files and folders = | |||
== [https://technet.microsoft.com/fr-fr/library/hh849800%28v=wps.620%29.aspx List] == | |||
<kode lang='ps'> | |||
# display names only | |||
ls C:\Dossier -Name | |||
# display fullnames (C:\Dossier\filename.ext) | |||
ls C:\Dossier | % FullName | |||
# display names without the extension | |||
ls C:\Dossier | % BaseName | |||
# filter | |||
ls C:\Dossier *.txt | |||
# exclude *.txt et *.dll | |||
ls C:\Dossier -exclude *.txt, *.dll | |||
# filter against RegEx (-NotMatch, -NotLike) | |||
ls C:\Dossier | ? Name -Match "\.txt$" # RegEx | |||
ls C:\Dossier | ? Name -Like "*.txt" # Wildcard Expression | |||
# lister toutes les DLL et EXE avec leurs versions | |||
ls *.dll,*.exe | % { "{0}`t{1}" -f $_.Name, [System.Diagnostics.FileVersionInfo]::GetVersionInfo($_).FileVersion } | |||
</kode> | |||
{{info | {{boxx|ls}} {{boxx|dir}} {{boxx|gci}} are aliases of {{boxx|Get-ChildItem}}}} | |||
{{warn | {{boxx|filter}} et {{boxx|exclude}} ne fonctionnent pas en même temps.<br> | |||
Utiliser * dans le chemin à la place de {{boxx|filter}}}} | |||
{{warn | {{boxx|-exclude}} only applies to basenames of items {{boxx|myfile.txt}}, not the fullname {{boxx|C:\folder\myfile.txt}}}} | |||
== [https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/sort-object?view=powershell-6 sort] == | |||
<kode lang='ps'> | |||
# sort by name | |||
ls C:\Dossier | sort | |||
# sort by LastWriteTime, last modified first | |||
ls C:\Dossier | sort -property LastWriteTime -Descending | |||
</kode> | |||
== Search by name == | |||
<kode lang='ps'> | |||
# look recursively for all the *.txt files | |||
ls -r -ErrorAction SilentlyContinue "*.txt" | |||
</kode> | |||
== Search by file content == | |||
<kode lang='ps'> | |||
# look recursively for files which contains xxx | |||
ls -r C:\Dossier | sls "xxx" | group path | % name | |||
# display all the occurences of xxx with 2 lines before and after | |||
ls -r C:\Dossier | sls "xxx" -context 2 | |||
# use quiet to return a boolean | |||
'123' | sls -quiet '2' # True | |||
</kode> | |||
{{info | {{boxx|sls}} is an alias of {{boxx|Select-String}}}} | |||
{{warn | {{boxx|context}} ne semble plus fonctionner}} | |||
== [https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.management/get-content Read / Get content] == | |||
<kode lang='ps'> | |||
# 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 realtime | |||
Get-Content .\file.txt -Wait -Tail 1 | |||
</kode> | |||
== [https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.management/set-content?view=powershell-7 Write / Set content] == | |||
<kode lang='ps'> | |||
Set-Content -Encoding UTF8 -Path .\file.txt -Value 'Text' | |||
</kode> | |||
{| class="wikitable wtp" | |||
|+ [https://docs.microsoft.com/en-us/dotnet/api/microsoft.powershell.commands.filesystemcmdletproviderencoding Encoding values] | |||
|- | |||
| Default || UTF-8 without BOM | |||
|- | |||
| UTF8 || UTF-8 with BOM (BOM for UTF-8 files is not recommended) | |||
|} | |||
== Replace content == | |||
{{warn | The default encoding is UTF-8 without BOM}} | |||
<kode lang='ps'> | |||
(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 | |||
</kode> | |||
== XPath == | |||
<kode lang='ps'> | |||
$path = 'C:\file.xml' | |||
[xml]$xml_content = Get-Content $path | |||
# to preserve the whitespaces | |||
$xml_content = [xml]::new() | |||
$xml_content .PreserveWhitespace = $true | |||
$xml_content .Load($path) | |||
# get node content | |||
select-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) | |||
</kode> | |||
* [https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/select-xml select-xml] | |||
== Delete files based on pattern == | |||
<kode lang='ps'> | |||
# delete all the *.txt files | |||
ls *.txt | Remove-Item | |||
</kode> | |||
== [https://www.powershellgallery.com/packages/Recycle Put to the recycle bin] == | |||
<kode lang='ps'> | |||
# in admin console | |||
Install-Module -Name Recycle | |||
Remove-ItemSafely [FileName|FolderName] | |||
# alias | |||
New-Alias trash 'Remove-ItemSafely' | |||
</kode> | |||
== [https://technet.microsoft.com/en-us/library/ee176914.aspx Créer / supprimer un dossier] == | |||
<kode lang=ps> | |||
# suppression d'un dossier et de son contenu | |||
rm -r -fo C:\Dossier | |||
# -r / -recurse | |||
# -fo / -force | |||
# -ErrorAction Continue | |||
# test before delete to avoid error | |||
if (test-path C:\Dossier) { rm -r C:\Dossier } | |||
# | Out-Null permet de masquer la sortie | |||
ni 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 | |||
</kode> | |||
{{info | Alias de Remove-Item: del, erase, rd, ri, rm, rmdir<br> | |||
Alias de New-Item: ni}} | |||
[https://technet.microsoft.com/fr-fr/library/hh849765%28v=wps.620%29.aspx Remove-Item] | |||
= Path = | |||
<kode lang=powershell> | |||
# dossier1\dossier2 | |||
join-path dossier1 dossier2 | |||
join-path -path dossier1 -childpath dossier2 | |||
join-path -path dossier1\ -childpath \dossier2\ | |||
join-path -path dossier1 -childpath (join-path -path dossier2 -childpath dossier3) | |||
# dossier1\dossier2\dossier3 | |||
# utilisation du Framework .NET | |||
[System.IO.Path]::Combine("C:\Dossier1", "Dossier2", "Dossier3") | |||
# C:\Dossier1\Dossier2\Dossier3 | |||
# test si le chemin c:\dossier existe | |||
if (Test-Path C:\Dossier -PathType Container) { } | |||
# test si le fichier c:\dossier\file.txt existe | |||
if (Test-Path C:\Dossier\file.txt -PathType Leaf) { } | |||
</kode> | |||
* [https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.management/test-path Test-Path] | |||
= [http://technet.microsoft.com/fr-fr/library/hh849793%28v=wps.620%29.aspx Copy-Item] = | |||
<kode lang=powershell> | |||
# copie de Fichier.txt dans Dossier2 sous le nom de Fichier2.txt | |||
# dans ce cas Dossier2 n'est pas créé s'il n'existe pas | |||
cp 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 exclusivement | |||
cp C:\Dossier C:\Dossier2 -recurse -filter *.txt | |||
# copie tous les *.txt en excluant les *.bak.txt | |||
cp 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)) | |||
} | |||
</kode> | |||
{{info | Alias {{boxx|Copy-Item}} {{boxx|copy}} {{boxx|cp}} {{boxx|cpi}}}} | |||
{{warn | Exclude ne fonctionne pas avec les répertoires}} | |||
= Measure / Count = | |||
<kode lang=powershell> | |||
ls | measure | |||
# Count : 8 | |||
# Average : | |||
# Sum : | |||
# Maximum : | |||
# Minimum : | |||
# Property : | |||
# compter le nombre d'éléments dans le dossier courant | |||
(ls | measure).Count; | |||
</kode> | |||
= Log = | |||
<kode lang='ps'> | |||
# log in MyProgram.log in the same folder | |||
Start-Transcript -path $PSCommandPath.replace('.ps1', '.log') | |||
</kode> | |||
= [https://ss64.com/ps/syntax-esc.html Échapper les caractères spéciaux] = | |||
<kode lang='powershell'> | |||
echo '$dollar' # $dollar | |||
echo `$dollar # $dollar | |||
</kode> | |||
= Encoding = | |||
Si la sortie affiche des caractères inattendus, utiliser l'encodage UTF-8 avec BOM. | |||
= [http://ss64.com/ps/syntax-regex.html Expressions rationnelles] = | |||
= Shutdown - Restart = | |||
<kode lang='ps'> | |||
Stop-Computer | |||
Restart-Computer | |||
</kode> | |||
[[Batch#Shutdown.2C_restart.2C_sleep|Batch commands]] | |||
= SQL server = | |||
* [https://docs.microsoft.com/en-us/powershell/module/sqlserver/backup-sqldatabase?view=sqlserver-ps Backup-SqlDatabase] | |||
* [https://docs.microsoft.com/en-us/powershell/module/sqlserver/restore-sqldatabase?view=sqlserver-ps Restore-SqlDatabase] | |||
<kode lang='ps'> | |||
$SqlConn = New-Object System.Data.SqlClient.SqlConnection | |||
$SqlConn.ConnectionString = "Server=XXX\YYY;Database=ZZZ;User Id=UUU;Password=PPP;" | |||
$SqlConn.Open() | |||
$SqlCmd = $SqlConn.CreateCommand() | |||
$SqlCmd.CommandText = "SELECT name, database_id FROM sys.databases" | |||
$SqlAdapter = New-Object System.Data.SqlClient.SqlDataAdapter | |||
$SqlAdapter.SelectCommand = $SqlCmd | |||
$DataSet = New-Object System.Data.DataSet | |||
$SqlAdapter.Fill($DataSet) | |||
$DataSet.Tables[0] | |||
#$DataSet.Tables[0] | out-file "C:\Folder\result.csv" | |||
</kode> | |||
= [https://docs.microsoft.com/en-us/powershell/module/addsadministration/?view=win10-ps Active Directory] = | |||
* Install [https://www.microsoft.com/en-us/download/details.aspx?id=45520 Remote Server Administration Tools] | |||
<kode lang='powershell'> | |||
Import-Module activedirectory | |||
Get-ADUser -filter * | |||
</kode> | |||
* [[Azure#PowerShell|Azure Active Directory]] | |||
= Process = | |||
<kode lang='ps'> | |||
# list processes by name | |||
ps | ? name -eq 'firefox' | |||
Get-Process | ? { $_.ProcessName -like "*git*" } | |||
# list processes by path | |||
ps | ? Path -match 'firefox.exe$' | |||
# list processes which use a port | |||
Get-Process -Id (Get-NetTCPConnection -LocalPort 135).OwningProcess | |||
# test is a process is running | |||
$firefox = Get-Process firefox -ErrorAction SilentlyContinue | |||
if ($firefox) { | |||
echo 'firefox is running' | |||
} | |||
# open a new powershell console | |||
start-process powershell -ArgumentList "-NoProfile -NoExit -Command echo $var" | |||
</kode> | |||
* [https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.management/start-process Start-Process] | |||
* [https://ss64.com/ps/powershell.html powershell.exe] | |||
= [https://4sysops.com/archives/managing-services-the-powershell-way-part-3 Services] = | |||
<kode lang=powershell> | |||
# affiche l'état d'un service | |||
get-service 'SQLBrowser' | |||
# Stopped / Running | |||
$ServiceName = 'MSSQL$SQLEXPRESS' | |||
if ((get-service $ServiceName).Status -eq 'Stopped') { | |||
# démarrer un service, nécessite les droits administrateur | |||
start-service $ServiceName -PassThru | |||
# PassThru force l'affichage d'un message de sortie | |||
} | |||
else { | |||
echo "$ServiceName est déjà démarré." | |||
} | |||
</kode> | |||
= Users = | |||
<kode lang='ps'> | |||
# list connected users | |||
query user /server:$SERVER | |||
</kode> | |||
= MessageBox = | |||
<kode lang=powershell> | |||
[void][Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") | |||
[void][System.Windows.Forms.MessageBox]::Show("Hello !") | |||
</kode> | |||
= Web = | |||
{{info | 1={{boxx|wget}} et {{boxx|iwr}} sont des alias de [https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/invoke-webrequest?view=powershell-7 Invoke-WebRequest]}} | |||
<kode lang='powershell'> | |||
# get the content and detect the output format: XML or JSON | |||
Invoke-RestMethod http://www.domain.net/api/values | % { $_ | select Prop1, Prop2 | Out-GridView } | |||
Invoke-RestMethod http://localhost:111/api/values -Method POST -Body @{value='2'} | |||
Invoke-WebRequest http://localhost:111/api/values -H @{"accept"="application/xml"} | Select-Object -Expand Content | |||
$content = (New-Object Net.WebClient).DownloadString("http://www.google.fr") | |||
wget http://www.domain.net/file.txt -outfile folder\file.txt | |||
</kode> | |||
== Target HTML == | |||
<kode lang='ps'> | |||
$url = "http://www.domain.net" | |||
$result = Invoke-WebRequest $url | |||
$result.AllElements | | |||
Where Class -eq "some css class" | | |||
Select -First 1 -ExpandProperty innerText | |||
</kode> | |||
= [http://www.computerperformance.co.uk/powershell/powershell_registry.htm Registre] = | |||
<kode lang='powershell'> | |||
$RegKey ="HKCU:\Control Panel\Cursors" | |||
# Obtenir la valeur de la clé IBeam | |||
Get-ItemProperty -Path "HKCU:\Control Panel\Cursors" | select -ExpandProperty IBeam | |||
# Changement de la valeur de la clé IBeam | |||
Set-ItemProperty -Path $RegKey -Name IBeam -Value "%SystemRoot%\cursors\beam_r.cur" | |||
</kode> | |||
= Use C# code = | |||
<kode lang='ps'> | |||
Add-Type -TypeDefinition @" | |||
public class Compute { | |||
public int Add(int n1, int n2) { | |||
return n1 + n2; | |||
} | |||
} | |||
"@ | |||
# load an assembly | |||
Add-Type -Path C:\Folder\Compute.dll | |||
$compute = New-Object Compute | |||
$compute.Add(6, 4) # 10 | |||
</kode> | |||
= Exemples = | |||
== Recherche de texte dans tous les fichiers - rg - ripgrep == | |||
<kode lang='powershell' collapsed> | |||
Function rg { | |||
param( | |||
[Parameter(Mandatory=$true, ValueFromPipeline=$true)] | |||
[string] | |||
$pattern | |||
) | |||
ls -r | sls $pattern -context 2 | | |||
foreach { | |||
"{0} : {1:00}" -f $_.Path, $_.LineNumber | |||
if ($_.Context.PreContext) {" {0}" -f $_.Context.PreContext } | |||
"> {0}" -f $_.Line | |||
if ($_.Context.PostContext) { " {0}" -f $_.Context.PostContext } | |||
"" | |||
} | |||
} | |||
</kode> | |||
== [https://social.technet.microsoft.com/wiki/contents/articles/4546.working-with-passwords-secure-strings-and-credentials-in-windows-powershell.aspx Stocker et récupérer un mot de passe] == | |||
<kode lang='powershell' collapsed> | |||
# store password | |||
$Password = "Password123!@#" | |||
$SecurePassword = $Password | ConvertTo-SecureString -AsPlainText -Force # SecureString | |||
# ou demande du password | |||
$SecurePassword = Read-Host -Prompt "Enter password" -AsSecureString | |||
# ou demande du password avec Get-Credential | |||
$Credential = Get-Credential -Message "Enter password" -Username "-" | |||
$SecurePassword = $Credential.Password | |||
$SecureStringAsPlainText = $SecurePassword | ConvertFrom-SecureString # String | |||
Set-Content "C:\Dossier\Password.txt" $SecureStringAsPlainText | |||
# get the password | |||
$SecureStringAsPlainText = Get-Content "C:\Dossier\Password.txt" # String | |||
$SecurePassword = $SecureStringAsPlainText | ConvertTo-SecureString # SecureString | |||
$Credential = New-Object PSCredential "user",$SecurePassword | |||
$PlainPassword = $Credential.GetNetworkCredential().Password # password en clair | |||
</kode> | |||
== [https://blogs.technet.microsoft.com/heyscriptingguy/2013/01/17/use-powershell-to-change-the-mouse-pointer-scheme/ Modifier le pointeur de la sourie] == | |||
<kode lang='powershell' collapsed> | |||
# changement du pointeur Text Selection | |||
$RegKey ="HKCU:\Control Panel\Cursors" | |||
Set-ItemProperty -Path $RegKey -Name IBeam -Value "%SystemRoot%\cursors\beam_r.cur" | |||
# Rafraichissement des curseurs pour prendre en compte le changement | |||
$CSharpSig = @' | |||
[DllImport("user32.dll", EntryPoint = "SystemParametersInfo")] | |||
public static extern bool SystemParametersInfo( | |||
uint uiAction, | |||
uint uiParam, | |||
uint pvParam, | |||
uint fWinIni); | |||
'@ | |||
$CursorRefresh = Add-Type -MemberDefinition $CSharpSig -Name WinAPICall -Namespace SystemParamInfo –PassThru | |||
$CursorRefresh::SystemParametersInfo(0x0057,0,$null,0) | |||
</kode> | |||
== [https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/get-filehash?view=powershell-6 SHA1] == | |||
<kode lang='powershell'> | |||
function sha1 { | |||
param( | |||
[Parameter(Mandatory=$true, ValueFromPipeline=$true)] | |||
[string] | |||
$file | |||
) | |||
(Get-FileHash -Algorithm SHA1 "$file")."Hash" | |||
} | |||
</kode> | |||
= [https://www.raydbg.com/2017/Call-Native-Win32-API-in-PowerShell/ Windows API] = | |||
== [https://stackoverflow.com/questions/43187787/change-wallpaper-powershell Set Wallpaper] == | |||
<kode lang='ps'> | |||
# C# wrapper around Windows API SystemParametersInfo | |||
Add-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') | |||
</kode> | |||
= [https://mathieubuisson.github.io/powershell-linux-bash/ Équivalents bash] = | |||
* [[Powershell_configuration#Bash_tools|Bash tools]] for Windows | |||
== find == | |||
<kode lang='ps'> | |||
# find . -type f -iname "filename" | |||
Get-ChildItem -Filter "*filename*" -Recurse -File | |||
ls -r -file *filename* | |||
</kode> | |||
== sed == | |||
{{warn | File encoding is changed to UTF-8 without BOM}} | |||
<kode lang='ps'> | |||
# sed 's/txt_to_replace/replacement_text/' -i file.txt | |||
(Get-Content file.txt) -replace 'txt_to_replace', 'replacement_text' | Set-Content file.txt | |||
(Get-Content file.txt) -replace '^(group1).*(group2)$', '$1 text $2' | Set-Content file.txt | |||
</kode> | |||
== grep == | |||
<kode lang='ps'> | |||
# ls | grep *.txt | |||
ls | % 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 recherche | |||
ls | out-string -stream | sls "\.txt" | |||
</kode> | |||
* [https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/findstr findstr] | |||
== which == | |||
<kode lang='powershell'> | |||
(Get-Command notepad).Source | |||
# C:\WINDOWS\system32\notepad.exe | |||
function which($name) { | |||
Get-Command $name | Select-Object -ExpandProperty Definition | |||
} | |||
</kode> |
Dernière version du 27 janvier 2023 à 10:23
Links
Script template
À 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ées Set-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' |
Astuces
# 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-Only sp 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 |
Variables
Pas de - dans les noms des variables. |
$my_var = "value" |
Environment Variables
# list all environment variables dir env: # create an env variable. scopes are process, user, machine [System.Environment]::SetEnvironmentVariable('MyVar','value', 'user') [System.Environment]::SetEnvironmentVariable('MyVar','value', 'machine') |
$env:userprofile | C:\Users\<user> |
$env:appdata | C:\Users\<user>\AppData\Roaming |
$env:ProgramFiles | C:\Program Files |
[environment]::getfolderpath("mydocuments") | C:\Users\<user>\Documents |
Automatic Variables
$_ | the current object in the pipeline |
$home | C:\Users\<user> |
$Pwd | full path of the current directory |
$PSCommandPath | path of the script file that is being executed |
$PSScriptRoot | path of the script directory that is being executed |
echo, Write-Host
echo 'my text' # saut de ligne echo line1 line2 echo line1`nline2 echo line1([system.environment]::newline)line2 # colors Write-Host -foregroundcolor green -backgroundcolor black Mon Message # erreur Write-Error "Error!" |
Black | Blue | Cyan | DarkBlue |
DarkCyan | DarkGray | DarkGreen | DarkMagenta |
DarkRed | DarkYellow | Gray | Green |
Magenta | Red | White | Yellow |
echo is an alias of Write-Output |
PSWriteColor
# 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 continue Write-Host -NoNewLine 'Press any key to continue...'; $null = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown'); |
GridView
# afficher une fenêtre avec une grille New-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ée Get-Service | Where Status -eq Stopped | Out-GridView -PassThru | Start-Service |
Types
String
echo "Escape `"double-quotes`" `$1" # "double-quotes" $1 echo "Retour à la ligne `r`n" # concaténation de string echo '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 empty if (!$MyString) # null or empty |
Date
Get-Date -Format 'yyyy-MM' # 2020-01 |
Tableau / array
$myArray = @() # empty $myArray = 1, 2, 3 # 1 2 3 $myArray += 4 # 1 2 3 4 $myArray.Length # 4 $myArray[1..2] # 2 3 sub array from index 1 to index 2 $myArray[-1] # 4 latest value of the array $myArray -ne 2 # 1 3 4 $myArray -gt 2 # 3 4 [array]::Reverse($myArray) # 4 3 2 1 $one, $two, $rest = $myArray # $one = 1, $two = 2, $rest = 3, 4 |
Hash table
$myHashTable = @{} # empty $myHashTable = @{ Key1 = 'Value1' } $myHashTable = [ordered]@{ Key1 = 'Value1' } # add key and update value $myHashTable.Key1 = "Value1" $myHashTable["Key2"] = "Value2" echo $myHashTable # Name Value # ---- ----- # Key1 Value1 # Key2 Value2 $myValue = $myHashTable.Key1 $myValue = $myHashTable["Key1"] $myValue = $myHashTable.$myKey "All keys: $($myHashTable.keys)" "All values: $($myHashTable.values)" if (!$myHashTable.contains($myKey)) |
PSObject
$obj = New-Object PSObject -Property @{ Prop1 = "Value1" Prop2 = "Value2" } |
if else
$nombre = 10 if ($nombre -eq 10) { "Le nombre est 10." } elseif (($nombre -gt 5) -and ($nombre -lt 10) -or ($nombre -eq 222)) { "Le nombre est entre 5 et 10 ou égal à 222." } elseif (!($nombre -eq 333)) { "Le nombre est différent de 333." } else { "Surement 333" } |
Opérateur | Description | Opérateur | Description |
---|---|---|---|
-eq | == | -ceq | == case senstivie |
-ne | != | ||
-lt | < | -le | <= |
-gt | > | -ge | >= |
-not ! | ! | ||
-and | && | -or | || |
-band | & | -bor | | |
Test string
if ([string]::IsNullOrEmpty($monString)) |
switch
switch ($var) { 'value1' { echo $var } 'value2' { echo $var } default { echo 'unknown value' } } $result = switch ($var) { 'Word1' { 'Value1' } 'Word2' { 'Value2' } default { 'Default Value' } } |
Select
# 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 -first 10 |
Where ?
1..4 | ? {$_ % 2 -eq 0} # 2 4 |
Alias: Where-Object where ? |
ForEach %
1..4 | % { $_ * 2 } # 2 4 6 8 1..4 | % { # opening bracket has to be on the same line as percent sign $_ * 2 } |
Fonctions
function TestName { param( [Parameter(Mandatory=$true, ValueFromPipeline=$true)] [string] $nom ) if ($nom -eq "moi") { return $true } return $false } TestName "moi" # True |
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 set if (!$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 $_ -PathType Leaf })] # run a command to validate the parameter [string] $FilePath, [ValidateSet('jpg', 'png')] # validate against a list and add auto-completion [string] $ImageFileExtension ) |
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 used Param ( [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 used echo $PSCmdlet.ParameterSetName # Env or Srv |
Common parameters
Parameter |
---|
-Debug |
-ErrorAction |
-ErrorVariable |
-OutBuffer |
-OutVariable |
-Verbose |
-WarningAction |
-WarningVariable |
[CmdletBinding()] # add this line at the top of the script file Param () if ($PSBoundParameters['Verbose']) # test if Verbose has been passed as parameter |
Help content
<# .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 -detailed exit } # display the help content MonScript.ps1 -h get-help MonScript.ps1 -detailed man MonScript.ps1 -detailed |
Files and folders
List
# display names only ls C:\Dossier -Name # display fullnames (C:\Dossier\filename.ext) ls C:\Dossier | % FullName # display names without the extension ls C:\Dossier | % BaseName # filter ls C:\Dossier *.txt # exclude *.txt et *.dll ls C:\Dossier -exclude *.txt, *.dll # filter against RegEx (-NotMatch, -NotLike) ls C:\Dossier | ? Name -Match "\.txt$" # RegEx ls C:\Dossier | ? Name -Like "*.txt" # Wildcard Expression # lister toutes les DLL et EXE avec leurs versions ls *.dll,*.exe | % { "{0}`t{1}" -f $_.Name, [System.Diagnostics.FileVersionInfo]::GetVersionInfo($_).FileVersion } |
ls dir gci are aliases of Get-ChildItem |
filter et exclude ne fonctionnent pas en même temps. Utiliser * dans le chemin à la place de filter |
-exclude only applies to basenames of items myfile.txt, not the fullname C:\folder\myfile.txt |
sort
# sort by name ls C:\Dossier | sort # sort by LastWriteTime, last modified first ls C:\Dossier | sort -property LastWriteTime -Descending |
Search by name
# look recursively for all the *.txt files ls -r -ErrorAction SilentlyContinue "*.txt" |
Search by file content
# look recursively for files which contains xxx ls -r C:\Dossier | sls "xxx" | group path | % name # display all the occurences of xxx with 2 lines before and after ls -r C:\Dossier | sls "xxx" -context 2 # use quiet to return a boolean '123' | sls -quiet '2' # True |
sls is an alias of Select-String |
context ne semble plus fonctionner |
Read / Get content
# 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 realtime Get-Content .\file.txt -Wait -Tail 1 |
Write / Set content
Set-Content -Encoding UTF8 -Path .\file.txt -Value 'Text' |
Default | UTF-8 without BOM |
UTF8 | UTF-8 with BOM (BOM for UTF-8 files is not recommended) |
Replace content
The default encoding is UTF-8 without BOM |
(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 # to preserve the whitespaces $xml_content = [xml]::new() $xml_content .PreserveWhitespace = $true $xml_content .Load($path) # get node content select-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) |
Delete files based on pattern
# delete all the *.txt files ls *.txt | Remove-Item |
Put to the recycle bin
# in admin console Install-Module -Name Recycle Remove-ItemSafely [FileName|FolderName] # alias New-Alias trash 'Remove-ItemSafely' |
Créer / supprimer un dossier
# suppression d'un dossier et de son contenu rm -r -fo C:\Dossier # -r / -recurse # -fo / -force # -ErrorAction Continue # test before delete to avoid error if (test-path C:\Dossier) { rm -r C:\Dossier } # | Out-Null permet de masquer la sortie ni 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 |
Path
# dossier1\dossier2 join-path dossier1 dossier2 join-path -path dossier1 -childpath dossier2 join-path -path dossier1\ -childpath \dossier2\ join-path -path dossier1 -childpath (join-path -path dossier2 -childpath dossier3) # dossier1\dossier2\dossier3 # utilisation du Framework .NET [System.IO.Path]::Combine("C:\Dossier1", "Dossier2", "Dossier3") # C:\Dossier1\Dossier2\Dossier3 # test si le chemin c:\dossier existe if (Test-Path C:\Dossier -PathType Container) { } # test si le fichier c:\dossier\file.txt existe if (Test-Path C:\Dossier\file.txt -PathType Leaf) { } |
Copy-Item
# copie de Fichier.txt dans Dossier2 sous le nom de Fichier2.txt # dans ce cas Dossier2 n'est pas créé s'il n'existe pas cp 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 exclusivement cp C:\Dossier C:\Dossier2 -recurse -filter *.txt # copie tous les *.txt en excluant les *.bak.txt cp 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-Item copy cp cpi |
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 folder Start-Transcript -path $PSCommandPath.replace('.ps1', '.log') |
Échapper les caractères spéciaux
echo '$dollar' # $dollar echo `$dollar # $dollar |
Encoding
Si la sortie affiche des caractères inattendus, utiliser l'encodage UTF-8 avec BOM.
Expressions rationnelles
Shutdown - Restart
Stop-Computer Restart-Computer |
SQL server
$SqlConn = New-Object System.Data.SqlClient.SqlConnection $SqlConn.ConnectionString = "Server=XXX\YYY;Database=ZZZ;User Id=UUU;Password=PPP;" $SqlConn.Open() $SqlCmd = $SqlConn.CreateCommand() $SqlCmd.CommandText = "SELECT name, database_id FROM sys.databases" $SqlAdapter = New-Object System.Data.SqlClient.SqlDataAdapter $SqlAdapter.SelectCommand = $SqlCmd $DataSet = New-Object System.Data.DataSet $SqlAdapter.Fill($DataSet) $DataSet.Tables[0] #$DataSet.Tables[0] | out-file "C:\Folder\result.csv" |
Active Directory
Import-Module activedirectory Get-ADUser -filter * |
Process
# list processes by name ps | ? name -eq 'firefox' Get-Process | ? { $_.ProcessName -like "*git*" } # list processes by path ps | ? Path -match 'firefox.exe$' # list processes which use a port Get-Process -Id (Get-NetTCPConnection -LocalPort 135).OwningProcess # test is a process is running $firefox = Get-Process firefox -ErrorAction SilentlyContinue if ($firefox) { echo 'firefox is running' } # open a new powershell console start-process powershell -ArgumentList "-NoProfile -NoExit -Command echo $var" |
Services
# affiche l'état d'un service get-service 'SQLBrowser' # Stopped / Running $ServiceName = 'MSSQL$SQLEXPRESS' if ((get-service $ServiceName).Status -eq 'Stopped') { # démarrer un service, nécessite les droits administrateur start-service $ServiceName -PassThru # PassThru force l'affichage d'un message de sortie } else { echo "$ServiceName est déjà démarré." } |
Users
# list connected users query user /server:$SERVER |
MessageBox
[void][Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") [void][System.Windows.Forms.MessageBox]::Show("Hello !") |
Web
wget et iwr sont des alias de Invoke-WebRequest |
# get the content and detect the output format: XML or JSON Invoke-RestMethod http://www.domain.net/api/values | % { $_ | select Prop1, Prop2 | Out-GridView } Invoke-RestMethod http://localhost:111/api/values -Method POST -Body @{value='2'} Invoke-WebRequest http://localhost:111/api/values -H @{"accept"="application/xml"} | Select-Object -Expand Content $content = (New-Object Net.WebClient).DownloadString("http://www.google.fr") wget http://www.domain.net/file.txt -outfile folder\file.txt |
Target HTML
$url = "http://www.domain.net" $result = Invoke-WebRequest $url $result.AllElements | Where Class -eq "some css class" | Select -First 1 -ExpandProperty innerText |
Registre
$RegKey ="HKCU:\Control Panel\Cursors" # Obtenir la valeur de la clé IBeam Get-ItemProperty -Path "HKCU:\Control Panel\Cursors" | select -ExpandProperty IBeam # Changement de la valeur de la clé IBeam Set-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 assembly Add-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
Function rg { param( [Parameter(Mandatory=$true, ValueFromPipeline=$true)] [string] $pattern ) ls -r | sls $pattern -context 2 | foreach { "{0} : {1:00}" -f $_.Path, $_.LineNumber if ($_.Context.PreContext) {" {0}" -f $_.Context.PreContext } "> {0}" -f $_.Line if ($_.Context.PostContext) { " {0}" -f $_.Context.PostContext } "" } } |
Stocker et récupérer un mot de passe
# store password $Password = "Password123!@#" $SecurePassword = $Password | ConvertTo-SecureString -AsPlainText -Force # SecureString # ou demande du password $SecurePassword = Read-Host -Prompt "Enter password" -AsSecureString # ou demande du password avec Get-Credential $Credential = Get-Credential -Message "Enter password" -Username "-" $SecurePassword = $Credential.Password $SecureStringAsPlainText = $SecurePassword | ConvertFrom-SecureString # String Set-Content "C:\Dossier\Password.txt" $SecureStringAsPlainText # get the password $SecureStringAsPlainText = Get-Content "C:\Dossier\Password.txt" # String $SecurePassword = $SecureStringAsPlainText | ConvertTo-SecureString # SecureString $Credential = New-Object PSCredential "user",$SecurePassword $PlainPassword = $Credential.GetNetworkCredential().Password # password en clair |
Modifier le pointeur de la sourie
# changement du pointeur Text Selection $RegKey ="HKCU:\Control Panel\Cursors" Set-ItemProperty -Path $RegKey -Name IBeam -Value "%SystemRoot%\cursors\beam_r.cur" # Rafraichissement des curseurs pour prendre en compte le changement $CSharpSig = @' [DllImport("user32.dll", EntryPoint = "SystemParametersInfo")] public static extern bool SystemParametersInfo( uint uiAction, uint uiParam, uint pvParam, uint fWinIni); '@ $CursorRefresh = Add-Type -MemberDefinition $CSharpSig -Name WinAPICall -Namespace SystemParamInfo –PassThru $CursorRefresh::SystemParametersInfo(0x0057,0,$null,0) |
SHA1
function sha1 { param( [Parameter(Mandatory=$true, ValueFromPipeline=$true)] [string] $file ) (Get-FileHash -Algorithm SHA1 "$file")."Hash" } |
Windows API
Set Wallpaper
# C# wrapper around Windows API SystemParametersInfo Add-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') |
Équivalents bash
- Bash tools for Windows
find
# find . -type f -iname "filename" Get-ChildItem -Filter "*filename*" -Recurse -File ls -r -file *filename* |
sed
File encoding is changed to UTF-8 without BOM |
# sed 's/txt_to_replace/replacement_text/' -i file.txt (Get-Content file.txt) -replace 'txt_to_replace', 'replacement_text' | Set-Content file.txt (Get-Content file.txt) -replace '^(group1).*(group2)$', '$1 text $2' | Set-Content file.txt |
grep
# ls | grep *.txt ls | % 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 recherche ls | out-string -stream | sls "\.txt" |
which
(Get-Command notepad).Source # C:\WINDOWS\system32\notepad.exe function which($name) { Get-Command $name | Select-Object -ExpandProperty Definition } |