Question Switch-Network (WMI / Wireless Wired))

Plus d'informations
il y a 11 ans 11 mois #11774 par Matthew BETTON
Bonjour,

Ci-après un script que j'avais écrit dans le cadre des Scripting Games 2012.

Il permet, sur un portable, de basculer entre réseau filaire et réseau Wi-Fi.

Il est sur que nous pouvons effectuer ces opérations à la main, mais dans certains cas, et pour certains utilisateurs, cela peut être pratique.

De plus, ce script rassemble une série de fonctions qui peuvent être réutilisées dans d'autres codes :

Test-isLaptop
Get-NetWorkInterface
Enable-NetworkAdapter
Disable-NetworkAdapter
Test-NetworkAdapterStatus
Test-NetworkAdapterState
Select-Choice

Dans certaines de ces fonctions, j'ai repris les informations présentes dans le MSDN, notamment concernant les codes d'erreur ( Availability et ConfigManagerErrorCode ).

Enfin, vous trouverez ici la solution donnée par un expert ... et qui nécessite PowerShell V3 en pré requis.

@ +
Matthew

[code:1]
#
# 2012 Scripting Games : Advanced Event 8
# Script : Switch-Network.ps1
# Synopsis : Enable and Disable Network Adapters.
# Author : Matthew BETTON (France / Basse-Normandie / Manche (50))
# Date : 4/15/2012
#

<#
.SYNOPSIS
This script toggles network connections, from wired to wireless and vice versa.

.DESCRIPTION
The 'Switch-Network.ps1' script toggles network connections (Wired <=> Wireless).

First it looks for a Wireless Network Card and a Wired Network Card.

If both are found and functionnals, the script enables one and disables the other Network Adapter.

If both Network Adapters are enabled or both are disabled, the script ask to select one to disable or one to enable.

This script must be run on a laptop computer (portable, laptop or netbook).
If not, the script will display a Warning message and will not continue.

This script needs to be run with admin rigths and needs an elevation of privileges.
If not, the script will display a Warning message and will not continue.

#>

Function Test-isLaptop(){
<#
.SYNOPSIS
Test if local computer is a portable, laptop or netbook.

.DESCRIPTION
The 'Test-isLaptop' function test if local computer is a portable, laptop or netbook.

.OUTPUT
$True if local computer is a portable, laptop or netbook.
$False if not.

#>
try{
$SystemEnclosure = Get-WmiObject -class Win32_SystemEnclosure -ErrorAction Stop
}
catch{
Write-Warning \"An error has occured while getting informations from WMI Class 'Win32_SystemEnclosure' : $($_.Exception.Message)\"
exit
}

if($SystemEnclosure.ChassisTypes -eq 8 -or $SystemEnclosure.ChassisTypes -eq 9 -or $SystemEnclosure.ChassisTypes -eq 10){
return $true
}
else{
return $false
}
}

Function Get-NetWorkInterface(){
<#
.SYNOPSIS
Gets the 'Wired' or 'Wireless' adapter of the local computer.

.DESCRIPTION
The 'Get-NetWorkInterface' function gets the 'Wired' or 'Wireless' adapter of the local computer.

.PARAMETER Type
This parameter must be 'Wireless' or 'Wired'

.OUTPUTS
System.Management.ManagementObject#root\cimv2\Win32_NetworkAdapter

.EXAMPLE
C:\PS>Get-NetWorkInterface -Type Wireless

This command returns the 'Wireless' Network Adapter.
If more than one Adapter is found, you have to make a choice and select one adapter from a list of 'Wireless' Adapters.
#>
param(
[Validateset(\"Wireless\",\"Wired\"«»)]
$Type
)


try{
Switch($Type){
\"Wireless\" {$NetWorkInterface = Get-WmiObject -Class Win32_NetworkAdapter -Filter \"Name like '%Wireless%'\" -ErrorAction Stop}
\"Wired\" {$NetWorkInterface = Get-WmiObject -Class Win32_NetworkAdapter -Filter \"Name like '%GigaBit%' or Name like '%GBE%'\" -ErrorAction Stop}
}
}
catch{
Write-Warning \"An error has occured while getting informations from WMI Class 'Win32_NetworkAdapter' : $($_.Exception.Message)\"
exit
}

if($NetWorkInterface){
if($NetWorkInterface.count -gt 1){
$Choices = @()
$i = 0
foreach($Interface in $NetWorkInterface){
$Choices += \"&$i) $($Interface.NetConnectionID)`n($($Interface.Name))\"
$i++
}
$Selected = Select-Choice -Caption \"There are more than one $Type NetWork Card.\" -Message \"Please select one: \" -choice $Choices
return $NetWorkInterface[$Selected]

}
else{
return $NetWorkInterface
}
}
else{
Write-Warning \"Can not find a $Type Network Adapter on this System.`nScript can not continue.\"
exit
}
}

Function Enable-NetworkAdapter($WMIAdapter){
<#
.SYNOPSIS
Enables a network adapter on the local computer.

.DESCRIPTION
The 'Enable-NetworkAdapter' function enables a network adapter of the local computer.

.PARAMETER WMIAdapter
This parameter must be an object type 'System.Management.ManagementObject#root\cimv2\Win32_NetworkAdapter' returned by WMI Class 'Win32_NetworkAdapter'

.EXAMPLE
C:\PS>$adapter = Get-NetWorkInterface -Type Wireless
C:\PS>Enable-NetworkAdapter -WMIAdapter $adapter

The first command returns the 'Wireless' Network Adapter.
The second command enables the 'Wireless' Adapter.
#>
$Action = $WMIAdapter.Enable()
if($Action.ReturnValue -ne 0){
Write-Warning \"An error has occured while enabling Network Interface '$($WMIAdapter.NetConnectionID)' ($($WMIAdapter.Name)) : $($Action.ReturnValue)\"
}

}

Function Disable-NetworkAdapter($WMIAdapter){
<#
.SYNOPSIS
Disables a network adapter on the local computer.

.DESCRIPTION
The 'Disable-NetworkAdapter' function disables a network adapter of the local computer.

.PARAMETER WMIAdapter
This parameter must be an object type 'System.Management.ManagementObject#root\cimv2\Win32_NetworkAdapter' returned by WMI Class 'Win32_NetworkAdapter'

.EXAMPLE
C:\PS>$adapter = Get-NetWorkInterface -Type Wireless
C:\PS>Disable-NetworkAdapter -WMIAdapter $adapter

The first command returns the 'Wireless' Network Adapter.
The second command disables the 'Wireless' Adapter.
#>
$Action = $WMIAdapter.Disable()
if($Action.ReturnValue -ne 0){
Write-Warning \"An error has occured while disabling Network Interface '$($WMIAdapter.NetConnectionID)' ($($WMIAdapter.Name)) : $($Action.ReturnValue)\"
}
}

Function Test-NetworkAdapterState($WMIadapter){
<#
.SYNOPSIS
Returns State of a Network Adapter

.DESCRIPTION
The 'Test-NetworkAdapterState' function returns state of a network adapter of the local computer.

.PARAMETER WMIAdapter
This parameter must be an object type 'System.Management.ManagementObject#root\cimv2\Win32_NetworkAdapter' returned by WMI Class 'Win32_NetworkAdapter'

.OUTPUTS
$True when Network Adapter specified is 'Running or Full Power'.
$False when the Network Adapters is not available.

.EXAMPLE
C:\PS>$adapter = Get-NetWorkInterface -Type Wireless
C:\PS>Test-NetworkAdapterState -WMIAdapter $adapter

The first command returns the 'Wireless' Network Adapter.
The second command returns state of the 'Wireless' Adapter.
#>
$Availability = $WMIadapter.Availability

Switch($Availability){
1 {$AdapterState = \"Other\"}
2 {$AdapterState = \"Unknown\"}
3 {$AdapterState = \"Runnning or Full Power\"}
4 {$AdapterState = \"Warning\"}
5 {$AdapterState = \"In test\"}
6 {$AdapterState = \"Not Applicable\"}
7 {$AdapterState = \"Power Off\"}
8 {$AdapterState = \"Off Line\"}
9 {$AdapterState = \"Off Duty\"}
10 {$AdapterState = \"Degraded\"}
11 {$AdapterState = \"Not Installed\"}
Default {$AdapterState = \"Unknown\"}
}

if($Availability -eq 3){
return $True
}
else{
Write-Warning \"NetWork Adapter '$($WMIadapter.Name)' is not available : '$AdapterState'\"
return $False
}
}

Function Test-NetworkAdapterStatus($WMIadapter){
<#
.SYNOPSIS
Returns Status of a Network Adapter

.DESCRIPTION
The 'Test-NetworkAdapterStatus' function returns status of a network adapter of the local computer.

.PARAMETER WMIAdapter
This parameter must be an object type 'System.Management.ManagementObject#root\cimv2\Win32_NetworkAdapter' returned by WMI Class 'Win32_NetworkAdapter'

.OUTPUTS
$True when Network Adapter specified is 'working properly' = 'Enabled'.
$False when the Network Adapters is not 'Disabled'.
Warning if the Network Adapter is not working properly.

.EXAMPLE
C:\PS>$adapter = Get-NetWorkInterface -Type Wireless
C:\PS>Test-NetworkAdapterStatus -WMIAdapter $adapter

The first command returns the 'Wireless' Network Adapter.
The second command returns status of the 'Wireless' Adapter.
#>
$ConfigManagerErrorCode = $WMIadapter.ConfigManagerErrorCode

Switch($ConfigManagerErrorCode){
0 {$AdapterStatus = \"Device is working properly.\"}
1 {$AdapterStatus = \"Device is not configured correctly.\"}
2 {$AdapterStatus = \"Windows cannot load the driver for this device.\"}
3 {$AdapterStatus = \"Driver for this device might be corrupted, or the system may be low on memory or other resources.\"}
4 {$AdapterStatus = \"Device is not working properly. One of its drivers or the registry might be corrupted.\"}
5 {$AdapterStatus = \"Driver for the device requires a resource that Windows cannot manage.\"}
6 {$AdapterStatus = \"Boot configuration for the device conflicts with other devices.\"}
7 {$AdapterStatus = \"Cannot filter.\"}
8 {$AdapterStatus = \"Driver loader for the device is missing.\"}
9 {$AdapterStatus = \"Device is not working properly. The controlling firmware is incorrectly reporting the resources for the device.\"}
10 {$AdapterStatus = \"Device cannot start.\"}
11 {$AdapterStatus = \"Device failed.\"}
12 {$AdapterStatus = \"Device cannot find enough free resources to use.\"}
13 {$AdapterStatus = \"Windows cannot verify the device's resources.\"}
14 {$AdapterStatus = \"Device cannot work properly until the computer is restarted.\"}
15 {$AdapterStatus = \"Device is not working properly due to a possible re-enumeration problem.\"}
16 {$AdapterStatus = \"Windows cannot identify all of the resources that the device uses.\"}
17 {$AdapterStatus = \"Device is requesting an unknown resource type.\"}
18 {$AdapterStatus = \"Device drivers must be reinstalled.\"}
19 {$AdapterStatus = \"Failure using the VxD loader.\"}
20 {$AdapterStatus = \"Registry might be corrupted.\"}
21 {$AdapterStatus = \"System failure. If changing the device driver is ineffective, see the hardware documentation. Windows is removing the device.\"}
22 {$AdapterStatus = \"Device is disabled.\"}
23 {$AdapterStatus = \"System failure. If changing the device driver is ineffective, see the hardware documentation.\"}
24 {$AdapterStatus = \"Device is not present, not working properly, or does not have all of its drivers installed.\"}
25 {$AdapterStatus = \"Windows is still setting up the device.\"}
26 {$AdapterStatus = \"Windows is still setting up the device.\"}
27 {$AdapterStatus = \"Device does not have valid log configuration.\"}
28 {$AdapterStatus = \"Device drivers are not installed.\"}
29 {$AdapterStatus = \"Device is disabled. The device firmware did not provide the required resources.\"}
30 {$AdapterStatus = \"Device is using an IRQ resource that another device is using.\"}
31 {$AdapterStatus = \"Device is not working properly. Windows cannot load the required device drivers.\"}
Default {$AdapterStatus = \"Device's status is unknown.\"}
}

if($ConfigManagerErrorCode -eq 0){
return $True
}
elseif($ConfigManagerErrorCode -eq 22){
return $false
}
else{
Write-Warning \"NetWork Adapter '$($WMIadapter.Name)' is not working properly : '$AdapterStatus'.`nScript can not continue\"
exit
}

}

Function Select-Choice{
<#
.SYNOPSIS
Display a selections menu to make a choice.

.DESCRIPTION
The 'Select-Choice' function displays a selections menu and offers to the user to make a choice.

.PARAMETER ChoiceList
An array of Strings. Each String value defines a choice.

.PARAMETER Caption
String that defines the caption of the selections Menu.

.PARAMETER Message
String that defines the proposal message of the selections Menu.

.PARAMETER Default
Value that defines the default choice. The first choice is made by default ('0').

.OUTPUTS
System.Int32
The choice number made by the user.

.EXAMPLE
C:\PS>$Choices = \"&0) Disable Wireless Network Interface\", \"&1) Disable Wired Interface\",\"&2) Cancel\"
C:\PS>Switch(Select-Choice -Caption \"Both network interfaces are enabled\" -Message \"Please select interface to disable: \" -choice $Choices -default 1 ){
0 {Write-Host \"Disabling Wireless Network Card ...\" ; Disable-NetWorkAdapter($WirelessInterface)}
1 {Write-Host \"Disabling Wired Network Card ...\" ; Disable-NetWorkAdapter($WiredInterface)}
2 {Write-Host \"Your choice is 'Cancel'\" ; exit}
}
Displays a selections menu to the user in order to select the Network Card to enable.
#>
Param(
[String[]]$ChoiceList,
[String]$Caption,
[String]$Message,
[int]$default=0
)

$choicedesc = New-Object System.Collections.ObjectModel.Collection[System.Management.Automation.Host.ChoiceDescription]

$choiceList | foreach { $choicedesc.Add((New-Object \"System.Management.Automation.Host.ChoiceDescription\" -ArgumentList $_))}

$Host.ui.PromptForChoice($caption, $message, $choicedesc, $default)
}

If (-not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] \"Administrator\"«»)){
Write-Warning \"This script requires Admin Rights. Please run this script with an account that has sufficient rights.\"
exit
}

If (-not (Test-isLaptop)){
Write-Warning \"This computer is not a laptop\"
exit
}

$WirelessInterface = Get-NetWorkInterface -Type Wireless
$WiredInterface = Get-NetWorkInterface -Type Wired

if(Test-NetworkAdapterState($WirelessInterface) -AND Test-NetworkAdapterState($WiredInterface)){

$WirelessEnabled = Test-NetworkAdapterStatus($WirelessInterface)
$WiredEnabled = Test-NetworkAdapterStatus($WiredInterface)


if($WirelessEnabled -AND $WiredEnabled){
$Choices = \"&0) Disable Wireless Network Interface\", \"&1) Disable Wired Interface\",\"&2) Cancel\"
Switch(Select-Choice -Caption \"Both network interfaces are enabled\" -Message \"Please select interface to disable: \" -choice $Choices -default 1 ){
0 {Write-Host \"Disabling Wireless Network Card ...\" ; Disable-NetWorkAdapter($WirelessInterface)}
1 {Write-Host \"Disabling Wired Network Card ...\" ; Disable-NetWorkAdapter($WiredInterface)}
2 {Write-Host \"Your choice is 'Cancel'\" ; exit}
}
}
elseif(-not $WirelessEnabled -AND -not $WiredEnabled){
$Choices = \"&0) Enable Wireless Network Interface\", \"&1) Enable Wired Interface\",\"&2) Cancel\"
Switch(Select-Choice -Caption \"Both network interfaces are disabled\" -Message \"Please select interface to enable: \" -choice $Choices -default 1 ){
0 {Write-Host \"Enabling Wireless Network Card ...\" ; Enable-NetWorkAdapter($WirelessInterface)}
1 {Write-Host \"Enabling Wired Network Card ...\" ; Enable-NetWorkAdapter($WiredInterface)}
2 {Write-Host \"Your choice is 'Cancel'\" ; exit}
}
}
elseif(-not $WirelessEnabled -AND $WiredEnabled){
Write-Host \"Enabling Wireless Network Card ...\"
Enable-NetWorkAdapter($WirelessInterface)
Write-Host \"Disabling Wired Network Card ...\"
Disable-NetWorkAdapter($WiredInterface)
}
elseif($WirelessEnabled -AND -not $WiredEnabled){
Write-Host \"Disabling Wireless Network Card ...\"
Disable-NetWorkAdapter($WirelessInterface)
Write-Host \"Enabling Wired Network Card ...\"
Enable-NetWorkAdapter($WiredInterface)
}

}
else{
Write-Warning \"There is a problem with at least one network adapter. This script can not continue.\"
exit
}
[/code:1]

Connexion ou Créer un compte pour participer à la conversation.

Plus d'informations
il y a 11 ans 11 mois #11793 par Laurent Dardenne
Salut Matthew,
pour ce type de code :
[code:1]
Switch($Availability){
1 {$AdapterState = \"Other\"}
2 {$AdapterState = \"Unknown\"}
3 {$AdapterState = \"Runnning or Full Power\"}
4 {$AdapterState = \"Warning\"}
5 {$AdapterState = \"In test\"}
6 {$AdapterState = \"Not Applicable\"}
7 {$AdapterState = \"Power Off\"}
8 {$AdapterState = \"Off Line\"}
9 {$AdapterState = \"Off Duty\"}
10 {$AdapterState = \"Degraded\"}
11 {$AdapterState = \"Not Installed\"}
Default {$AdapterState = \"Unknown\"}
}
[/code:1]
On peut utiliser cette astuce .
Ce qui donne :
[code:1]
$AdapterState=@{
1=\"Other\"
2=\"Unknown\"
3= \"Runnning or Full Power\"
4= \"Warning\"
5= \"In test\"
6= \"Not Applicable\"
7= \"Power Off\"
8= \"Off Line\"
9= \"Off Duty\"
10= \"Degraded\"
11= \"Not Installed\"
Default=\"Unknown value\" # LIMITE : les valeurs à tester ne doivent pas inclure le nom clé 'Default'
}
#$AdapterState.GetEnumerator()|% {$_.Key.gettype()}

$Availability=2
$AdapterState.$Availability

$Availability=55

$GetAdapterState={
if ($AdapterState.ContainsKey($Availability))
{$AdapterState.$Availability}
else
{ $AdapterState.Default}
}
&$GetAdapterState
[/code:1]
On peut aussi utiliser le mécanisme de sélection de la langue courante ('localisation')
[code:1]
md 'C:\temp\fr-Fr'
@\"
ConvertFrom-StringData @'
1=\"Autre\"
2=\"Inconnue\"
3= \"En cours d'exécution ou sous secteur\"
4= \"Avertisssement\"
5= \"En test\"
6= \"Inapplicable\"
7= \"Hors secteur\"
8= \"hors ligne\"
9= \"hors service\"
10= \"Dégradé\"
11= \"N'est pas installé\"
Default=\"Valeur inconnue\"
'@
\"@ > 'C:\temp\fr-Fr\LocalizedData.psd1'

Set-location \"C:\temp\"

Import-LocalizedData -BindingVariable AdapterState -Filename 'LocalizedData.psd1' -EA Stop
#AdapterState.GetEnumerator()|% {$_.Key.gettype()}

$Availability=2
$AdapterState.$Availability

$Availability=\"2\"
$AdapterState.$Availability
$Availability=55
&$GetAdapterState
$Availability=\"55\"
&$GetAdapterState
#AdapterState.GetEnumerator()|% {$_.Key.gettype()}
[/code:1]
Il reste un piège qui est que l'on peut pas combiner facilement des hashtables créées dans le code avec celles créées par le cmdlet Import-LocalizedData.
Mais si, pour créer des hashtables localisées, on utilise que le cmdlet Import-LocalizedData cela ne pose pas de pb car les clés seront tjr du type String.

Une autre optimisation, pour le fun :
[code:1]
try{
Switch($Type){
\"Wireless\" {$NetWorkInterface = Get-WmiObject -Class Win32_NetworkAdapter -Filter \"Name like '%Wireless%'\" -ErrorAction Stop}
\"Wired\" {$NetWorkInterface = Get-WmiObject -Class Win32_NetworkAdapter -Filter \"Name like '%GigaBit%' or Name like '%GBE%'\" -ErrorAction Stop}
}
}
[/code:1]
Peut être transformé en :
[code:1]
$NetWorkInterfaceTypes=@{
Wireless= \"Name like '%Wireless%'\"
Wired= \"Name like '%GigaBit%' or Name like '%GBE%'\"
}
try{
$NetWorkInterface = Get-WmiObject -Class Win32_NetworkAdapter -Filter $NetWorkInterfaceTypes.$Type -ErrorAction Stop}
}
[/code:1]
L'intérêt est qu'en cas d'ajout de type on ne duplique pas le code.

Ceci dit j'aime bien lire ce type de code, c'est reposant :)<br><br>Message édité par: Laurent Dardenne, à: 13/05/12 15:08

Tutoriels PowerShell

Connexion ou Créer un compte pour participer à la conversation.

Plus d'informations
il y a 11 ans 11 mois #11807 par Matthew BETTON
Bonsoir Laurent,

Merci beaucoup pour ton retour ;)

@ +

Matthew

Connexion ou Créer un compte pour participer à la conversation.

Temps de génération de la page : 0.078 secondes
Propulsé par Kunena