PowerShell
PowerShell on aime ou on aime pas (moi j'aime pas) mais quoi qu'il en soit il faut l'utiliser si on a un PC sous Windows. Donc voila une page dans ce but.
Introduction à PowerShell
Contrairement aux shells Unix traditionnels (Bash, Korn Shell, Zsh, etc.), PowerShell n'a pas été conçu comme un interpréteur de commandes manipulant principalement du texte.
La philosophie de PowerShell repose sur une idée simple :
Tout est objet.
Lorsqu'une commande produit un résultat, elle ne renvoie généralement pas du texte mais des objets .NET contenant des propriétés et des méthodes.
Par exemple, sous Linux :
ps -ef | grep python
Les différentes commandes échangent des lignes de texte qu'il faut ensuite analyser.
Sous PowerShell :
Get-Process |
Where-Object ProcessName -eq "python"
Les commandes manipulent directement des objets représentant des processus. Il n'est donc pas nécessaire d'extraire ou de parser du texte.
Les cmdlets
Les commandes PowerShell sont appelées cmdlets (prononcer "command lets").
Elles suivent généralement la convention :
Verbe-Nom
Exemples :
Get-Process
Get-Service
Get-ChildItem
Start-Process
Stop-Service
New-Item
Remove-Item
Cette convention permet de deviner facilement le rôle d'une commande.
Par exemple :
Get-Command *Process*
affichera les commandes permettant de manipuler des processus.
Le pipeline d'objets
Le caractère | conserve le même rôle général que sous Unix : transmettre le résultat d'une commande à la suivante.
Cependant, la nature des données transmises est différente.
Sous Linux :
ps -ef | grep chrome
Le pipeline transporte du texte.
Sous PowerShell :
= Alias, fonctions et profil utilisateur =
== Introduction ==
PowerShell dispose d'un mécanisme similaire aux fichiers ''~/.profile'', ''~/.bash_profile'' ou ''~/.bashrc'' sous Linux.
Le profil PowerShell permet de définir automatiquement :
* des alias ;
* des fonctions ;
* des variables d'environnement ;
* des personnalisations du terminal.
Le script est exécuté à chaque ouverture d'une session PowerShell.
== Le fichier de profil PowerShell ==
Le chemin du profil courant est stocké dans la variable :
<syntaxhighlight lang="powershell">
$PROFILE
Exemple :
C:\Users\jp38c44n\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1
Afficher le chemin :
$PROFILE
Vérifier si le profil existe :
Test-Path $PROFILE
Créer le répertoire et le fichier si nécessaire :
mkdir (Split-Path $PROFILE) -Force
notepad $PROFILE
Recharger le profil sans fermer le terminal :
. $PROFILE
Correspondance avec Linux
| Linux | PowerShell |
|---|---|
| ~/.bashrc | Microsoft.PowerShell_profile.ps1 |
| alias ll='ls -la' | function ll { Get-ChildItem -Force } |
| export VAR=valeur | $env:VAR = "valeur" |
| source ~/.bashrc | . $PROFILE |
Créer un alias simple
Alias temporaire pour la session courante :
Set-Alias vi vim
Afficher tous les alias :
Get-Alias
Afficher un alias particulier :
Get-Alias vi
Limitation des alias
Un alias ne peut pointer que vers une seule commande.
Ceci fonctionne :
Set-Alias ll Get-ChildItem
Ceci ne fonctionne pas :
Set-Alias gm '$env:NODE_USE_SYSTEM_CA = 1; gemini'
Pour exécuter plusieurs instructions, il faut utiliser une fonction.
Créer une fonction
Exemple :
function ll {
Get-ChildItem -Force
}
Fonction acceptant des arguments :
function grep {
Select-String @args
}
Utilisation :
grep erreur fichier.log
Exemples
Lancer Gemini avec NODE_USE_SYSTEM_CA
C'est utile pour les entreprises qui utilisent un proxy interne pour l'utilisation de Google Gemini code assis CLI par exemple.
Dans le profil :
function sgm {
$env:NODE_USE_SYSTEM_CA = 1
gemini @args
}
Utilisation :
sgm
ou :
sgm "Explique les alias PowerShell"
Script automatique pour gérer un mini écran.
J'ai acheté un mini écran HDMI pour avoir une console d'urgence pour mes Raspberry PI. Mais, entre deux urgences je l'utilise comme second ou troisième écran sur mon laptop.
Je l'utilise souvent pour afficher une page de liens et qui donne l'heure. Mais c'est fastidieux de lancer chrome à chaque coup de le déplacer dans l'écran en question...
Je me suis dit qu'un script powerShell serait idéal. Plusieurs questions :
- Comment l'écrire alors que je ne suis pas expert en PowerShell (énumérer les écrans, détecter celui qui fait 600x1024 etc.)
- Comment le lancer automatiquement le script (y'a plus d'
autoexec.batet cela me surprendrais que ce soit un .profile dans$HOME)
Alors j'ai demandé a mon ami Copilot qui sait tout.
Lancer un script automatiquement
Non il n'y a plus de autoexec.bat sous Windows depuis... très longtemps. Il y a une variable d'environnement : shell:startup
Soit on tape shell:startup dans la barre d'adresse du l'explorer, soit on lance la commande PowerShell:
explorer.exe shell:startup
dans les deux cas ca ouvre l'explorateur à l'endroit ou on doit mettre les trucs a lancer au démarrage.
Moi ca me donne un truc du genre:
C:\Users\<<USER>>\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup
On est chez Microsoft pourquoi faire simple?
On pourrait se dire : "zou je balance mon script .ps1 dans ce répertoire et roule!". Et bien NON! L'action par défaut sous Windows pour les fichiers .ps1 c'est... Notepad!
Donc si on pose le script .ps1 dans shell:startup, et bien au login ça... ouvre le fichier dans notepad. Il faut, soit changer le programme par défaut des .ps1 soit créer un moche raccourci soit faire un script "cmd" qui lui même appelle le .ps1.
Je sais pas laquelle est la plus crade; mais j'ai choisit la dernière solution.
Je crée seulement un script cmd pour lancer le script ps1 qui lui même va lancer chrome!
Le script pour lancer le script :
@echo off
powershell.exe -ExecutionPolicy Bypass -WindowStyle Hidden -File "C:\Users\<<MONREP>>\screen-auto.ps1"
Le @echo off on connait c'est vieux comme MSDOS 2.0 (peut être 1.0 j'ai jamais connu).
Les options de powershell.exe
-ExecutionPolicy Bypass
Définit temporairement la politique d'exécution pour cette instance PowerShell uniquement.
Sans cette option, ton script peut être bloqué par la politique de sécurité de la machine.
Les valeurs les plus courantes sont :
| Valeur | Signification |
|---|---|
| Restricted | Aucun script autorisé |
| RemoteSigned | Les scripts téléchargés doivent être signés |
| Unrestricted | Tout autorisé avec avertissement |
| Bypass | Tout autorisé, aucun avertissement |
Avec :
PowerShell
-ExecutionPolicy Bypass
PowerShell exécute le script sans poser de question, même si la politique normale de la machine est restrictive.
C'est très courant pour les scripts lancés automatiquement au démarrage.
-WindowStyle Hidden
Demande à PowerShell de masquer sa propre fenêtre.
Sans cette option : On verras une fenêtre noire apparaître quelques instants et c'est très moche...
Avec : PowerShell -WindowStyle Hidden
le script s'exécute en arrière-plan sans fenêtre visible.
Pratique pour :
- scripts de démarrage
- automatisations
À noter que cela ne masque pas les programmes lancés par le script. Si le script ouvre Chrome, Chrome sera visible.
-File
Indique à PowerShell que ce qui suit est un fichier .ps1 à exécuter.
Exemple :
PowerShell
-File "C:\Users\<<MONREP>>\screen-auto.ps1"
PowerShell charge et exécute ce fichier.
Sans -File, PowerShell interprète les arguments différemment.
Bon maintenant qu'on a fait le script pour lancer le script, on va écrire le script pour lancer chrome.
Lancer Crome, sur le bon écran en plein écran.
Le script que Copilot m'a mitonné:
Add-Type -AssemblyName System.Windows.Forms
# Recherche de l'écran portrait 600x1024
$targetScreen = [System.Windows.Forms.Screen]::AllScreens |
Where-Object {
($_.Bounds.Width -eq 600 -and $_.Bounds.Height -eq 1024) -or
($_.Bounds.Width -eq 1024 -and $_.Bounds.Height -eq 600)
} |
Select-Object -First 1
if (-not $targetScreen) {
Write-Host "Petit écran non détecté."
exit
}
$url = "https://scratch.pinon-hebert.fr/"
$chrome = Start-Process `
chrome.exe `
-ArgumentList `
"--user-data-dir=$env:TEMP\ChromeDashboard", `
"--new-window", `
"--kiosk", `
$url `
-PassThru
Start-Sleep -Seconds 5
$hwnd = $null
for ($i = 0; $i -lt 20; $i++) {
$proc = Get-Process chrome |
Where-Object MainWindowHandle -ne 0 |
Select-Object -First 1
if ($proc) {
$hwnd = $proc.MainWindowHandle
break
}
Start-Sleep -Milliseconds 500
}
if (-not $hwnd) {
exit
}
Add-Type @"
using System;
using System.Runtime.InteropServices;
public class Win32 {
[DllImport("user32.dll")]
public static extern bool MoveWindow(
IntPtr hWnd,
int X,
int Y,
int nWidth,
int nHeight,
bool bRepaint
);
[DllImport("user32.dll")]
public static extern bool ShowWindow(
IntPtr hWnd,
int nCmdShow
);
}
"@
$x = $targetScreen.Bounds.X
$y = $targetScreen.Bounds.Y
$w = $targetScreen.Bounds.Width
$h = $targetScreen.Bounds.Height
[Win32]::MoveWindow($hwnd, $x, $y, $w, $h, $true)
# Maximiser
[Win32]::ShowWindow($hwnd, 3)
Toute une partie de la ruse est dans les options de chrome (c'est pas du PowerShell là) :
chrome.exe `
-ArgumentList `
"--user-data-dir=$env:TEMP\ChromeDashboard", `
"--new-window", `
"--kiosk", `
$url `
Les arguments sont :
--user-data-dir=$env:TEMP\ChromeDashboardpour faire démarrer une session séparée--new-windowcomme son nom l'indique c'est pour ouvrir la page dans une nouvelle fenêtre sinon ca va faire un onglet dans un chrome partagé--kioskc'est pour l'ouvrir en mode kiosque. Envoyer un F11 pour l'avoir en plein écran était possible mais super lourd. (et je suis pas une bête en powerShell)$url... c'est l'URL à ouvrit
Voila un bien joli script!