Formation PowerShell (TP)

En cherchant une cas concret pour des travaux pratiques lors d’une formation PowerShell dispensée à quelques collègues, je suis tombé sur une pépite.

Cette idée était tellement sympa et stimulante qu’il m’a paru impossible de ne pas la partager avec la communauté francophone.

J’ai fait de cet exercice sur la gestion des modes d’alimentation un petit cookbook illustré d’environs une trentaine de pages, disponible ici .

Voici le code qui accompagne ce petit cookbook. Il est disponible sur ce lien

C’est pas tout! Une occasion unique s’offre à vous 😀
Vous pouvez apprendre PowerShell DSC (Desired State Configuration) le 25 et 26 février en live sur la Microsoft Virtual Academy.
C’est ​Jeffrey Snover et Jason Helmick qui dispensent ces 2 cours.

Pour ce faire, il faut:

Follow-up: configuring a proxy with DSC

While working on a custom DSC (Desired State Configuration) resource that forces the Windows Update Agent to opt-in to Microsoft Update, I found a major caveat with my previous blog post about configuring a proxy per machine with DSC.

My server wouldn’t opt-in to Microsoft Update (MU) and when it tried, it last ~20 seconds which is an excessive amount of time. Under my user account, the registration takes less than a second.

Here’s the code I’m using inside the DSC resource and at command prompt.

(New-Object -ComObject Microsoft.Update.ServiceManager).
AddService2('7971f918-a847-4430-9279-4a52d1efe18d',7,"");

I couldn’t understand why and started a procmon trace.

The WindowsUpdate.log file acknowledged that it lasts 20 seconds and indicated that it doesn’t use the proxy set per machine 😦

The procmon trace indicated that the Windows Update service was looking for the WinHttpSettings value and couldn’t find it

My bad 😦
That’s what I actually set in my DSC configuration as I set the WinHttpSetting as absent.

To fix it, I duplicated the DefaultConnectionSettings item and set the exact same value for the WinHttpSettings item

And now the registration is back to normal:

I also found a second problem while reading the verbose output when applying the DSC configuration 😦

[ Start Test ] [[Registry]ProxyAddressPerMachineDefaultConnectionSettings]
VERBOSE: [MyComputerName]: [[Registry]ProxyAddressPerMachineDefaultConnectionSettings] Registry key value ‘HKLM:\software\microsoft\windows\currentversion\internet settings\connections\DefaultConnectionSettings’ of type ‘Binary’ does not contain data ‘46000000040000000300000015…0’

The DSC Test-TargetResource function always returned false because the registry value set in the first place was somehow “autocorrected”.
The fact that the Test-TargetResource always returns false isn’t normal.

I recommended in my original post to extract the value from the registry like this:

$regkey = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings\Connections"
-join (
(Get-ItemProperty -Path  $regkey -Name DefaultConnectionSettings).DefaultConnectionSettings |
 Foreach-Object { '{0:X2}' -f $_ })

…which is the wrong way and the root cause of the above behavior I described.

My bad 😦 Sorry about that.

I fixed my issue by capturing correctly the hexadecimal value from the registry 😀

$regkey = "HKLM:\Software\Microsoft\Windows\CurrentVersion\Internet Settings\Connections"
-join (
(Get-ItemProperty -Path  $regkey -Name DefaultConnectionSettings).DefaultConnectionSettings |
 Foreach-Object { '{0:X1}' -f $_ })

Backporting the Get-FileHash function

Not later than this morning, my colleague needed to check the checksum of a file but didn’t got any PowerShell script to easily get it but got the 11-years old fciv.exe instead.

To get rid of the fciv.exe utility, there’s actually a Get-FileHash function available as of PowerShell version 4.0 built-in the Microsoft.PowerShell.Utility module.

Good news! As it’s a function, it’s directly accessible from the Microsoft.PowerShell.Utility.psm1 file and the effort to make it work on PowerShell version 2.0 on Windows 7 isn’t as monumental as we can think.

The first step is to open the module on a Windows 10 Technical Preview in the ISE to copy the first 2 functions Get-FileHash and GetStreamHash.

and paste them into the ISE of a PowerShell version 2.0

NB: We can see that the syntax highlighting is broken.

The second step consists in making minor changes to make these functions compatible with PowerShell version 2.0

  • On lines 5,9 and 14: replace the Mandatory statement by Mandatory = $true.
    It will restore the syntax highlighting and avoid the following error message
  • # from
    [Parameter(Mandatory, ParameterSetName="Path", Position = 0)]
    # to
    [Parameter(Mandatory=$true, ParameterSetName="Path", Position = 0)]
    
  • On line 3, remove the HelpURI from the CmdletBinding statement and avoid the following error message
  • # from
    [CmdletBinding(DefaultParameterSetName = "Path", HelpURI = "http://go.microsoft.com/fwlink/?LinkId=517145")]
    # to
    [CmdletBinding(DefaultParameterSetName = "Path")]
    
  • On lines 40 and 44, fix the Foreach-Object statement and avoid the following error message
  • # from
    $pathsToProcess += Resolve-Path $Path | 
    Foreach-Object ProviderPath
    # to
    $pathsToProcess += Resolve-Path $Path | 
    Foreach-Object { $_.ProviderPath}
    
  • On line 62, remove the type PowerShell isn’t aware of when the file doesn’t exist
  • # from
    $errorMessage = [Microsoft.PowerShell.Commands.UtilityResources]::FileReadError -f $FilePath, $_
    # to
    $errorMessage = 'FileReadError {0}:{1}' -f $FilePath, $_
    

That’s all folks 😎

You can see the result (stored as gist file)