Pearls of Wisdom
This is where I am going to put PowerShell facts that don't really fit anywhere else
In PowerShell a hastable is a series of key value pairs it is effectively an associative array and it looks like this
@{"key"="value","FirstName"="Paul","LastName"="Frampton"}
A splat or here string is more like a multiline variable and looks like this
$var = 'hello' $message = @" $var This is a string "@
Replace and Split
These utilities are useful for manipulating strings
Replace replaces one sting with another. I have used this to change date formats
(Get-Date).ToShortDateString().Replace("/","-")
(Get-Date).ToShortDateString() 27/05/2020 (Get-Date).ToShortDateString().Replace("/","-") 27-05-2020
Split breaks a string on certain deliminators. I have used this one to break an email address into first name last name.
$email = "John.Smith@company.com" $firstname = $email.Split(".")[0] $lnameraw = $email.Split(".")[1] $lastName = $lnameraw.Split("@")[0] $firstname $lastName John Smith
Handling native command line utilities that don't work well with PowerShell
A good example of this is icacls this can be handled in 2 ways.
icacls c:\test\* /grant "administrator:(d,wdac)" icacls --% c:\text\* /grant administrator:(d,wdac)
The --% is for PowerShell 3 and above PowerShell treats --% just like it is a command line utility
"contains" and "in"
$x = 1,2,3,4,5,6,'one','two','three','four','five','six' $x -contains 'two' True $x -contains 7 False 4 -in $x True 8 -in $x False
Join
Join is useful if your results return a column and you want to change the output to a comma (or somthing else) separated list
$arr = 1,2,3,4,5,6,7,8,9 $arr += 'one','two','three' $arr 1 2 3 4 5 6 7 8 9 one two three $arr -join ',' 1,2,3,4,5,6,7,8,9,one,two,three
Setting Default parameter values
Supposing you were checking event logs regularly and always specifying the -Newest 10 and you are getting tired of typing that in
get-eventlog -LogName Security -Newest 10
There is a variable called $PSDefaultParameterValues which starts off empty but you can add values to it in the form of a hashtable
$PSDefaultParameterValues = @{ key=value ; key=value} #these exist as key = value pairs
$PSDefaultParameterValues = @{"get-eventlog:newest"=10} Get-EventLog application Index Time EntryType Source InstanceID Message ----- ---- --------- ------ ---------- ------- 11647 May 29 10:22 Information edgeupdate 0 The description for Event ID '0' in Source 'edgeupdate' can... 11646 May 29 10:22 Information edgeupdate 0 The description for Event ID '0' in Source 'edgeupdate' can... 11645 May 29 10:22 Information edgeupdatem 0 The description for Event ID '0' in Source 'edgeupdatem' ca... 11644 May 29 09:26 Information Software Protecti... 1073758208 Successfully scheduled Software Protection service for re-s... 11643 May 29 09:26 Information Software Protecti... 3221241866 Offline downlevel migration succeeded. 11642 May 29 09:22 Information edgeupdatem 0 The description for Event ID '0' in Source 'edgeupdatem' ca... 11641 May 29 09:22 Information edgeupdate 0 The description for Event ID '0' in Source 'edgeupdate' can... 11640 May 29 08:22 Information edgeupdate 0 The description for Event ID '0' in Source 'edgeupdate' can... 11639 May 29 08:22 Information edgeupdatem 0 The description for Event ID '0' in Source 'edgeupdatem' ca... 11638 May 29 07:48 Information SecurityCenter 15 Updated Windows Defender status successfully to SECURITY_PR...
To add another value to $PSDefaultParameterValues you can write the same command and add a new value by adding a semi column but a better way is this format
$PSDefaultParameterValues.add("get-eventlog:logname","application")
Now if you type get-eventlog the application log comes up by default.
To remove these setting use:
$PSDefaultParameterValues.Remove("get-eventlog:newest")
Regions
Regions make your code more readable they are collapsable which can help you to concentrate on the parts of the script that you are interested in
It works like this:
#region function1 function dosomething { something } #endregion #region do next function code more code #endregion
It is important to note the syntax it is hash region all lower case followed by a space and an optional comment and the closing tag is #endregion all lowercase and one word and nothing else on the line.
Storing Credentials
There are a number of ways of storing credentials you can use:
Get-Credential | Export-Clixml C:\scripts\cred.xml PS C:\> cat C:\scripts\cred.xml <Objs Version="1.1.0.1" xmlns="http://schemas.microsoft.com/powershell/2004/04"> <Obj RefId="0"> <TN RefId="0"> <T>System.Management.Automation.PSCredential</T> <T>System.Object</T> </TN> <ToString>System.Management.Automation.PSCredential</ToString> <Props> <S N="UserName">administrator</S> <SS N="Password">01000000d08c9ddf0115d1118c7a00c04fc297eb01000000214f81b1ef716b47969dee18481a6205 00000000020000000000106600000001000020000000cb0fa894651979558d32dc3572494715c91a3f662e82418e7cf4fd44 0a298f7b000000000e80000000020000200000005483214c76b293f3b119dc2b1ae18f5b6dfdbf0c37f6dca9b0b456596449 0b12200000003d8e817a54fc719ce896a936410bdb2bfae3ee88b0d32e5077172c130d4ba7d140000000a5a0f3dbb0eadb54 98557c9584e35a9a0fb5f6d3c17431e0448cdb4120ea8caa1129e7e7ab7b67acaed2450949d9b3dafdb35e369b720b75bbb 40f67987fbe91</SS> </Props> </Obj> </Objs> $cred = Import-Clixml C:\scripts\cred.xml
Perhaps a better solution would be to use the credential manager that comes with Windows
Add a generic credential using the GUI say O365 give it the appropriate user name and password and save it.
This can also be done with the following command after you have installed the credential manager module.
New-StoredCredential -Target [servername] -UserName [username] -Password [password] -persist ENTERPRISE
To use this password in a script you will first need to install the module Install-Module -Name credentialmanager
Then use Get-StoredCredential
to assign the credential to a variable
$mancred = Get-StoredCredential -Target O365
Now you can use that credential as you please
$session = New-PSSession -ConfigurationName Microsoft.Exchange` -ConnectionUri https://outlook.office365.com/powershell-liveid/` -Credential $mancred -authentication basic -allowredirection Import-PSSession $session