and
-and
array, compare - differences
$a1 =@(1,2,3)
$b1=@(1,2,3,4)
(Compare-Object $a1 $b1 ).InputObject
returns
4
array, compare - SideIndicator
$a1 =@(1,2,3,4,5,8)
$b1=@(1,2,3,4,5,6)
Compare-Object $a1 $b1
returns
InputObject SideIndicator ----------- ------------- 6 => 8 <=
array, convert into from object - see object, convert into array
array, create from string with delimited values
$recipients = $addresses -split ";"
array, declare so increasing the number of elements is not restricted
[System.Collections.ArrayList]$array = @()
array, duplicate elements - find
$a
=
@(1,2,3,1,2)
$ht = @{}
$a
|
foreach
{$ht["$_"] += 1}
$ht.keys
|
where
{$ht["$_"] -gt
1} |
%
{Write-Host
"Duplicate element
found $_"}
array, find string as a member of
$array = 1,2,5,8,3,4,5
to use:
$array.Contains(2)
above returns True
$array.Contains(12)
above returns False
array, find elements of an array somewhere in a string
We're looking for a user that might belong to
- US tenant if his distinguished name contains one,two or three
- UK if the distinguishedName contains four,five or six or
- Germany if the distinguishedName contains Germany
the line below beginning with “if($null” has the test
$arrayTenants
= ("UK","US","Germany")
#declare a hash of tenants with their respective qualifying OUs
as elements
$O365Tenant
=
@{}
$O365Tenant["US"] = ("one","two","three")
$O365Tenant["UK"
= ("four","five","six")
$O365Tenant["Germany"] = ("seven")
Get-ADUser
-Filter
'name -like "*"'
|
ForEach-Object
{
$distinguishedName
=
$_.distinguishedName
ForEach
($tenantName
in
$arrayTenants)
{
if($null
-ne ($O365Tenant[$tenantName] |
?
{
$distinguishedName -match $_ }))
{
"$tenantName
found"
}
}
}
see here for more
array, import from text file - see text file, import into an object, record for each field in a file, parse, CSV, import into an object
array index, find which inside of foreach
loop
foreach
($item
in
$array) {
$array.IndexOf($item)
}
array, initialize
$myArray
=
@("a","b","c","d","e","f","g","h")
$myArray
=
"a","b","c","d","e","f","g","h"
create array and then display one at a time
$upn =
@("user1@yourDomain.com",
"user2@yourDomain.com",
"user3@yourDomain.com")
$upn | %{"$_"}
to also list the indices:
$upn | %{"$($upn.IndexOf($_)) $_"}
array, methods available (static) - display
[array] | gm -s | select name, definition | ft -a
This is basically a "get help" command for the PowerShell array function
array of hashes, populate - see hash, array of, populate
array of objects - convert to array of strings
put all our OU names into an array
$arrayOUs
=
Get-ADObject -Filter
{ObjectClass -eq
'organizationalunit'}
-Properties
CanonicalName
|
Select-Object
-Property Name
# convert the array of objects into an array of strings
$strArrayOUs =
$arrayOUs |
ForEach {"$($_.Name)"}
array, print contents of
the trick is the built-in ofs
variable
$proxyAddresses
=
$user.proxyAddresses
$ofs
=
'; '
# render $proxyAddresses array printable - separated by ";
"
"$($proxyAddresses.Count) useful proxyAddresses: $proxyAddresses" # prints out array
count & array contents separated by "; "
array, read into from text file - see text file, import into an object, record for each field in a file, parse, CSV, import into an object
break - see also continue, exit, return
terminates execution of a loop or switch statement and hands over control to next statement after it
This does not work like this if the loop in question is
part of a piped foreach
("%") statement.
If you try that, the dang code just dies right here and never proceeds to the next statement!
can’t load or run a script - see also scripts disabled
File C:\Scripts\ListDir.ps1 cannot be loaded because the execution of scripts is disabled on this system. Please see "get-help about_signing" for more details. At line:1 char:14 + .\ListDir.ps1 <<<< + CategoryInfo : NotSpecified: (:) [], PSSecurityException + FullyQualifiedErrorId : RuntimeException
From an elevated prompt:
Set-ExecutionPolicy Unrestricted
or better (restricted to only current user):
Set-ExecutionPolicy Unrestricted -Scope CurrentUser
Sometimes the command above won't work. It will likely complain about some more specific scope overriding your attempt.
Set-ExecutionPolicy : Windows PowerShell updated your execution policy successfully, but the setting is overridden by a policy defined at a more specific scope. Due to the override, your shell will retain its current effective execution policy of AllSigned.
To find out more, list all the different scopes:
Get-ExecutionPolicy -List
might return something like this:
Scope ExecutionPolicy
----- ---------------
MachinePolicy Undefined
UserPolicy Undefined
Process Restricted
CurrentUser Undefined
LocalMachine Unrestricted
More specific scopes like Process
override less specific scopes like CurrentUser
.
So we need to change the more inclusive Process
scope. Try this:
Set-ExecutionPolicy Bypass -Scope Process -Confirm
You may wonder: why not just set this
Process
scope to Unrestricted
as well?
But the system may not allow it. But setting it to Bypass
instead will probably be allowed.
case statement - see switch
can’t run scripts - see scripts disabled, can’t load or run a script
clipboard, send output of a command to
simply append your command with "| clip"
color of Write-Host
command - see also Write-Color
Write-Host "green color" -foreground "green"
multiple colors on one line
Write-Host "Green " -ForegroundColor Green -NoNewline; Write-Host "Red "-ForegroundColor Red -NoNewline; Write-Host "Yellow " -ForegroundColor Yellow
colors, show available
[enum]::GetValues([System.ConsoleColor]) | Foreach-Object {Write-Host $_ -ForegroundColor $_}
colors, multiple in one line - see Write-Color
shows each command, sequence and duration for the current session - most recent up top
Get-History | select id, CommandLine, StartExecutionTime, EndExecutionTime, @{n="duration";e={$_.EndExecutionTime - $_.StartExecutionTime}} | sort id -Descending | ogv
comment out a line - use "#". For a block of comments, "<#" at beginning of block followed by "#>" at end of block
concatenate - +
continue - see also break, exit, return
skip the current execution of the loop and to return the execution to the top of the innermost loop
contains, does a variable contain a substring?
if ($DisplayName -match "departed")
CSV, import into an object - see also text file, read into object, record for each field in a file, parse
$dir
=
[environment]::getfolderpath("mydocuments")
$docName
=
"$($dir)\someFile.csv"
$csv
=
Import-Csv
$docName
$i=0;
$count
=
$csv.Count
$result
=
@()
foreach
($item
in
$csv)
{
$i++; $percentTxt
= ($i/$count).ToString("P")
Write-Host
"$i
of
$($count)
($percentTxt): Name =
$($item.Name)
and email =
$($item.Email)"
-ForegroundColor Green
$result
+=
New-Object
-TypeName PSObject
-Property
@{
Name
=
$item.Name
Email
=
$item.Email}
}
$result
=
$result
|
sort Name
|
select Name,
Email
$result
| ogv
CSV, import special characters
Even though a CSV may look like it has special characters, doesn't mean those are actually stored as unicode that gets processed the right way.
$dir
= [environment]::getfolderpath("mydocuments")
$originalFileName
=
"$($dir)/input.csv"
$convertedFileName
=
"$($dir)/$((Get-Date).ToString('MM-dd-yyyy_hh-mm-ss'))inputConverted.csv"
Get-Content
$originalFileName
|
Out-File
$convertedFileName
-Encoding UTF8
Remove-Item
$convertedFileName
-recurse -force
$csv
=
Import-Csv
$convertedFileName
Foreach
($item
in
$csv){Write-Host
"$($item.Name) - $($item."email address")"
-ForegroundColor "green"}
Had the original "input.csv
"
file had what appeared to be special characters
and you merely "Import-Csv
"
on it and looped through using "foreach
"
without first "Get-Content
"
piped to "Out-File
"
with "-Encoding UTF8
",
you likely would have only seen unprintable character resembling a solid diamond
with a question mark in it for each of those special characters.
Notice that we immediately delete the intermdiate
$convertedFileNamefile
because we don't want it left around to clutter things up once we're done with it.
$myDate = [DateTime]"Jul-16"
date, include in file name - see timestamp, include in file name
digitally signed, ps1 file won't run
Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass
display value of a variable - simply put the variable in its own line. No write-host necessary:
$variable
disabled scripts - see scripts disabled
duplicate elements in an array, find - see array, duplicate elements - find
duration of last command - see time it took to run most recent command
edit scripts - powershell ISE (included with Windows 7, 8)
elapsed time - see time elapsed
list all
gci env:* | sort-object name
domain
$env:UserDomain
computer name
$env:ComputerName
path
$env:Path -split(";") | sort $_
user name
$env:UserName
or
whoami
equal - -eq()
error, expand
$error | Format-List -Force
error when running script - see can't load a script
even number, test for
1..20 | % {if ($_ % 2 -eq 0 ) {"$_ is even"}}
execution policy - see scripts disabled
exit - see also break, continue, return
terminates the current execution session altogether. It also closes the console window and may or may not close ISE.
exit from for loop -
if
$thing
-eq
'some_condition')
{
break
}
file, read into array – see text file, import into an object
$file
=
"someFile.htm"
$myDocs
= [environment]::GetFolderPath("MyDocuments")
$file
=
$myDocs
+
"\"
+
$file
$fileContent
=
Get-Content
$file
for
($i=
0;
$i
-lt
$fileContent.length;
$i++){
$fileContent[$i]
}
This is all well and good. But what if we really want an array of hashes? The following works good for CSVs
$csv=
Import-Csv
$inputfile
foreach($item
in
$csv)
{
"$($item.UserPrincipalName) - $($item.DisplayName)"
}
file name, include timestamp in - see timestamp, include in file name
filter timestamp {"$(Get-Date -Format G): $_"}
write-output "hello world" | timestamp
find whether elements of an array can be found anywhere in a string - see array, can elements of an array can be found anywhere in a string
foreign characters - see also special characters, CSV, import special characters
If a command exports users whose names
contain foreign characters into a CVS file, those foreign characters
will be replaced with a ?. To preserve those foreign
characters, use Export-Csv $outputfile -Encoding UTF8
Get-Content
$file
|
Out-File
$fileUTF8
-NoTypeInformation -Encoding UTF8
function, return more than one value – see Returning multiple values from a PowerShell function
function, invoke function residing outside file
Occasionally you may want to keep functionality in a file and maybe even directory outside of the script you're running rather than have to store those functions inside the script.
$directoryWithFunctions
=
"\\deathstar.galaxyfarfaraway.com\Infrastructure\"
.
"$($directoryWithFunctions)DestroyPlanetLaser.ps1"
cd
$directoryWithFunctions
Or the other way around:
cd
$directoryWithFunctions
.
".$($directoryWithFunctions)DestroyPlanetLaser.ps1"
greater than
-gt
greater than or equal
-ge
gridview - |
Out-GridView
or |
ogv
group by
Get-User | Group RecipientTypeDetails
hash, clear
$a.Clear()
hash, declare
$guestUsers = @{}
$guestUsers
=
@
@{email
=
'bob.smith@yourDomain.com';
DisplayName
=
"Bob Smith"}
@{email
=
'jim.jones@yourDomain.com';
DisplayName
=
"Jim Jones"}
@{email
=
'sally.hayes@yourDomain.com';
DisplayName
= "Sally Hayes"}
)
history of commands - see Command History
how long did the last command take to run? See time it took to run most recent command, Command History
-in operator – see also -notin operator
"orange" -in "orange","apple" # True
import text file into array - see text file, import into an object, record for each field in a file, parse, CSV, import into an object
'Install-Module' is not recognized
Start with Get-PackageProvider
Get-PackageProvider
Hopefully, you ought to get at least 3 rows, one of which ought to be PowerShellGet
.
If Get-PackageProvider isn't recognized, try Install-PackageProvider
Install-PackageProvider -Name NuGet -Force
invoke function residing outside file – see function, invoke function residing outside file
join members of an array together separated by character(s)
$groups = @("US Users","Staff","Big building")
$allGroups = ($replace | % {$groups}) -join ','
last command, how long did it take to run? - see time it took to run most recent command
less than - -lt()
less than or equal - -le()
line continuation - use the “grave accent” (`) mark.
Get-ChildItem
-Recurse `
-Filter *.jpg `
| Select LastWriteTime
However, this is only ever necessary in such cases as shown above. Usually you get automatic line continuation when a command cannot syntactically be complete at that point. This includes starting a new pipeline element:
Get-ChildItem
|
Select Name,Length
Similar to the | a comma will also work in some contexts.
strings (in all varieties) may also extend beyond a single line:
'foo
bar'
They include the line breaks within the string, then.
Function
Get-CurrentLine
{
$Myinvocation.ScriptlineNumber
}
Get-CurrentLine
$null
Get-CurrentLine
loop, percent progress through - see percent progress through a loop
loop - several types
For - read content of a file as in
$file
=
"someFile.htm"
$myDocs
= [environment]::GetFolderPath("MyDocuments")
$file
=
$myDocs
+ "\"
+
$file
$fileContent
=
Get-Content
$file
for
($i
=
0;
$i
-lt
$fileContent.length;
$i++){
$fileContent[$i]
}
ForEach - for “normal” arrays - see also array, loop through
ForEach-Object (or "%") for objects - you need to have the “{” on the same line right after the “ForEach-Object” or you’ll get prompted for:
cmdlet ForEach-Object at command pipeline position 2
Supply values for the following parameters:
Process[0]:
unlike the other flavors of “ForEach” and “While” which expect the “{” to be on the next line.
While - loop through the contents of a file or database query/table
continue - see also break, exit, return
loop, escape - break
(all by itself) - see break,
continue, exit, return
Keep in mind that this does not work like you'd expect if the loop in question
is part of a piped foreach
("%") statement.
If you try that, the dang thing just dies and never proceeds to the next statement after the loop!
lower case - see also proper case
append ".ToLower
" to string. For example:
$Username = "$($FirstName.Substring(0,1))$LastName".ToLower()
takes the first letter of $FirstName
variable and
appends to $LastName
and then puts whole thing lower case.
If you attempt to run some command like
Install-PackageProvider -Name "PowerShellGet"
or
Get-PSRepository
or
Get-InstalledModule
and get some error like this
PacketManagement\Find-Package: Unable to find module providers (PowerShellGet) At C:\Program Files\WindowsPowerShell\Modules\PowerShellGet\1.0.0.1\PSModules.psm1:1397 char:3
look under Documents\WindowsPowerShell folder for a "Modules" folder under that and then delete or rename that "Modules" folder to something like "ModulesOld" and try again. It should recreate that "Modules" folder. And now things might work better.
Modules installed
Gets installed modules on a computer:
Get-InstalledModule
Gets the modules that have been imported or that can be imported into the current session:
Get-Module
What's available:
Get-Module -ListAvailable
update a module:
Update-Module -Name someModule -Verbose
Sometimes you must know where a module is installed. Especially if you need to uninstall or import.
$AzureInstalled
=
Get-InstalledModule
|
Where-Object
{$_.Name
-like
'Azure*'}
$AzureInstalled
| select Name, InstalledLocation
Module providers
You may try to run a command like
Find-Module *ms*
and get an error
PacketManagement\Find-Package: Unable to find module providers (PowerShellGet) At C:\Program Files\WindowsPowerShell\Modules\PowerShellGet\1.0.0.1\PSModules.psm1:1397 char:3
or some such directory path, file & line number. Before you go chasing down that directory to make sure the module exists, run this command first to find out what Package Providers you have
Get-PackageProvider
You should get a list of package providers. If the one you want (PowerShellGet in this case) is missing, then try:
Install-PackageProvider -Name "PowerShellGet"
if this fails, see Module install attempt fails
Modulo operator (remainder in division)
if $i
below is 10, 20, 30, etc., the if
statement below will be true
if ($i % 10 -eq 0) {$i}
not
-not()
-notin operator – see also -in operator
"orange" -notin "orange","apple" # False
null, assign
sometimes you can assign the $null
variable.
Other times you must use the -clear
operator.
null, check if string is null
if
([string]::IsNullOrEmpty($mystring) {Write-Host
"string is NULL or EMPTY"}
else
{Write-Host
"string has a value"}
null, check if property is null when filtering
Normally, you can simply filter on
someProperty -ne
$null
.
But when trying to filter on some commands like
Get-AdUser
, problems because PowerShell doesn't recognize what the
$null
variable is in that context.
So instead, filter on -notlike "*"
.
Get-AdUser -filter (msExchHideFromAddressLists -notlike "*")} -Properties $Properties
Let's say you already have an object $objResult
with many fields,
one of whose fields is called "Source Workstation". To convert
this particular field to an array $PCs
:
$PCs = $objResult.("Source Workstation")
To get rid of dupes:
$PCs = $PCs | select -Unique
odd number, test for
1..20 | % {if ($_ % 2 -eq 1 ) {"$_ is odd"}}
or
-or
output results of a command to clipboard
simply append your command with "| clip"
percent progress through a loop
$employees
=
Get-Msoluser
-All
$i=0;
$count
=
$employees.Count
$employeesWithMailboxes
=
@()
foreach
($employee
in
$employees) {
$i++;
$percentTxt
= ($i/$count).ToString("P")
$displayName
=
$employee.DisplayName
$messagePrefix
=
"$i
of
$($count)
($percentTxt):
$displayName"
Write-Host
"$messagePrefix
now"
-ForegroundColor Green
}
PowerShell version - see also Windows version
Use the built in variable
$PSVersionTable
shows
Name Value
---- -----
PSVersion 5.1.17763.134
PSEdition Desktop
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0...}
BuildVersion 10.0.17763.134
CLRVersion 4.0.30319.42000
WSManStackVersion 3.0
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1
or
$PSVersionTable.psversion
gives version detail in table format
Major Minor Build Revision
----- ----- ----- --------
5 1 17763 134
Get-Host just shows you the version of the host (i.e. of Console.Exe or Visual Studio Code Host).
Name : Visual Studio Code Host
Version : 1.10.2
InstanceId : 7f3dd862-f8ce-49a2-b420-b44ccebc0053
UI :
System.Management.Automation.Internal.Host.InternalHostUserInterface
CurrentCulture : en-US
CurrentUICulture : en-US
PrivateData : Microsoft.PowerShell.EditorServices.EditorServicesPSHost+ConsoleColorProxy
DebuggerEnabled : True
IsRunspacePushed : False
Runspace :
System.Management.Automation.Runspaces.LocalRunspace
Or $Host.Version
will zero into more detailed version info
in a table format.
$Host.Version
Major Minor Build Revision
----- ----- ----- --------
1 10 2 -1
means you have Visual Studio Code Host version 1
progress through loop, percent - see percent progress through a loop
$words
=
'wAr aNd pEaCe'
$TextInfo
= (Get-Culture).TextInfo
$TextInfo.ToTitleCase($words)
if all caps:
$words
=
'WAR AND PEACE'
$TextInfo.ToTitleCase($words)
$TextInfo.ToTitleCase($words.ToLower())
property name has spaces - see spaces in property name
This example gets all properties of a folder:
Get-ItemProperty \\fs.jiminy.org\songs | Format-List -Property *
or
Get-ItemProperty \\fs.jiminy.org\songs | Get-Member | ? {$_.memberType -eq "Property"}
properties - sometimes you can just add Select-Object
.
But usually you need to add a Select-Object
As in:
Get-MsolUser -All | Select-Object UserPrincipalName, isLicensed, immutableID
read text file into array - see text file, import into an object, record for each field in a file, parse, CSV, import into an object
record for each field in a file, parse
Instead of getting one record with each field delimited by something like a comma as you would in a CSV, occasionally you get a separate record for each file. In the case below, we have two separate fields - “DisplayName” and “Department” - and each is on its own record. We need to gather these two fields together and put them all together in one record.
$dir
=
[environment]::getfolderpath("mydocuments")
$docName
=
"$($dir)/ticket1519133.txt"
$fileContents
=
Get-Content
-Path
$docName
$i=0;
$count
=
$fileContents.Count
$fieldCount
=
2
$result
=
@()
foreach
($line
in
$fileContents)
{
$i++;
$percentTxt
=
($i/$count).ToString("P")
if
($i
%
$fieldCount
-eq
1) {
$DisplayName
=
$line
} else {
$j
=
[math]::floor([decimal]($i/$fieldCount))
$jcount
=
[math]::floor($count/$fieldCount)
Write-Host
"$j
of
$($jcount)
($percentTxt):
$line"
-ForegroundColor Green
$result
+=
New-Object
-TypeName PSObject -Property
@{
"DisplayName"
=
$DisplayName
"Department"
=
$line
}
}
}
$result
=
$result
|
select
DisplayName,
Department
$result
|
ogv
remainder (as in division) - see modulo
PowerShell Replace Method And Operator: Syntax, Examples or How to Use PowerShell Replace to Replace Text [Examples]
Method - case sensitive
("Sad to see you").Replace("S","Gl")
you can also “chain” these together
("Sad to see you go").Replace("S","Gl").Replace("you go","you're back!")
Operator - not case sensitive
("Sad to see you") -Replace("S","Gl")
return - see also break, continue, exit
terminates execution of the current function and passes control to the statement immediately after the function call
return more than one value from a function – see function, return more than one value
Scripts disabled - see also can’t load or run a script
To see current policy:
Get-ExecutionPolicy
To change current policy:
Set-ExecutionPolicy RemoteSigned
But what if you get this?
Set-ExecutionPolicy :
Access to the registry key 'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell' is denied.
At line:1 char:1
+ Set-ExecutionPolicy RemoteSigned
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo :
NotSpecified: (:) [Set-ExecutionPolicy], UnauthorizedAccessException
+ FullyQualifiedErrorId :
System.UnauthorizedAccessException,Microsoft.PowerShell.Commands.SetExecutionPolicyCommand
Answer: run PowerShell as an administrator
spaces in property name - enclose with quotes as in
$_."IP Address"
spaces in string, trim – see white space, trim
special characters - see also CSV, import special characters, foreign characters
special characters, replace
[char[]]$replace
=
'!@#$%^&*(){}[]":;,<>/|\+=`~
'''
$regex
=
($replace
|
%
{[regex]::Escape($_)})-join
'|'
cd
'D:\test
Get-ChildItem
-recurse |
ForEach
{
if ($_.Name -match
$RegEx){
Ren $_.Fullname -NewName $($_.Name -replace $RegEx, '_') -whatif
}
}
if ($DisplayName
-match
"departed")
or
[char[]]$replace = '!@#$%^&*(){}[]":;,<>/|\+=`~ '''
$regex = ($replace | % {[regex]::Escape($_)}) -join '|'
Get-ChildItem -recurse | Where-Object { $_.Name -match $RegEx} | Rename-Item -NewName {$_.Name -replace $RegEx, '_'} -whatif
sort -
Get-EventLog system -newest 5 | Sort-Object eventid
Get-MsolUser -All | Sort-Object -property UserPrincipalName
If you want to sort stuff descending, add the -Descending
argument
Get-SPOSite | select Url, StorageUsageCurrent, WebsCount | sort StorageUsageCurrent -Descending | ft
If you want to sort stuff descending and ascending, need to do things a little differently
Get-SPOSite | select Url, StorageUsageCurrent | sort @{expression="StorageUsageCurrent";Descending=$true},@{expression="Url";Ascending=$true} | ft
string, how many instances - see Counting the number of occurrences of a string or file in PowerShell
"OU=Pumpkin Patch,DC=farms,DC=Dogpatch,DC=gov" -split ",DC=" | measure | select -exp count
If you expect these strings to always be in the middle somewhere, then subtract 1. Because the example above returns 4 because that's how many substrings result from the split - even though there are only 3 instances of the string we're searching.
string, find just one
$s = "New York City"
"New","Old" | %{ if ($s.contains($_)) { "$s contains $_" }}
string, find if any of several match - see also string, how many instances
$ignoreDirectories
=
@("SYSVOL","#recycle","SysStates","LogsConfig")
if(Select-String
-InputObject $filename
-pattern $ignoreDirectories)
{
Write-Host
"ignore"
$filename
}
“-match” also works but is usually used to find match in an array
string, can elements of an array can be found anywhere in - see array, can elements of an array can be found anywhere in a string
string, find files that contain in a directory
if you're already in the directory you want to search:
Get-ChildItem -recurse | Select-String -pattern "something went wrong" | group path | select name
if you're not already in the directory you want to search, you can try this. You might get permission complaints, though:
Select-String -Path C:\inetpub\wwwroot -pattern "something went wrong"
string, find whether it is in an array - array, find string as a member of
string, replace
$a = $a -replace "one", "two"
substring - see also string, how many instances
append ".Substring(start position, number of characters)
" to string. For example:
$Username = "$($FirstName.Substring(0,1))$LastName".ToLower()
takes the first letter of $FirstName
variable and
appends to $LastName
and then puts whole thing lower case.
switch statement - same as the “case” statement in other languages - see here
term 'xx' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again. (Exchange)
for example:
get-mailbox -ResultSize Unlimited
returns:
get-mailbox : The term 'get-mailbox' is not recognized as the name of a cmdlet,
function, script file, or operable program. Check the spelling of the name, or if a path was included,
verify that the path is correct and try again.
At line:1 char:1
+ get-mailbox -ResultSize Unlimited
+ ~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (get-mailbox:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
need to run:
add-pssnapin *exchange* -erroraction SilentlyContinue
text file, import into an object - see also CSV, import into an object, record for each field in a file, parse
$dir
=
[environment]::getfolderpath("mydocuments")
$docName
=
"$($dir)\textToImport.txt"
$fileContents
=
Get-Content
-Path
$docName
$i=0;
$count
=
$fileContents.Count
$result
=
@()
foreach($line
in
$fileContents)
{
$i++;
$percentTxt
=
($i/$count).ToString("P")
Write-Host
"$i
of
$($count)
($percentTxt):
$line"
-ForegroundColor Green
$result
+=
New-Object
-TypeName PSObject
-Property
@{
line
=
$line}
}
$result
| ogv
the best way to see how long recent commands took to run that I've found so far:
Get-History | select id, CommandLine, StartExecutionTime, EndExecutionTime, @{n="duration";e={$_.EndExecutionTime - $_.StartExecutionTime}} | sort id -Descending | ogv
loop example
$startTime
= $(Get-Date)
Write-Host
"Elapsed:00:00:00"
$NoEvent
=
$true
While
($NoEvent)
{
Start-Sleep
1
$elapsedTime
=
New-TimeSpan
$startTime
$(Get-Date)
Write-Host
"Elapsed:$($elapsedTime.ToString("hh\:mm\:ss"))"
#Handle event
if(event){$NoEvent
=
$false}
}
or use the .NET Stopwatch class
$Time
= [System.Diagnostics.Stopwatch]::StartNew()
$NoEvent
=
$true
while
($NoEvent) {
$CurrentTime
=
$Time.Elapsed
Write-Host
$([string]::Format("`rTime: {0:d2}:{1:d2}:{2:d2}",
$CurrentTime.hours,
$CurrentTime.minutes,
$CurrentTime.seconds)) -nonewline
Sleep 1
#Handle event
if(event){$NoEvent
=
$false}
}
time it took to run most recent command - see also Command History
(Get-History)[-1].EndExecutionTime - (Get-History)[-1].StartExecutionTime
how long it took each of the previous 10 commands to run
for
($i
=
-1;
$i
-gt
-10;
$i--){
$duration
= (Get-History)[$i].EndExecutionTime - (Get-History)[$i].StartExecutionTime
"duration for event $($i):
$duration"
}
timestamp - see filter timestamp example
(Get-Date).ToString("MM/dd/yyyy hh:mm:ss tt")
timestamp, include in file name
$outFile = "baseFileName_{0:yyyyMMdd-HHmm}.csv" -f (Get-Date)
or if you don't want to mess with a variable and want to send to the My Documents folder
Get-AdUser | Export-Csv -Path "$([environment]::getfolderpath("mydocuments"))\fileBaseName$((Get-Date).ToString('MM-dd-yyyy_hh-mm-ss')).csv" -NoTypeInformation -Encoding UTF8
title case - see proper case
tools
ISESteroids - add-on for the Windows PowerShell ISE editor
top 5 - add following to any command: | Select-Object -First 5
trim – see also white space, trim
" first last ".Trim()
try/catch - will suppress system error message but
instead keep going and show error of your choice (and highlight just
the pertinent part of the error message with back color
if you have Write-Color
module installed)
$dir
= [environment]::getfolderpath("mydocuments")
$docName
=
"$($dir)/my.csv"
$csv
=
Import-Csv
$docName
foreach
($item
in
$csv)
{
try
{
$user
=
Get-MsolUser
-UserPrincipalName
$item.UserPrincipalName
Write-Host
"$($item.DisplayName)
/
$($item.UserPrincipalName)
found"
-ForegroundColor Green
}
catch
{
Write-Color
-T
"$($item.DisplayName)
/
$($item.UserPrincipalName)
",
"not
found!"
-C Blue, Red -B Black, DarkYellow
}
}
I've never been able to get try/catch to work properly with
Get-Mailbox
failure - see
Get-Mailbox
failure for work-around
upper case - see also proper case
append ".ToUpper
" to string
user name environment variable - see environment variables
variable name has spaces - see spaces in property name
winget install Microsoft.PowerShell
if that fails:
Invoke-Expression "& { $(irm https://aka.ms/install-powershell.ps1) } -UseMSI"
As far as I can tell, this doesn't allow you to specify a version. Whether you want it or not, it's 7. But you can cancel it before it finishes.
… Windows
Visual Studio, install
Install-Script Install-VSCode -Scope CurrentUser; Install-VSCode.ps1
Visual Studio, shell setting, default - go to File → Preferences → Settings
Integrated Terminal
// Place your
settings in this file to overwrite default and user settings.
{
"terminal.integrated.shell.windows": "\\windows\\system32\\WindowsPowerShell\\v1.0\\powershell.exe"
}
or 64-bit PowerShell
"terminal.integrated.shell.windows": "C:\\WINDOWS\\Sysnative\\WindowsPowerShell\\v1.0\\powershell.ex"
check if 64-bit:
[Environment]::is64bitProcess
should return True
#
Expected to remove leading and trailing two spaces.
(" Test
").Trim()
#Expected to remove the leading two spaces and carriage
return and newline characters.
(" Test`r`n").Trim()
# Expected to remove the leading two spaces and
trailing Unicode Next Line character.
(" Test
Test $([Char]0x0085)").Trim()
whoami
# Install from Powershell Gallery
https://www.powershellgallery.com/packages/PSWriteColor
Install-Module
-Name PSWriteColor
Import-Module
PSWriteColor
tabs and vertical space
Write-Color
-Text
"This is text
in Green ",
"followed by red ",
"and then we have Magenta... ",
"isn't
it fun? ",
"Here goes DarkCyan"
-Color Green, Red, Magenta, White, DarkCyan -StartTab
3
-LinesBefore
1
-LinesAfter
1
with background colors and aliases
Write-Color -T "My text", " is ", "all colorful" -C Yellow, Red, Green -B Green, Green, Yellow
xml, parse
If you include a line like this in your DNS:
_dmarc 3600 IN TXT v=DMARC1; pct=100; p=none; rua=mailto:someUser@yourDomain.com
you'll get XML records mailed to you from various email providers such as yahoo & google. The code below will get some of the columns; not all columns fetched for simplicity's sake.
$dir
= [environment]::getfolderpath("mydocuments")
$fileNameOnly
=
"google.com!youdDomain.com!1556064000!1556150399.xml"
$fileName
=
"$dir\$fileNameOnly"
[xml]$xml
=
Get-Content
-Path
$fileName
$xml_row
=
$xml.SelectNodes("//row")
$objResult
=
@()
foreach
($row
in
$xml_row) {
$rowRecord
=
$row
| select
@{n='sourceIP';e={$_.source_IP}},@{n='DKIM';e={$_.policy_evaluated.dkim}},@{n='spf';e={$_.policy_evaluated.spf}}
$objResult
+=
$rowRecord
}
$objResult | ogv