PowerShell for Windows Admins

August 28, 2015  1:31 PM

PowerShell User Group meeting in Manchester

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

The UK PowerShell User Group was the World’s first user group dedicated to PowerShell. Its been in hibernation for the last few years but Ryan Yates is bringing it back to life.

He’s set up a meeting in Manchester for Tuesday 13 October 2016. See  http://www.kilasuit.org/Blog/Post/18/Coming-to-Manchester-October-13th—Get-PSUGUKMan

for details.

If you’re in the area I’d recommend you get there if you can

August 27, 2015  12:38 PM

PowerShell Summit Europe 2015 final schedule

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

The schedule for the PowerShell Summit Europe 2015 has been finalised.  See the event site at http://eventmgr.azurewebsites.net/event/home/PSEU15#schedule

August 26, 2015  2:33 PM

PowerShell gallery security

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

There are a number of concerns with pulling code from the Internet e.g. code quality and whether it contains malicious actions.

The PowerShell gallery has implemented a couple of features that should help. All modules have to meet a minimum quality standard as outlined here – http://blogs.msdn.com/b/powershell/archive/2015/08/07/powershell-gallery-new-security-scan.aspx

You can also use Save-Module to download the module to a safe location so you can inspect the contents.

August 19, 2015  10:03 AM

Creating JSON from a hash table

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
JSON, Powershell

A question on the forum was asking about creating a JSON structure for use with a REST API.

The original has table looked like this

$body = @{
auth_token = “$auth_token”
items = @{
label = “server1”
value = “OK”
label = “server2”
value = “OK”

This fails because you can’t have duplicate keys in a hash table.

One way to create the JSON is like this

$items = @()
$items += @{label = “server1”; value = “OK”}
$items += @{label = “server2”; value = “OK”}

$body = New-Object -TypeName PSOBject -Property @{
auth_token = “$auth_token”
Items = $items

ConvertTo-Json -InputObject $body

which gives:

“Items”:  [
“value”:  “OK”,
“label”:  “server1”
“value”:  “OK”,
“label”:  “server2”
“auth_token”:  “”

The items are created by adding hah tables to a pre-existing hash table.  You’re creating a hashtable of hash tables.

If you need to control the order of values you need an ordered hash table to use with New-Object

$items = @()
$items += @{label = “server1”; value = “OK”}
$items += @{label = “server2”; value = “OK”}

$props =  [ordered]@{
auth_token = “$auth_token”
Items = $items

$body = New-Object -TypeName PSOBject -Property $props

ConvertTo-Json -InputObject $body

which gives

“auth_token”:  “”,
“Items”:  [
“value”:  “OK”,
“label”:  “server1”
“value”:  “OK”,
“label”:  “server2”

August 18, 2015  7:33 AM

Passing data into Jobs

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

PowerShell jobs are a powerful tool for running processes in the background. You have to remember that a PowerShell job runs in a separate process that only exists for the duration of the job. The results are returned to your process when the job finishes.

A user on the forum asked about passing variables into jobs.  He’d done this:

$w = ‘1..10’
Invoke-Expression $w

and got the expected result


He then tried this

Start-Job -ScriptBlock { Invoke-Expression $w}

But the job said

Cannot bind argument to parameter ‘Command’ because it is null.
+ CategoryInfo          : InvalidData: (:) [Invoke-Expression], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.InvokeExpre
+ PSComputerName        : localhost

Irrespective of whether using Invoke-Expression is a good idea  and I’ll cover that in a future post the job fails because its failing to find $w because the job is running in a separate PowerShell process and $w doesn’t exist.

The simplest answer is to make the job self contained

Start-Job -ScriptBlock { $w = ‘1..10’; Invoke-Expression $w}

Everything is in the script block passed to the job and therefore passed to the new PowerShell process.

Alternatively, you can pass the variable $w into the script block

Start-Job -ScriptBlock { param($w) Invoke-Expression $w} -ArgumentList $w

You need to define a param block on the script block and pass the $w variable to it using the –Argumentlist parameter on start-job.

Another option introduced with PowerShell 3.0 us the $using scope modifier

Start-Job -ScriptBlock { Invoke-Expression $using:w}

Which is another way to say use the $w variable from the current scope

You can find out more on $using from about_scopes, about_Remote_Variables

August 11, 2015  12:45 PM

WinOps conference

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
DevOps, Powershell

The WinOps conference will take place 22 September 2015 in London.

Details from http://winops.org/

Its all about “Windows in a DevOps world”

August 10, 2015  5:51 AM

Windows 10 and PSScriptAnalyzer

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

If you were wondering where the PSScriptanalyzer module was in Windows 10 RTM – its not there.  Its been moved out of core PowerShell and is now available on the PSGallery.

£> Find-Module *Script*

Version    Name                                Repository
——-    —-                                ———-
0.1        nScriptAnalyzerRules                PSGallery
1.0.2      PSScriptAnalyzer                    PSGallery    ScriptBrowser                       PSGallery    ScriptCop                           PSGallery    ScriptCS                            PSGallery
1.0        ScriptTransforms                    PSGallery
1.0        SQLInvokeScripts                    PSGallery

You can install it from the gallery

£> Install-Module -Name PSScriptAnalyzer

You are installing the module(s) from an untrusted repository. If you trust this repository, change its
InstallationPolicy value by running the Set-PSRepository cmdlet.
Are you sure you want to install software from ‘https://www.powershellgallery.com/api/v2/’?
[Y] Yes  [A] Yes to All  [N] No  [L] No to All  [S] Suspend  [?] Help (default is “N”): y

By default the gallery isn’t a trusted source so you’ll need to confirm the install.  I’d recommend NOT making PSGallery a trusted source. That designation should be reserved for your internal repositories.

The module has 2 cmdlets

£> Get-Command -Module PSScriptAnalyzer

CommandType     Name
———–     —-
Cmdlet          Get-ScriptAnalyzerRule
Cmdlet          Invoke-ScriptAnalyzer

You can view the rules currently available:

£> Get-ScriptAnalyzerRule | Format-Table RuleName, Severity -AutoSize

RuleName                                          Severity
——–                                          ——–
PSAvoidUsingCmdletAliases                          Warning
PSAvoidDefaultValueSwitchParameter                 Warning
PSAvoidUsingEmptyCatchBlock                        Warning
PSAvoidGlobalVars                                  Warning
PSAvoidInvokingEmptyMembers                        Warning
PSAvoidUsingPositionalParameters                   Warning
PSReservedCmdletChar                               Warning
PSReservedParams                                   Warning
PSAvoidShouldContinueWithoutForce                  Warning
PSAvoidUsingDeprecatedManifestFields               Warning
PSProvideDefaultParameterValue                     Warning
PSAvoidUninitializedVariable                       Warning
PSAvoidUsingUserNameAndPassWordParams                Error
PSAvoidUsingComputerNameHardcoded                    Error
PSAvoidUsingConvertToSecureStringWithPlainText       Error
PSAvoidUsingInternalURLs                       Information
PSAvoidUsingInvokeExpression                       Warning
PSAvoidUsingPlainTextForPassword                   Warning
PSAvoidUsingWMICmdlet                              Warning
PSAvoidUsingWriteHost                              Warning
PSUseOutputTypeCorrectly                       Information
PSMissingModuleManifestField                       Warning
PSPossibleIncorrectComparisonWithNull              Warning
PSProvideCommentHelp                           Information
PSUseApprovedVerbs                                 Warning
PSUseCmdletCorrectly                               Warning
PSUseDeclaredVarsMoreThanAssigments                Warning
PSUsePSCredentialType                              Warning
PSShouldProcess                                    Warning
PSUseShouldProcessForStateChangingFunctions        Warning
PSUseSingularNouns                                 Warning
PSDSCDscTestsPresent                           Information
PSDSCDscExamplesPresent                        Information
PSDSCUseVerboseMessageInDSCResource            Information
PSDSCUseIdenticalMandatoryParametersForDSC           Error
PSDSCUseIdenticalParametersForDSC                    Error
PSDSCStandardDSCFunctionsInResource                  Error
PSDSCReturnCorrectTypesForDSCFunctions         Information

You can also get a description of the rule. Its worth reading through the rules to see what is considered best practice by the authors of this module!

This simple script should trigger a few rules Smile

Write-Host ‘getting data’
gwmi Win32_computersystem

£> Invoke-ScriptAnalyzer -Path C:\TestScripts\testsa.ps1 | fl
RuleName : PSAvoidUsingWriteHost
Severity : Warning
Line     : 1
Column   : 1
Message  : File ‘testsa.ps1’ uses Write-Host. This is not recommended because it may not work in some hosts or there  may even be no hosts at all. Use Write-Output instead.

RuleName : PSAvoidUsingPositionalParameters
Severity : Warning
Line     : 2
Column   : 1
Message  : Cmdlet ‘gwmi’ has positional parameter. Please use named parameters instead of positional parameters when  calling a command.

RuleName : PSAvoidUsingPositionalParameters
Severity : Warning
Line     : 1
Column   : 1
Message  : Cmdlet ‘Write-Host’ has positional parameter. Please use named parameters instead of positional parameters when calling a command.

RuleName : PSAvoidUsingCmdletAliases
Severity : Warning
Line     : 2
Column   : 1
Message  : ‘gwmi’ is an alias of ‘Get-WmiObject’. Alias can introduce possible problems and make scripts hard to  maintain. Please consider changing alias to its full content.

Nice simple way to test your code for best practices and avoid some of the major issues that make scripts difficult to read and maintain.

August 8, 2015  7:19 AM

Masking output

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

A question on the forum on how to stop the output from New-Item raises an important point. Many cmdlets produce output when run for example

£> New-Item -Type File -Name test.txt
Directory: C:\Test2
Mode                LastWriteTime         Length Name
—-                ————-         —— —-
-a—-       08/08/2015     14:14              0 test.txt

There are times when you want to hide that output. The converse situation where you want output from cmdlets that don’t normally produce it can be resolved with the –Passthru parameter where present or by using –verbose.

You have a number of cjoices when trying to mask output

£> New-Item -Type File -Name test1.txt | Out-Null
£> [void](New-Item -Type File -Name test2.txt)
£> New-Item -Type File -Name test3.txt > $null
£> $nf = New-Item -Type File -Name test4.txt

Any of the above techniques will work. I prefer the first one as I can develop and test the code showing output and then pipe to out-null to mask it

August 7, 2015  2:43 AM

WMF 5 roadmap

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

With the recent release of Windows 10 a lot of confusion has arisen regarding the position of PowerShell 5.0.

That confusion has been cleared up with a post from the PowerShell team – http://blogs.msdn.com/b/powershell/archive/2015/08/06/windows-management-framework-wmf-5-0-roadmap.aspx

August 6, 2015  10:23 AM

KB3081424 failed to install

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
Windows 10

Microsoft rolled out a Cumulative Update for Windows 10 – KB3081424 today. It downloaded and tried to install – got about 30% of the way through, rebooted and then went through a number of reboot cycles to uninstall the changes.

An article here http://news.softpedia.com/news/windows-10-cumulative-update-kb3081424-fails-to-install-stuck-in-reboot-loop-488638.shtml

suggested that deleting keys related to orphaned profiles (users no longer exist) from

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList

may fix the problem.  As it happened I had an orphaned profile key, deleted it and retried the install of KB3081424.

It worked

Forgot Password

No problem! Submit your e-mail address below. We'll send you an e-mail containing your password.

Your password has been sent to: