Déployer des réseaux Wi-Fi sur vos postes en mode D OS
Vos utilisateurs doivent pouvoir se connecter au Wi-Fi dès l'allumage du poste, sans saisir de mot de passe et sans intervention de votre support. Cette page explique comment intégrer vos réseaux Wi-Fi à votre poste master, pour que tous les postes déployés en mode D OS en bénéficient automatiquement.
Compatibilité : D OS ✅
Temps estimé : 30 minutes, hors création de version.
Ce que vous allez obtenir
À la fin de cette procédure :
- vos réseaux Wi-Fi sont configurés sur tous les postes issus de votre master ;
- la connexion est disponible dès l'écran d'ouverture de session, pour tous les utilisateurs ;
- vous pouvez déclarer plusieurs réseaux, dans l'ordre de préférence de votre choix ;
- chaque démarrage laisse une trace consultable en cas de problème.
Exemple concret
Un établissement dispose d'un réseau principalEtab-Pedagoet d'un réseau de secoursEtab-Secoursdans un bâtiment annexe. Avec cette procédure, chaque poste connaît les deux réseaux, se connecte en priorité àEtab-Pedago, et bascule automatiquement surEtab-Secourslorsqu'il est dans l'annexe.
Les scripts fournis
| Script | Rôle | Où l'utiliser |
|---|---|---|
setWifi_v2.ps1 | Installe vos réseaux Wi-Fi à chaque démarrage | Sur le poste master, en script de démarrage |
Verifier-SetWifi.ps1 | Contrôle l'installation : script, encodage, droits, profils, journal | Sur le master puis sur le poste de validation, à la demande |
Le contenu complet des deux scripts est disponible en annexe, à la fin de cette page.
Comment ça marche
Le principe tient en trois étapes :
- Vous déclarez vos réseaux dans un script, SetWifi.
- Ce script est placé sur votre poste master et s'exécute à chaque démarrage de la machine.
- Les postes déployés à partir de ce master héritent du script : ils installent vos réseaux Wi-Fi à chaque démarrage.
Le script s'exécute avant l'ouverture de session, sans aucune action de l'utilisateur. S'il rencontre un problème avec un réseau, il le signale et passe au suivant : un réseau mal renseigné ne bloque ni les autres réseaux, ni le démarrage du poste.
Prérequis
Avant de commencer, vérifiez que vous disposez de :
- les scripts
setWifi_v2.ps1etVerifier-SetWifi.ps1, fournis en annexe de cette page ; - un accès administrateur à votre poste master ;
- pour chaque réseau : son nom exact (SSID), sa clé et son type de sécurité (WPA2 ou WPA3) ;
- un poste de validation équipé d'une carte Wi-Fi, à portée des réseaux concernés.
💡 Où trouver le type de sécurité ?
Il est indiqué dans la configuration de votre borne ou de votre contrôleur Wi-Fi. En cas de doute, choisissez WPA2 : c'est le type le plus répandu.
Étape 1 — Renseigner vos réseaux
Récupérez le script depuis l'annexe :
- Rendez-vous à la section Script 1 — setWifi_v2.ps1.
- Copiez l'intégralité du bloc de code (bouton de copie en haut à droite du bloc, ou sélection complète).
- Collez-le dans un éditeur de texte (Bloc-notes ou Visual Studio Code).
- Enregistrez le fichier sous le nom
setWifi_v2.ps1, en respectant l'encodage indiqué plus bas.
En haut du fichier, repérez le bloc $WifiNetworks et remplacez les lignes d'exemple par vos réseaux, une ligne par réseau :
$WifiNetworks = @(
@{ SSID = 'Etab-Pedago'; Password = 'VotreCle1' }
@{ SSID = 'Etab-Secours'; Password = 'VotreCle2' }
)Dans la plupart des cas, le nom et la clé suffisent. Pour les situations particulières, ajoutez les options suivantes :
| Besoin | Option à ajouter | Exemple |
|---|---|---|
| Réseau en WPA3 | Authentication = 'WPA3SAE' | @{ SSID = 'Etab-WPA3'; Password = 'VotreCle'; Authentication = 'WPA3SAE' } |
| Réseau masqué (nom non diffusé) | Hidden = $true | @{ SSID = 'Labo'; Password = 'VotreCle'; Hidden = $true } |
| Connexion manuelle uniquement | AutoConnect = $false | @{ SSID = 'Invites'; Password = 'VotreCle'; AutoConnect = $false } |
| Réseau ouvert, sans clé | Authentication = 'open' | @{ SSID = 'Invites'; Authentication = 'open'; AutoConnect = $false } |
📌 L'ordre compte
Le premier réseau de la liste est celui auquel le poste se connecte en priorité lorsque plusieurs sont disponibles. Placez votre réseau principal en premier.
📌 Règles à respecter
- Le SSID doit être écrit exactement comme il apparaît sur le réseau, majuscules comprises.
- La clé doit compter entre 8 et 63 caractères, sans accent.
- Conservez les apostrophes
'autour des valeurs.
Enregistrez le fichier en « UTF-8 avec BOM ».
- Dans le Bloc-notes : Fichier › Enregistrer sous, puis choisissez l'encodage UTF-8 avec BOM.
- Dans Visual Studio Code : cliquez sur l'encodage en bas à droite, puis Enregistrer avec l'encodage › UTF-8 with BOM.
⚠️ Pourquoi c'est important
Sans cet encodage, les noms de réseaux contenant des accents (par exempleMédiathèque) ne sont pas reconnus, sans qu'aucune erreur ne s'affiche.
Étape 2 — Installer le script sur le poste master
Sur votre poste master, avec un compte administrateur :
- Appuyez sur Windows + R, tapez
gpedit.mscet validez. - Dans l'arborescence, ouvrez Configuration ordinateur › Paramètres Windows › Scripts (démarrage/arrêt).
- Double-cliquez sur Démarrage, puis ouvrez l'onglet Scripts PowerShell.
- Cliquez sur Afficher les fichiers… : un dossier s'ouvre.
- Copiez
setWifi_v2.ps1dans ce dossier, puis fermez-le. - Revenez à la fenêtre Démarrage, cliquez sur Ajouter…, sélectionnez
setWifi_v2.ps1et validez par OK. - Cliquez sur Appliquer, puis OK.
💡 Bien choisir la section
Le script doit être déclaré dans Configuration ordinateur et non dans Configuration utilisateur. C'est ce qui lui permet de s'exécuter avant toute ouverture de session.
Étape 3 — Protéger vos clés Wi-Fi
Le script contient vos clés Wi-Fi en clair. Par défaut, le dossier dans lequel vous l'avez copié est lisible par tous les utilisateurs du poste. Cette étape réserve sa lecture aux administrateurs.
Elle est indispensable : ne la sautez pas.
- Faites un clic droit sur le menu Démarrer et ouvrez Terminal (administrateur) ou Windows PowerShell (administrateur).
- Copiez la commande suivante, collez-la et validez :
icacls "C:\Windows\System32\GroupPolicy\Machine\Scripts\Startup\setWifi_v2.ps1" /inheritance:r /grant:r *S-1-5-18:F *S-1-5-32-544:F
- Vérifiez le résultat avec :
icacls "C:\Windows\System32\GroupPolicy\Machine\Scripts\Startup\setWifi_v2.ps1"
Seuls AUTORITE NT\Système et BUILTIN\Administrateurs doivent apparaître.
💡 Bon à savoir
La commande fonctionne quelle que soit la langue de Windows : les comptes y sont désignés par leur identifiant système plutôt que par leur nom.
Étape 4 — Vérifier sur le poste master
Redémarrez le poste master, puis ouvrez une session.
Vos réseaux sont-ils installés ? Dans un terminal, tapez :
netsh wlan show profiles
Vos réseaux doivent apparaître dans la rubrique Profils Tous les utilisateurs.
Le script s'est-il bien déroulé ? Ouvrez le journal :
notepad C:\Windows\Logs\SetWifi\SetWifi.log
La dernière ligne indique le bilan du démarrage, par exemple :
[INFO ] Bilan : 2 profil(s) importé(s), 0 échec(s) sur 2 réseau(x) configuré(s).
Si un réseau est en échec, la raison est indiquée quelques lignes plus haut. Consultez la section En cas de problème.
Pour tout vérifier d'un coup, utilisez le script de contrôle Verifier-SetWifi.ps1 :
- Enregistrez-le sur le poste (par exemple dans
C:\Temp), en UTF-8 avec BOM. - Dans un terminal ouvert en tant qu'administrateur, lancez :
powershell.exe -NoProfile -ExecutionPolicy Bypass -File "C:\Temp\Verifier-SetWifi.ps1"
Le script affiche un résultat [OK] ou [KO] pour chaque point : présence et encodage du script, lignes d'exemple restantes, protection des droits, profils installés, dernier bilan et derniers événements. Il ne modifie rien sur le poste.
💡 Conseil
Ce script de contrôle n'a pas besoin de rester sur le master : supprimez-le après usage pour ne pas l'intégrer à votre version.
Étape 5 — Valider puis déployer
Suivez votre processus habituel de création de version :
- Créez une nouvelle version à partir de votre poste master.
- Déployez-la sur votre poste de validation.
- Redémarrez le poste de validation et vérifiez :
- que le poste se connecte au Wi-Fi avant l'ouverture de session ;
- que le réseau prioritaire est bien celui choisi en premier ;
- que le journal se termine par 0 échec(s).
- Une fois la validation concluante, déployez la version sur votre parc.
💡 Conseil
Testez la connexion en débranchant le câble réseau du poste de validation : vous êtes ainsi certain que c'est bien le Wi-Fi qui est utilisé.
Faire évoluer vos réseaux
| Vous souhaitez… | Ce qu'il faut faire |
|---|---|
| Ajouter un réseau | Ajoutez une ligne dans $WifiNetworks sur le master, réenregistrez en UTF-8 avec BOM, puis créez et déployez une nouvelle version. |
| Changer une clé | Modifiez la clé sur votre borne et dans le script du master, puis créez et déployez une nouvelle version. |
| Changer l'ordre de priorité | Réordonnez les lignes dans $WifiNetworks, puis créez et déployez une nouvelle version. |
| Retirer un réseau | Supprimez sa ligne dans le script. Le retrait de la liste ne supprime pas le profil déjà installé sur les postes : contactez votre interlocuteur Wisper pour organiser sa suppression. |
⚠️ Après chaque modification
Vérifiez que les droits de l'étape 3 sont toujours en place. Si vous avez remplacé le fichier par une nouvelle copie, appliquez de nouveau la commandeicacls.
Suivre vos postes
À chaque démarrage, le script laisse une trace à deux endroits.
Le fichier journal : C:\Windows\Logs\SetWifi\SetWifi.log. Il détaille chaque réseau traité. Les clés Wi-Fi n'y sont jamais écrites.
L'Observateur d'événements Windows : journal Application, source SetWifi.
| Identifiant | Signification |
|---|---|
| 1000 | Tout s'est bien passé |
| 1001 | Avertissement : au moins un réseau n'a pas pu être installé |
| 1002 | Erreur : détail du problème rencontré |
💡 Pour un grand parc
Si vous disposez d'un outil de supervision qui collecte les événements Windows, filtrez sur la source SetWifi et les identifiants 1001 et 1002 : vous repérez immédiatement les postes concernés, sans avoir à vous y connecter.
Sécurité : les bonnes pratiques
Ce que le script fait pour vous :
- il ne laisse jamais vos clés sur le disque en dehors du script lui-même ;
- il n'écrit jamais vos clés dans les journaux ;
- il refuse les réseaux mal renseignés plutôt que de créer une configuration incorrecte.
Ce qui relève de votre responsabilité :
- Protéger le script : appliquez systématiquement l'étape 3.
- Considérer votre master comme sensible : il contient vos clés Wi-Fi, au même titre que vos versions.
- Changer vos clés régulièrement, et immédiatement en cas de perte ou de vol d'un poste.
- Isoler les réseaux invités de votre réseau interne et les configurer en connexion manuelle (
AutoConnect = $false).
ℹ️ À savoir
Avec une clé Wi-Fi partagée (WPA2 ou WPA3 « Personnel »), la clé doit être présente sur le poste pour qu'il se connecte. Un administrateur du poste peut donc toujours la retrouver. Pour les réseaux sensibles, une authentification WPA2/WPA3-Entreprise par certificat supprime toute clé partagée. Votre interlocuteur Wisper peut vous accompagner dans cette réflexion.
En cas de problème
| Ce que vous constatez | Cause probable | Que faire |
|---|---|---|
| Aucun fichier journal | Le script ne s'exécute pas | Vérifiez qu'il est déclaré dans Configuration ordinateur › … › Démarrage, onglet Scripts PowerShell (étape 2). |
| « Droits administrateur requis » | Script déclaré dans Configuration utilisateur | Déclarez-le dans Configuration ordinateur. |
| « Aucune carte Wi-Fi active détectée » | Carte absente, désactivée ou pilote manquant | Vérifiez la carte dans le Gestionnaire de périphériques. Sur un poste fixe sans Wi-Fi, ce message est normal. |
| « Clé invalide » | Clé trop courte, trop longue ou avec accents | Vérifiez la clé : 8 à 63 caractères, sans accent. |
| « SSID non renseigné » | Une ligne d'exemple est restée dans la liste | Remplacez ou supprimez les lignes contenant A_REMPLACER. |
| Nom de réseau avec caractères étranges | Fichier non enregistré en UTF-8 avec BOM | Réenregistrez le fichier avec le bon encodage (étape 1). |
| Réseau installé mais pas de connexion | Clé, nom ou type de sécurité différents de la borne | Comparez avec la configuration de la borne, majuscules comprises. |
| Échec uniquement sur un réseau WPA3 | Carte ou pilote non compatible WPA3 | Mettez à jour le pilote, ou utilisez WPA2 pour ce réseau. |
Si le problème persiste, contactez votre interlocuteur Wisper en joignant le fichier C:\Windows\Logs\SetWifi\SetWifi.log du poste concerné.
En résumé
- Renseignez vos réseaux dans
setWifi_v2.ps1et enregistrez en UTF-8 avec BOM. - Déclarez le script en démarrage ordinateur sur votre poste master.
- Protégez le script avec la commande
icacls. - Vérifiez sur le master : profils installés et journal sans échec.
- Validez sur un poste de validation, puis déployez sur votre parc.
Annexe : les scripts
⚠️ Avant d'utiliser ces scripts
- Copiez chaque script en entier, de la première à la dernière ligne.
- Enregistrez-le en UTF-8 avec BOM (voir étape 1).
- Ne publiez jamais une copie de
setWifi_v2.ps1contenant vos clés réelles (ticket, messagerie, partage de fichiers).
Script 1 — setWifi_v2.ps1
Installe vos réseaux Wi-Fi à chaque démarrage du poste. Seul le bloc $WifiNetworks, en haut du script, est à modifier.
\xEF\xBB\xBF<#
.SYNOPSIS
Déploie un ou plusieurs profils Wi-Fi (tous utilisateurs) au démarrage de la machine.
.DESCRIPTION
Prévu pour un script de démarrage GPO (Configuration ordinateur), donc exécuté sous SYSTEM
sans session interactive : aucune pause, aucune saisie, pas d'affichage console.
Journalisation dans C:\Windows\Logs\SetWifi\SetWifi.log (avec rotation) et, pour les
avertissements/erreurs/bilan, dans le journal d'événements "Application" (source SetWifi).
Les réseaux sont déclarés dans $WifiNetworks. L'ordre du tableau définit la priorité
de connexion (le premier est préféré).
Codes de sortie : 0 = tout est OK (ou rien à faire), 1 = au moins un réseau en échec,
2 = erreur bloquante.
.NOTES
Version : 2.0
- Enregistrer ce fichier en UTF-8 AVEC BOM, sinon PowerShell 5.1 corrompt les caractères
accentués des SSID/clés.
- Ce fichier contient des clés Wi-Fi en clair : restreindre ses ACL (SYSTEM + Administrateurs).
#>
#Requires -Version 5.1
[CmdletBinding()]
param()
Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'
# =====================================================================
# CONFIGURATION
# =====================================================================
# SSID : nom du réseau (1 à 32 octets)
# Password : clé WPA (8 à 63 caractères ASCII, ou 64 caractères hexadécimaux)
# Authentication : 'WPA2PSK' | 'WPA3SAE' | 'open' (défaut : WPA2PSK)
# Hidden : $true si le SSID n'est pas diffusé (défaut : $false)
# AutoConnect : $true = automatique, $false = manuelle (défaut : $true)
#
# Exemples :
# @{ SSID = 'Corp-WiFi'; Password = 'MotDePasse1'; Authentication = 'WPA2PSK' }
# @{ SSID = 'Corp-WPA3'; Password = 'MotDePasse2'; Authentication = 'WPA3SAE' }
# @{ SSID = 'Labo-cache'; Password = 'MotDePasse3'; Hidden = $true }
# @{ SSID = 'Invites'; Authentication = 'open'; AutoConnect = $false }
# =====================================================================
$WifiNetworks = @(
@{ SSID = 'A_REMPLACER'; Password = 'A_REMPLACER'; Authentication = 'WPA2PSK'; Hidden = $false; AutoConnect = $true }
@{ SSID = 'A_REMPLACER'; Password = 'A_REMPLACER'; Authentication = 'WPA2PSK'; Hidden = $false; AutoConnect = $true }
)
$AppName = 'SetWifi'
$AppVersion = '2.0'
$LogDir = Join-Path $env:SystemRoot "Logs\$AppName"
$LogFile = Join-Path $LogDir "$AppName.log"
$MaxLogSizeKB = 1024 # au-delà, le log courant est renommé en .old
$WlanWaitSec = 60 # attente max du service WLAN au démarrage
$EventSource = $AppName
$script:EventLogReady = $false
$script:ExitCode = 0
# =====================================================================
# JOURNALISATION
# =====================================================================
function Initialize-Log {
if (-not (Test-Path -LiteralPath $LogDir)) {
New-Item -ItemType Directory -Path $LogDir -Force | Out-Null
}
if ((Test-Path -LiteralPath $LogFile) -and ((Get-Item -LiteralPath $LogFile).Length / 1KB -gt $MaxLogSizeKB)) {
Move-Item -LiteralPath $LogFile -Destination "$LogFile.old" -Force
}
try {
if (-not [System.Diagnostics.EventLog]::SourceExists($EventSource)) {
New-EventLog -LogName Application -Source $EventSource
}
$script:EventLogReady = $true
}
catch {
$script:EventLogReady = $false
}
}
function Write-Log {
param(
[ValidateSet('INFO', 'WARN', 'ERROR')]
[string]$Level = 'INFO',
[Parameter(Mandatory)]
[string]$Message,
[switch]$ToEventLog
)
$line = '[{0}] [{1,-5}] {2}' -f (Get-Date -Format 'yyyy-MM-dd HH:mm:ss'), $Level, $Message
try { Add-Content -LiteralPath $LogFile -Value $line -Encoding UTF8 } catch { }
Write-Verbose $line
if ($script:EventLogReady -and ($ToEventLog -or $Level -ne 'INFO')) {
$type = switch ($Level) { 'ERROR' { 'Error' } 'WARN' { 'Warning' } default { 'Information' } }
$id = switch ($Level) { 'ERROR' { 1002 } 'WARN' { 1001 } default { 1000 } }
try { Write-EventLog -LogName Application -Source $EventSource -EventId $id -EntryType $type -Message $Message } catch { }
}
}
# =====================================================================
# OUTILS
# =====================================================================
function Test-IsAdmin {
$id = [Security.Principal.WindowsIdentity]::GetCurrent()
return ([Security.Principal.WindowsPrincipal]$id).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
}
function Invoke-Netsh {
param([Parameter(Mandatory)][string[]]$Arguments)
# En PS 5.1, stderr redirigé + ErrorActionPreference=Stop lève une exception : on l'évite ici.
$ErrorActionPreference = 'Continue'
$output = & netsh.exe @Arguments 2>&1 | Out-String
return [pscustomobject]@{ ExitCode = $LASTEXITCODE; Output = $output.Trim() }
}
function Wait-WlanService {
$svc = Get-Service -Name WlanSvc -ErrorAction SilentlyContinue
if (-not $svc) {
Write-Log INFO 'Service WLAN AutoConfig (WlanSvc) absent : aucune action.'
return $false
}
if ($svc.StartType -eq 'Disabled') {
Write-Log WARN 'Service WlanSvc désactivé : impossible de déployer les profils Wi-Fi.'
return $false
}
if ($svc.Status -ne 'Running') {
Write-Log INFO "Service WlanSvc à l'état '$($svc.Status)', démarrage et attente (max $WlanWaitSec s)..."
try {
if ($svc.Status -eq 'Stopped') { Start-Service -Name WlanSvc }
$svc.WaitForStatus('Running', [TimeSpan]::FromSeconds($WlanWaitSec))
}
catch {
Write-Log ERROR "Le service WlanSvc n'a pas démarré : $($_.Exception.Message)"
return $false
}
}
return $true
}
function Get-WifiAdapters {
# NdisPhysicalMedium 9 = Native 802.11 (indépendant de la langue du système)
return @(Get-NetAdapter -Physical -ErrorAction SilentlyContinue |
Where-Object { $_.NdisPhysicalMedium -eq 9 -and $_.Status -ne 'Disabled' })
}
function Get-NetValue {
param([hashtable]$Net, [string]$Key, $Default)
if ($Net.ContainsKey($Key) -and $null -ne $Net[$Key] -and "$($Net[$Key])" -ne '') { return $Net[$Key] }
return $Default
}
# Retourne $null si la configuration est valide, sinon un message d'erreur.
function Test-WifiConfig {
param([hashtable]$Net)
$ssid = [string](Get-NetValue $Net 'SSID' '')
$auth = [string](Get-NetValue $Net 'Authentication' 'WPA2PSK')
$pass = [string](Get-NetValue $Net 'Password' '')
if ($ssid -eq '') { return 'SSID vide.' }
$ssidBytes = [Text.Encoding]::UTF8.GetByteCount($ssid)
if ($ssidBytes -gt 32) { return "SSID trop long ($ssidBytes octets, maximum 32)." }
if ($ssid -match 'A_REMPLACER|remplacer') { return 'SSID non renseigné (valeur exemple).' }
if ($auth -notin @('WPA2PSK', 'WPA3SAE', 'open')) {
return "Authentification '$auth' non supportée (WPA2PSK, WPA3SAE ou open)."
}
if ($auth -ne 'open') {
if ($pass -match 'A_REMPLACER|remplacer') { return 'Clé non renseignée (valeur exemple).' }
if ($pass -notmatch '^[\x20-\x7E]{8,63}$' -and $pass -notmatch '^[0-9A-Fa-f]{64}$') {
return 'Clé invalide : 8 à 63 caractères ASCII imprimables, ou 64 caractères hexadécimaux.'
}
}
return $null
}
function New-WlanProfileXml {
param([hashtable]$Net)
$ssid = [string](Get-NetValue $Net 'SSID' '')
$auth = [string](Get-NetValue $Net 'Authentication' 'WPA2PSK')
$pass = [string](Get-NetValue $Net 'Password' '')
$hidden = [bool](Get-NetValue $Net 'Hidden' $false)
$autoCon = [bool](Get-NetValue $Net 'AutoConnect' $true)
# Échappement XML (&, <, >, ", ') : un caractère spécial ne casse plus le profil
$ssidXml = [Security.SecurityElement]::Escape($ssid)
# Forme hexadécimale du SSID : fiable même avec accents ou caractères spéciaux
$ssidHex = -join ([Text.Encoding]::UTF8.GetBytes($ssid) | ForEach-Object { $_.ToString('X2') })
$mode = if ($autoCon) { 'auto' } else { 'manual' }
$nonBc = if ($hidden) { 'true' } else { 'false' }
if ($auth -eq 'open') {
$security = @"
<authEncryption>
<authentication>open</authentication>
<encryption>none</encryption>
<useOneX>false</useOneX>
</authEncryption>
"@
}
else {
$keyType = if ($pass -match '^[0-9A-Fa-f]{64}$') { 'networkKey' } else { 'passPhrase' }
$passXml = [Security.SecurityElement]::Escape($pass)
$security = @"
<authEncryption>
<authentication>$auth</authentication>
<encryption>AES</encryption>
<useOneX>false</useOneX>
</authEncryption>
<sharedKey>
<keyType>$keyType</keyType>
<protected>false</protected>
<keyMaterial>$passXml</keyMaterial>
</sharedKey>
"@
}
return @"
<?xml version="1.0" encoding="UTF-8"?>
<WLANProfile xmlns="http://www.microsoft.com/networking/WLAN/profile/v1">
<name>$ssidXml</name>
<SSIDConfig>
<SSID>
<hex>$ssidHex</hex>
<name>$ssidXml</name>
</SSID>
<nonBroadcast>$nonBc</nonBroadcast>
</SSIDConfig>
<connectionType>ESS</connectionType>
<connectionMode>$mode</connectionMode>
<MSM>
<security>
$security
</security>
</MSM>
</WLANProfile>
"@
}
function Add-WifiProfile {
param([hashtable]$Net)
$ssid = [string]$Net.SSID
$xml = New-WlanProfileXml -Net $Net
# Fichier temporaire au nom aléatoire, créé en exclusif (CreateNew) :
# impossible à pré-créer ou à lire par un utilisateur standard, supprimé quoi qu'il arrive.
$tmp = Join-Path $env:SystemRoot ('Temp\{0}.xml' -f [guid]::NewGuid().ToString('N'))
try {
$bytes = (New-Object System.Text.UTF8Encoding($false)).GetBytes($xml)
$fs = [IO.File]::Open($tmp, [IO.FileMode]::CreateNew, [IO.FileAccess]::Write, [IO.FileShare]::None)
try { $fs.Write($bytes, 0, $bytes.Length) } finally { $fs.Dispose() }
$r = Invoke-Netsh -Arguments @('wlan', 'add', 'profile', "filename=$tmp", 'user=all')
if ($r.ExitCode -ne 0) {
throw "netsh a échoué (code $($r.ExitCode)) : $($r.Output)"
}
Write-Log INFO "Profil '$ssid' importé. netsh : $($r.Output)"
}
finally {
if (Test-Path -LiteralPath $tmp) {
Remove-Item -LiteralPath $tmp -Force -ErrorAction SilentlyContinue
if (Test-Path -LiteralPath $tmp) {
Write-Log WARN "Impossible de supprimer le fichier temporaire $tmp (contient une clé en clair)."
}
}
}
}
function Set-WifiPriority {
param([string[]]$Profiles, [object[]]$Adapters)
foreach ($adapter in $Adapters) {
$priority = 1
foreach ($name in $Profiles) {
$r = Invoke-Netsh -Arguments @('wlan', 'set', 'profileorder', "name=$name", "interface=$($adapter.Name)", "priority=$priority")
if ($r.ExitCode -ne 0) {
Write-Log WARN "Priorité $priority non appliquée pour '$name' sur '$($adapter.Name)' : $($r.Output)"
}
$priority++
}
}
}
# =====================================================================
# PROGRAMME PRINCIPAL
# =====================================================================
function Invoke-Main {
Write-Log INFO "===== $AppName v$AppVersion - $env:COMPUTERNAME - compte : $([Security.Principal.WindowsIdentity]::GetCurrent().Name) ====="
if (-not (Test-IsAdmin)) {
Write-Log ERROR 'Droits administrateur requis (le script doit tourner en script de démarrage ordinateur).'
$script:ExitCode = 2
return
}
if (-not (Wait-WlanService)) { return }
$adapters = Get-WifiAdapters
if ($adapters.Count -eq 0) {
Write-Log INFO 'Aucune carte Wi-Fi active détectée : aucune action.'
return
}
Write-Log INFO ("Carte(s) Wi-Fi : " + (($adapters | ForEach-Object { "$($_.Name) [$($_.InterfaceDescription)]" }) -join ', '))
$seen = @{}
$added = New-Object System.Collections.Generic.List[string]
$failures = 0
$index = 0
foreach ($net in $WifiNetworks) {
$index++
$label = "Réseau #$index"
try {
$err = Test-WifiConfig -Net $net
if ($err) { throw $err }
$ssid = [string]$net.SSID
$label = "Réseau #$index '$ssid'"
if ($seen.ContainsKey($ssid)) { throw 'SSID en double dans la configuration.' }
$seen[$ssid] = $true
Add-WifiProfile -Net $net
$added.Add($ssid)
}
catch {
$failures++
Write-Log ERROR "$label : $($_.Exception.Message)"
}
}
if ($added.Count -gt 1) {
Set-WifiPriority -Profiles $added.ToArray() -Adapters $adapters
}
$summary = "Bilan : $($added.Count) profil(s) importé(s), $failures échec(s) sur $($WifiNetworks.Count) réseau(x) configuré(s)."
if ($failures -gt 0) {
Write-Log WARN $summary
$script:ExitCode = 1
}
else {
Write-Log INFO $summary -ToEventLog
}
}
try {
Initialize-Log
Invoke-Main
}
catch {
Write-Log ERROR "Erreur bloquante : $($_.Exception.Message)"
$script:ExitCode = 2
}
exit $script:ExitCodeScript 2 — Verifier-SetWifi.ps1
Contrôle l'installation de SetWifi sur un poste. À lancer en administrateur ; ne modifie rien.
<#
.SYNOPSIS
Contrôle l'installation de SetWifi sur le poste (script, droits, profils, journal).
.NOTES
À lancer dans une console PowerShell ouverte en tant qu'administrateur.
Enregistrer en UTF-8 avec BOM. Ce script ne modifie rien sur le poste.
#>
$ScriptPath = 'C:\Windows\System32\GroupPolicy\Machine\Scripts\Startup\setWifi_v2.ps1'
$LogPath = 'C:\Windows\Logs\SetWifi\SetWifi.log'
function Show-Result {
param([string]$Label, [bool]$Ok, [string]$Detail = '')
if ($Ok) { Write-Host " [OK] $Label" -ForegroundColor Green }
else { Write-Host " [KO] $Label" -ForegroundColor Red }
if ($Detail) { Write-Host " $Detail" -ForegroundColor Gray }
}
Write-Host "`n=== Vérification SetWifi - $env:COMPUTERNAME ===" -ForegroundColor Cyan
# 1. Présence et encodage du script
Write-Host "`n1. Script de démarrage" -ForegroundColor Cyan
$present = Test-Path -LiteralPath $ScriptPath
Show-Result 'Script présent dans le dossier de démarrage' $present $ScriptPath
if ($present) {
$bytes = [IO.File]::ReadAllBytes($ScriptPath)
$bom = $bytes.Length -ge 3 -and $bytes[0] -eq 0xEF -and $bytes[1] -eq 0xBB -and $bytes[2] -eq 0xBF
Show-Result 'Encodage UTF-8 avec BOM' $bom
$placeholder = Select-String -LiteralPath $ScriptPath -Pattern "SSID\s*=\s*'A_REMPLACER'" -Quiet
Show-Result 'Aucune ligne d''exemple restante' (-not $placeholder)
}
# 2. Droits d'accès au script
Write-Host "`n2. Protection du script" -ForegroundColor Cyan
if ($present) {
$acl = Get-Acl -LiteralPath $ScriptPath
$allowed = @('S-1-5-18', 'S-1-5-32-544') # SYSTEM, Administrateurs
$others = @()
foreach ($rule in $acl.Access) {
try { $sid = $rule.IdentityReference.Translate([Security.Principal.SecurityIdentifier]).Value }
catch { $sid = $rule.IdentityReference.Value }
if ($sid -notin $allowed) { $others += $rule.IdentityReference.Value }
}
Show-Result 'Héritage des droits désactivé' $acl.AreAccessRulesProtected
Show-Result 'Accès réservé à SYSTEM et aux Administrateurs' ($others.Count -eq 0) `
$(if ($others.Count) { 'Comptes en trop : ' + (($others | Sort-Object -Unique) -join ', ') })
}
else {
Show-Result 'Contrôle impossible : script absent' $false
}
# 3. Profils Wi-Fi installés
Write-Host "`n3. Profils Wi-Fi installés" -ForegroundColor Cyan
netsh.exe wlan show profiles | ForEach-Object { if ($_.Trim()) { Write-Host " $_" } }
# 4. Dernier bilan du journal
Write-Host "`n4. Dernier démarrage" -ForegroundColor Cyan
if (Test-Path -LiteralPath $LogPath) {
$last = Select-String -LiteralPath $LogPath -Pattern 'Bilan' | Select-Object -Last 1
if ($last) {
Show-Result 'Dernier bilan sans échec' ($last.Line -match ' 0 échec') $last.Line
}
else {
Show-Result 'Aucun bilan dans le journal' $false $LogPath
}
}
else {
Show-Result 'Journal absent : le script ne s''est pas encore exécuté' $false $LogPath
}
# 5. Derniers événements Windows
Write-Host "`n5. Derniers événements (journal Application, source SetWifi)" -ForegroundColor Cyan
$events = Get-WinEvent -FilterHashtable @{ LogName = 'Application'; ProviderName = 'SetWifi' } -MaxEvents 5 -ErrorAction SilentlyContinue
if ($events) {
$events | ForEach-Object { Write-Host (" {0:yyyy-MM-dd HH:mm} [{1}] {2}" -f $_.TimeCreated, $_.Id, ($_.Message -split "`n")[0]) }
}
else {
Write-Host ' Aucun événement trouvé.' -ForegroundColor Gray
}
Write-Host ''Updated about 6 hours ago
