Table of Contents
list inactive users
List all inactive users
Search-ADAccount -AccountInactive | where {$_.ObjectClass -eq 'user'} | Format-Table -wrap -A Name,SamAccountName,LastLogonDate | Out-File Z:\sandbox\inactiveusers.txt -Encoding ascii
List all inactive users older than 1 year
Search-ADAccount -AccountInactive -TimeSpan | where {$_.ObjectClass -eq 'user'} | Format-Table -wrap -A Name,SamAccountName,LastLogonDate | Out-File Z:\sandbox\inactiveusers.txt -Encoding ascii
Apply remote allowed settings to Advanced Firewall Rules to license4.aoe.vt.edu
set-executionpolicy unrestricted (bad, use remote signed instead)
$List1 = @("128.173.188.0/16","198.82.0.0/16","172.16.0.0/12","2001:468:c80::/48","2607:b400::/40","2002:80ad::/32","2002:c652::/32")
$List2 = @("192.168.50.0/24")
#STK License Server Daemon UDP
Set-NetFirewallRule -DisplayName "STK License Server Daemon UDP" -RemoteAddress $List1
Set-NetFirewallRule -DisplayName "STK License Server Daemon TCP" -RemoteAddress $List1
Set-NetFirewallRule -DisplayName "STK License Manager vendor daemon UDP" -RemoteAddress $List1
Set-NetFirewallRule -DisplayName "STK License Manager vendor daemon TCP" -RemoteAddress $List1
Set-NetFirewallRule -DisplayName "PHX License Server Daemon UDP" -RemoteAddress $List1
Set-NetFirewallRule -DisplayName "PHX License Server Daemon TCP" -RemoteAddress $List1
Set-NetFirewallRule -DisplayName "PHX License Manager vendor daemon UDP" -RemoteAddress $List1
Set-NetFirewallRule -DisplayName "PHX License Manager vendor daemon TCP" -RemoteAddress $List1
Set-NetFirewallRule -DisplayName "Mathcad License Server Daemon UDP" -RemoteAddress $List1
Set-NetFirewallRule -DisplayName "Mathcad License Server Daemon TCP" -RemoteAddress $List1
Set-NetFirewallRule -DisplayName "Mathcad License Manager vendor daemon UDP" -RemoteAddress $List1
Set-NetFirewallRule -DisplayName "Mathcad License Manager vendor daemon TCP" -RemoteAddress $List1
Set-NetFirewallRule -DisplayName "Intel FlexNet Publisher* License Server Daemon UDP" -RemoteAddress $List1
Set-NetFirewallRule -DisplayName "Intel FlexNet Publisher* License Server Daemon TCP" -RemoteAddress $List1
Set-NetFirewallRule -DisplayName "Intel(R) Software* License Manager vendor daemon UDP" -RemoteAddress $List1
Set-NetFirewallRule -DisplayName "Intel(R) Software* License Manager vendor daemon TCP" -RemoteAddress $List1
Random notes including stuff from Lynda.com PowerShell 5 Essential Training
netsh is the older command that works on windows 7 and might get dropped in future releases.
netsh interface ipv6 6to4 set state disabled netsh interface teredo set state disabled netsh interface ipv6 isatap set state disabled
Windows 8.1 and up can use Get-NetAdapter which is a little easier to work with:
Get-DnsClientServerAddress
Get-NetAdapter | SELECT name, status, speed, fullduplex | where status -eq ‘up’ Get-NetIPConfiguration | select InterfaceAlias, IPv4Address | where InterfaceAlias -eq 'Ethernet' (replace with result from above.)
Get-NetAdapter | where status -eq 'up' | Get-NetIPAddress -ea 0 | where AddressFamily -eq 'IPv4' | select IPAddress | Where {$_.IPAddress -like "128.173.*" -OR $_.IPAddress -like "198.82.*"}
The -ea is an error action switch. Zero means continue silently. Might not be needed.
if the address begins with 128.173 or 198.82, then set these DNS settings:
netsh interface ip set dns “Local Area Connection” static 128.173.188.25 netsh interface ip set dns “Local Area Connection” static 128.173.188.26 netsh interface ipv6 set dns “Local Area Connection” static 2001:468:c80:610c:ccfb:66e9:490f:d18 netsh interface ipv6 set dns “Local Area Connection” static 2001:468:c80:610c:d1cd:8142:30a:3a7a
Save Configuration:
netsh interface dump > mycfg.dat
Restore Configuration:
netsh exec mycfg.dat
Works with ps3:
Get-WmiObject win32_networkadapterconfiguration IPEnabled,DNSServerSearchOrder -Filter IPEnabled=True IPAddress
Get-WmiObject win32_networkadapterconfiguration IPEnabled,DNSServerSearchOrder,IPAddress | ? {$_.IPEnabled=True}
$adapter = Get-WmiObject win32_networkadapter -Filter ‘index = 13’ $adapter.NetConnectionID
Get-WmiObject -Class Win32_NetworkAdapter | Get-Member Get-WmiObject -Class Win32_NetworkAdapter -Filter NetEnabled=TRUE NetConnectionID
Lynda.com Powershell training notes:
Get-ChildItem is dir or ls and has an alias of gci.
get-service -name "*net*"
get-service | out-file c:\services.txt
get-command
get-help get-childitem
get-help has an alias of gh
get-service | where-object {$_.status -eq "stopped"}
get-service | get-memeber
Create a function:
function add <then hit enter>
>>> {
>>> $add =[int](2+2)
>>> write-output "$add"
>>> }
add
-whatif tells what would happen if the command runs
-confirm allows the operation on each object to get a y/n/etc prompt
ise (brings up Integrated Scripting Environment)
get-service | format-list displayname, status, requiredservices get-service | format-table displayname, status required get-service | sort-object -property status | format-list get-service | sort-object -property status | format-list displayname, status, requiredservices
get-service | outfile c:\services.txt get-service | export-csv c:\services.csv
in the ISE, highlight highlighted text can be run individually
Grid View
get-service | out-gridview get-service | select-object displayname, status, requiredservices | out-gridview get-service | select-object * | out-gridview
Modules
get-module -listavailable import-module -name applocker get-command -module applocker
Module creation
Save script as .psm1
Import-Module ./Diskinfo.psm1 -force -verbose
cat Env:\PSModulePath
Put file in the User location returned. The location will need to be created.
$env:PSModulePath
or separated
$env:PSModulePath -split ";" C:\Users\stedwar1\Documents\WindowsPowerShell\Modules C:\Windows\system32\WindowsPowerShell\v1.0\Modules\
Use only the user area to put modules
get-help *diskinfo* #Listed as a function
execution policy
get-executionpolicy set-executionpolicy restricted #default setting
Set the following to execute:
Set-ExecutionPolicy RemoteSigned Set-ExecutionPolicy Restricted powershell -ExecutionPolicy ByPass -File script.ps1
Signing
Set-AuthenticodeSignature .\diskinfo.ps1 $cert -TimestampServer http://timestamp.comodoca.com/authenticode
Get-AuthenticodeSignature .diskinfo.ps1 | format-list
dir cert:\CurrentUser -Recurse -CodeSigningCert -OutVariable a $a $cert = $a[0]
Test.ps1
write-Output "Hello world"
set-executionpolicy allsigned
Now the code will not run
set-authenticodesignature -certificate $cert -filepath ./Test.ps1 cat ./Test.ps1 # will now have a big signature appended to the file get-help about_signed
Windows feature
get-windowsfeature get-windowsfeature -name web-server get-windowsfeature -name web-server | install-windowsfea...
Example scripts
Microsoft scriptcenter https://gallery.technet.microsoft.com/scriptcenter/
Aliases
To see the aliases:
get-alias
To see what an alias does:get-alias ls
get-alias dir get-alias cls
Update Help
First update help, and do it often
update-help -force
Basic commands
get-verb
help
get-help *array* get-help about* get-process get-help get-process get-help get-process -detailed get-help get-process -examples get-help get-process -full (same as detailed with additional usage information) get-help get-process -showwindow get-help get-process -detailed get-help get-process -online get-verb
extensions
get-pssnapin get-module -ListAvailable
get-command -Module activedirectory
find-module install-module psreadline import-module psreadline (needs script execution: set-executionpolicy remotesigned)
find-package
Command examples
get-childitem -Path c:\ -filter *.txt* get-help *content* (also cat and type are aliases for get-content) get-content -path c:\filename.txt
get-eventlog -list get-eventlog -logname security -entrytype error -newest 5
Export to XML
Compare process states
get-process | export-clixml -path c:\gold.xml import-clixml c:\gold.xml calc; notepad; mspaint compare-object -referenceobject (import-clixml c:\gold.xml) -differenceobject (get-process) -property processname
Export to HTML
get-eventlog -logname system -newest 2 -entrytype error | convertto-html -title "Windows Errors" -body (get-date) -precontent "<p>Generated by IT</p>" -postcontent "For more details check the full server log" | out-file \\webserver\c$\c:\error.html ./error.html
Get-Member
get-service | get-member get-service | gm get-process | gm
From Get-Member information, we can derive these:
get-service -name bits | select-object -property name,status,machinename | format-table -autosize get-service -name bits -computername dc,s1, client| select-object -property name,status,machinename | format-table -autosize
get-service | select-object -Property name, status | sort-object -Property status -descending
changing column heading names
get-service -name bits | select-object -property name, @{name="ServiceName";expression={"hello"}}
get-service -name bits | select-object -property name, @{name="ServiceName";expression={$_.name}}
get-service -name bits | select-object -property @{name="ServiceName";expression={$_.name}}, status
get-service -name bits | select-object -property @{n="ServiceName";e={$_.name}}, status
get-wmiobject -class wind32_logicaldisk -filter "DeviceID='c:' " | select-object -property DeviceID,
@{n="FreeGB";e={$_.Freespace / 1gb -as [int] }}
Script file with parameter
<#
.Synopsys
This is the short explanation
.Description
This is the long explanation
.Parameter ComputerName
The remote computers to run the command on
.Example
DiskInfo -computername remote
This is a remote computer
.Example
DiskInfo remote
#>
function Get-diskinfo{
[CmdletBinding()]
param(
[parameter(Mandatory=$True)]
[sting[]]$ComputerName
$bogus='localhost'
)
get-wmiObject -computername $ComputerName -class wind32_logicaldisk -filter "DeviceID='c:' "
}
Source the function
. ./Diskinfo.ps1
To make the function stick around
Now the function is accessible to the command line:
Get-diskinfo -Computername dc -OutVariable a $a
Works with tab complete and get-help.
Code Formating
Line breaks can occur at commas, pipes and a few other places
selecting
get-service | where-object -filterscript {}
basic comparison
case insensitive
"Hello" -eq "hello" true
case sensitive
"Hello" -ceq "hello" False "Hello" -ceq "Hello" True
get-service | where-object {$_.status -eq "Stopped" -and $_.name -like "b*" }
more effecient to filter further left:
get-service -name b* | where-object { $_.
get-wmiobject -filter
... | where-object -filterscript {}
... | where-object {}
GPO settings
GPO: Policies, Administrative Templates, Windows Components, Windows PowerShell
Variables
get-eventlog -logname system -newest 5 -entrytype error
# variable as an object $var=get-service -name bits $var.status $var.name $var.start $var.status #(still references initially saved state) $var.refresh() #(updates the variable reference) $var.status
get-help *variable* get-variable
# variable as string $var="hello!" write-output $var $var
# variable as an array $var=1,2,3,4 $var 1 2 3 4 $var[1] 2 $var[1]=9 $var 1 9 3 4 $var[-1] #(last one in array)
$var=read-host "Enter a computerName" $var
Automatic help generation
<#
.Synopsis
Lynda.com example
.Description
Disk Information
.Parameter ComputeName
This is the name of a remote computer
.Example
diskinfo -computername localhost
.Example
diskinfo -computername DC
#>
param(
[parameter(Mandatory=$true)]
[string[]]$computername='DC',
$NotForUse
)
# Main Code here
Get-CimInstance -computername $computername -ClassName win32_logicaldisk -filter "deviceID='c:'" |
Select-Object -Property @{n="ComputerName";e={$_.PSComputername}},
@{n="FreeGB";e={$_.Freespace /1gb -as [int]}}
snippets
Use control-j to bring up a list of snippets. Also found under Edit > Start snippets.
Remote Administration
get-service -computername DC #refers to the old DCOM communications method
Enable-PSRemoting Enter-PSSession -ComputerName dc
Invoke-Command -ComputerName dc,s3,s4 -ScriptBlock {Get-service -name bits} | outfile c:\service.txt
Once the session ends, the shell is closed.
To keep the session open:
$sessions=New-PSSession -computerName s3,s4
Invoke-Command -Session $sessions {$var=2}
Invoke-Command -Session $sessions {write-output $var} #this would not be possible without the session.
Get-pssession
measure-command {icm -Computername dc {get-process}}
measure-command {icm $sessions {get-process}}
get-windowsfeature #lists all installed components
$servers='s3','s4'
$servers | foreach-object {start iexplore http://$_} #checks to see if webserver is running on each server
$sessions=New-PSSession -computername $servers
invoke-command -session $sessions {install-windowsfeature web-server}
$servers | foreach-object {copy-item ./default.htm -destination \\$_\c$\inetpub\wwwroot}
On a minimal server, the gui can be installed thus:
get-windowsfeature *gui* | install windowsfeature
Active directory tools can be used from the DC without installing RSAT on the local machine.
get-adcomputer -filter * #fails unless RSAT is installed get-module -listavailable #show active directory is not installed $adsession=new-pssession -computername dc import-pssession -session $adsession -Module ActiveDirectory #imports links to the commands
This will link to the modules remotely (implicit remoting)
get-adcomputer -filter * #will now work
To get specifice pieces:
Import-pssession -session $adsession -Module ActiveDirectory -Prefix remote
A profile can be created that will set up the links each session
$profile #shows existing profile location new-item $profile -itemtype file -force #force will overwrite if it already exists ise $profile
Add the lines (same as above)
$adsession=new-pssession -computername dc import-pssession -session $adsession -Module ActiveDirectory
or to put something in the name of the commands
Import-pssession -session $adsession -Module ActiveDirectory -Prefix remote get-help *remote* get-remoteADcomputer -filter * get-help get-process get-command get-process $c=get-command get-process $c.Parameters $c.Parameters["Name"]
The above are functions that point to the machine where the commands run
get-command get-*ADcomputer #retuns a cmdlet and function (get-command get-remoteAdcomputer).definition (get-command ./GetAOE-DNS.ps1).scriptblock $s = nsn Import-PSSession $s -CommandName get-process -Prefix wow get-wowprocess
invoke-command -ComputerName dc,s1,s2 {get-eventlog -Logname System -new 3} | sort timewritten | formtat-table -Property timewritten, message -Autosize
icm dc,s1,s2 {get-volume} | sort Sizeremaining | select -Last 3
invoke command comparison
Let's Powershell handle concurrency control - creates three lists: Todo, in-progress, Done. A sliding buffer. This is preferable because the second one will wait on a stalled server before proceeding.
invoke-command -ComputerName (get-content servers.txt) { }
Serially loops through the list of servers and issues the Invoke-Command
foreach ($s in (Get-Content servert.txt) ) { Invoke-Command -ComputerName $s {}}
remote powershell through a web browser
On server:
enter-PSSession <computer name> get-windowsfeature install-windowsfeature windowspowershellwebaccess get-help *pswa* install-pswawebapplication -usetestcertificate add-pswaauthorizationrule * * * #DO NOT DO THIS ON A REAL SERVER. use get-help and set the groups properly.
More Information
Books:
Learn Windows PowerShell in a Month of Lunches
Learn PowerShell Toolmaking in a Month of Lunches
Free ebooks: https://powershell.org/ebooks/
microsoftvirtualacademy.com
Jeffrey Snover is the inventory of PowerShell “getting started with Microsoft PowerShell”
MSVA Getting Started with Microsoft Powershell v3.0
Casting XML to an object variable
$x = [xml](cat ./r_and_j.xml) $x $x.gettype $x.PLAY.Act[0].SCENE[0].SPEECH $x.PLAY.Act.SCENE.SPEECH $x.PLAY.Act.SCENE.SPEECH | select -First 1 $x.PLAY.Act.SCENE.SPEECH | group speaker | sort count
History
get-history
Where-Object
Where-object v2 method
get-service | where-object -FilterScript {$_.status -eq "Running"}
get-service | where {$_.status -eq "Running"}
get-help *comparison*
get-help *operators*
Where-object v3 method
get-service | where {$PSItem.status -eq "Running" }
mixed
get-service | where {$PSItem.status -eq "Running" -and $_.name -like "b*" }
Simplified version
get-service | where handles -ge 1000
Advanced Piping
Sending pipe needs to have a receiving equivalent—By-Value (TypeName) first then By-PropertyName
get-member shows TypeName: at the top of the results.
The types should match
get-service | stop-process
don't match but it will fall back to byName
get-service | gm
is type ServiceController
get-help stop-process
has (-showwindow and search for byvalue)(or search for
- InputObject <Process[]>
that accepts pipeline input byValue as Process
get-help
get-service | stop-process -whatif
will not find the By-Value that matches ServiceController but it will find name
calc get-process calc
get-process has a path and dir takes a path:
get-process calc | dir
Another example with an AD controller
get-adcomputer -filter * | get-service -name bits
This works, but the columns are meaninless
get-service -name bits | select -Propery naem, stitus
Hash table syntax
get-service -name bits | select -Propery name, @{name='ComputerName';expression={$_.name}}
get-service -name bits | select -Propery name, @{n='ComputerName';e={$_.name}}
The old way uses lowercase l (L) and/or Label for name which was confused with 1 (one).
So, to hook up two pipes that don't ordinarily have common paramerters:
get-adcomputer -fileter * | select -property @{n='ComputerName';e={$_.name}} | get-service -name bits
Wmi example. Get-WmiObject does not take pipeline input:
get-wmiobject -class win32_bios get-wmiobject -class win32_bios -ComputerName dc,s3
get-adcomputer -filter * | get-wmiobject -class win32_bios get-adcomputer -fileter * | gm get-help get-wmiobject -full #has no pipeline input get-adcomputer -filter * | select -ExpandProperty name #give just the names get-wmiobject -class win32_bios -ComputerName (get-adcomputer -filter * | select -ExpandProperty name).name get-wmiobject -class win32_bios -ComputerName (get-adcomputer -filter * ).name
Updated method that uses pipeline input
get-help get-CimInstance
Script parameters
get-adcomputer -filter * | get-wmiobject -class win32_bios -ComputerName {$_.name}
output
Send data to the terminal, but not the pipeline
write-host
Send data to the terminal and the pipeline
write-output
Yellow text by default
write-warning "Please don't do that"
Red text
write-error "Stop touching me!"
1..5
1..5 > $test.txt
${z:\sandbox\test.txt}
${z:\sandbox\test.txt} = "New file data overwites old file data!"
${z:\sandbox\test.txt} = ${z:\sandbox\test.txt} + "New file data appended."
Network Adapter
Using WMI
Get-NetworkAdapterStatus.ps1
<#
.Synopsis
Produces a listing of network adapters and status on a local or remote machine.
.Description
This script produces a listing of network adapters and status on a local or remote machine.
.Example
Get-NetworkAdapterStatus.ps1 -computer MunichServer
Lists all the network adapters and status on a computer named MunichServer
.Example
Get-NetworkAdapterStatus.ps1
Lists all the network adapters and status on local computer
.Inputs
[string]
.OutPuts
[string]
.Notes
NAME: Get-NetworkAdapterStatus.ps1
AUTHOR: Ed Wilson
LASTEDIT: 1/10/2014
KEYWORDS: Hardware, Network Adapter
.Link
Http://www.ScriptingGuys.com
#Requires -Version 2.0
#>
Param(
[string]$computer= $env:COMPUTERNAME
) #end param
function Get-StatusFromValue
{
Param($SV)
switch($SV)
{
0 { " Disconnected" }
1 { " Connecting" }
2 { " Connected" }
3 { " Disconnecting" }
4 { " Hardware not present" }
5 { " Hardware disabled" }
6 { " Hardware malfunction" }
7 { " Media disconnected" }
8 { " Authenticating" }
9 { " Authentication succeeded" }
10 { " Authentication failed" }
11 { " Invalid Address" }
12 { " Credentials Required" }
Default { "Not connected" }
}
} #end Get-StatusFromValue function
# *** Entry point to script ***
# PowerShell 2.0
Get-WmiObject -Class win32_networkadapter -computer $computer |
Select-Object Name, @{LABEL="Status";
EXPRESSION={Get-StatusFromValue $_.NetConnectionStatus}}
# PowerShell 3.0
Get-CimInstance -ClassName win32_networkadapter |
Select-Object Name, @{LABEL="Status";
EXPRESSION={Get-StatusFromValue $_.NetConnectionStatus}}
Using Net-Adapter (Windows 8 and 8.1)
Get-NetAdapter
Reduce to Physical
Get-NetAdapter -physical
Now only the “Up” adapter
Get-NetAdapter -physical | where status -eq 'up'
Twitter #powershell @jsnover
MVA - Scripting Toolmaking
Get code from powershell.org: https://powershell.org/2013/07/29/mva-powershell-jumpstart-2-scripts-for-aug-1st/
Invoke-Item to open current location
ii .
Unblock file to unblock files from execution since the example scripts are blocked from execution
unblock-File *\* -Verbose
Variables
Variables with spaces can be wrapped in {}
$MyVar=2
${My Var}="Hello"
${My Var}
User Write-Output in scripts
Write-Output $MyVar
Control variable type to help generate proper help
[string]$MyName="Steve" [int]$Oops="string" # failed by design $x = [int]"1" #casts 1 to an integer $x = "test" #assumes string and changes the type of the var [int]$x = "1" #types the variable as int
Stores date as a string of characters
$d = “9/19/2017” Intelesense or gm will give string functions
Store date as date/time object
[datetime]$d = "9/19/2017"
Will give different properties, methods and functions
$d.dayofweek $.AddDays(- (7*6))
Validate variable data to only a, b or c:
[validateset("a","b","c")][string]$x = "a"
Quote strength
Double quotes will resolve variables and single will not. To print a $, escape it with a backtick
"This is the variable $i, and $i Rocks!" #prints the variable contents 'This is the variable $i, and $i Rocks!' #prints the variable name exactly as in the single quootes "This is the variable `$i, and $i Rocks!" #prints the first variable name and resolves the second one
Variable expansion
$p = get-process lsass "Process id = $($p.id)" "Process id = $(read-host "What should I give them?")"
HERE strings
“HERE string” is a multiline string. Snipits use them, which can be user created.
@' #begin string # end of string '@
Use a HERE string to create an ISE code snipit by assigning the HERE contents to a variable and running the assignment command in ISE (select code and run selection). Search for snipit in the command window and select New-IseSnipit. Then put the variable name in the Text* file of the snipit and run the snipit command.
Sub expressions
$Msg="Service Name is $($service.name.ToUpper())"
Range Operator
1..5 5..1 1..-1 #Goes to the end of the array
Parenthesis
Do what is inside the parethesis first.
get-service -computername (import-csv c:\computers.csv | select -expandproperty computername)
PS v3:
get-service -computername (import-csv c:\computers.csv).computername
To just the names, use expandproperty
import-csv c:\Computers.csv | select-object -expandproperty computername
Logical Constructs (if, then)
if
If ($this -eq $that) {
# commands
} elseif ($those -ne $them) {
# commands
} elseif ($we -gt $they) {
# commands
} else {
# commands
}
$y = if ($false) {“1”} else {“2”}
Switch
Switch ($status) {
0 { $status_text = 'ok' }
1 { $status_text = 'error' }
2 { $status_text = 'jammed' }
3 { $status_text = 'overheated' }
4 { $status_text = 'empty' }
default { $status_text = 'unknown' }
}
$status_text = Switch ($status) {
0 { 'ok' }
1 { 'error' }
2 { 'jammed' }
3 { 'overheated' }
4 { 'empty' }
default { 'unknown' }
}
Looping Constructs
Do
# Do loop
$i= 1
Do {
Write-Output "PowerShell is Great! $i"
$i=$i+1 # $i++ # i+=2 # $i--
} While ($i -le 5) #Also Do-Until
While
# While Loop
$i=5
While ($i -ge 1) {
Write-Output "Scripting is great! $i"
$i--
}
For, For Each, ForEach-Object
$services = Get-Service
ForEach ($service in $services) {
$service.Displayname #$item would be a good variable or $s is even easier to read.
}
#For loop
For ($i=0;$i –lt 5;$i++) {
#do something
}
#Another way
1..5 | ForEach-Object -process { # abbreviated with a percent sign %
Start calc
}
Template
Code blocks can run just at the begining and end, but process blocks on each object passed to the function
<#
Comment based help
#>
Function Verb-Noun {
[CmdletBinding()]
Param(
[Parameter()][String]$MyString,
[Parameter()][Int]$MyInt
)
Begin{<#Code#>}
Process{<#Code#>}
End{<#Code#>}
}
Parameters
switch
Switch parameters allows -switches to be evaluated.
Powershell generally uses only singular variable names because English plurality rules are irregular.
write-verbose requires the -verbose switch to be added to get any output
The @{ } is a hash table which that allows custom field names to be applied, but the sort order will be random unless [ordered] is used.
Function Get-CompInfo{
[CmdletBinding()]
Param(
#Want to support multiple computers
[String[]]$ComputerName,
#Switch to turn on Error logging
[Switch]$ErrorLog,
[String]$LogFile = 'c:\errorlog.txt'
)
Begin{
If($errorLog){
Write-Verbose 'Error logging turned on'
} Else {
Write-Verbose 'Error logging turned off'
}
Foreach($Computer in $ComputerName){
Write-Verbose "Computer: $Computer"
}
}
Process{
foreach($Computer in $ComputerName){
$os=Get-Wmiobject -ComputerName $Computer -Class Win32_OperatingSystem
$Disk=Get-WmiObject -ComputerName $Computer -class Win32_LogicalDisk -filter "DeviceID='c:'"
$Prop=@{ #With or without [ordered]
'ComputerName'=$computer;
'OS Name'=$os.caption;
'OS Build'=$os.buildnumber;
'FreeSpace'=$Disk.freespace / 1gb -as [int]
}
$Obj=New-Object -TypeName PSObject -Property $Prop
Write-Output $Obj
}
}
End{}
}
Pipe to clip
copy to the clipboard
get-help about_Functions_advanced_parameters | clip
then paste to a document
Error Handling
Error Action Preferences
$errorActionPreference
dir variable:*pref*
switches can be used on commands to temporarily change the error action and error variable
- -ea
- -ev e
$e contains the array of error objects
$e[0] | fl * -force
Display errors:
$myError
$e.targetobject
foreach ($t in $e.targetobject) { $t }
Category View
dir variable:*error* $errorview = "Normalview"
generate some errors
stop-process -id 13 asdfas $errorview = "CategoryView:
generate some errors
stop-process -id 13 asdfas
The view will be different
Event Log
This also needs to be registered to work
write-EventLog -LogName Application -Source JasonSavesYouMoney -EntryType Information -Message "Sxript foo ran" -EventID 7
Tools that make changes
Add commandlet binding
[cmdletbinding(SupportsShouldProcess=$true,
ConfirmImpact='Medium")]
Add the switch -whatif or -confirm and -verbose
- whatif will not run the code
- confirm will ask
- verbose will run the code, but give more information
Default views
\Windows\system32\WindowsPowerShell\v1.0\DotNetTypes.format.ps1xml
built in views
Give garbage view name to get error message the tells the view names
gps * | format-table -view blahblah
process, priority, selection
gps * | format-table -view priority gps * | sort priority | format-table -view gps * | sort starttime | format-table -view
pstypenames
$x = gps lsass $x.GetType() $x.pstypenames $x.pstypenames.Insert(0, "anything you want") $x.pstypenames
Examine the type name of the results from the following command
Get-EventLog -LogName Application -Newest 3 | gm
$x = Get-EventLog -LogName Application -Newest 3 | gm $x.pstypenames
The previous will show synthesized names that simplify or parse the results
From the examples
$obj=New-Object -TypeName PSObject -Property $Prop $obj.PSObject.TypeNames.Insert(0,'Jason.InventoryObject') $obj.PSTypeNames.Insert(0,'Jason.InventoryObject')
Other Randomness
Network exploration
Get-WmiObject -Class Win32_NetworkAdapterConfiguration -Filter IPEnabled=false | Select-Object description | %{ $_.description } | measure | %{ $_.count }
Get-WmiObject -Class Win32_NetworkAdapterConfiguration -Filter IPEnabled=true| Where-Object {$_.IPAddress -like "128.173.*" -or $_.IPAddress -like "198.82.*" } | Select-Object description, | %{ $_.description }
$nic = Get-WmiObject -Class Win32_NetworkAdapterConfiguration -Filter IPEnabled=true| Where-Object {$_.IPAddress -like "128.173*" } | Select-Object description
Get-WmiObject -Class Win32_NetworkAdapterConfiguration -Filter IPEnabled=true| format-list description, IPAddress, DNSServerSearchOrder
Get-WmiObject -Class Win32_NetworkAdapterConfiguration -Filter IPEnabled=true| Select-Object * | Out-GridView
$NA = Get-WmiObject -Class CIM_NetworkAdapter -filter DeviceID=7
$NA.Properties | Select-Object name,value
$NA.Properties.Item("Netconnectionid").value
$NA.Properties.Item("Name").value
#Get-WmiObject -Class Win32_NetworkAdapterConfiguration -Filter IPEnabled=TRUE -ComputerName . |
# something
#Get-WmiObject -Class Win32_NetworkAdapterConfiguration -Filter IPEnabled=TRUE | Format-List *
#netsh interface ipv6 6to4 set state disabled
#netsh interface teredo set state disabled
#netsh interface ipv6 isatap set state disabled
( nslookup orion.aoe.vt.edu 128.173.188.26 | select-string "128" ).count
#netsh interface ip set dns "Local Area Connection" static 128.173.188.25
#netsh interface ip set dns "Local Area Connection" static 128.173.188.26
#netsh interface ipv6 add dnsserver "Local Area Connection" static 2001:468:c80:610c:ccfb:66e9:490f:d18
#netsh interface ipv6 add dnsserver "Local Area Connection" static 2001:468:c80:610c:d1cd:8142:30a:3a7a
#netsh interface ipv6 add dnsserver "Local Area Connection" static 2001:468:c80:610c:d1cd:8142:30a:3a7a
$DC = "128.173.188.25,128.173.188.26"
$Internet = "8.8.8.8"
$dns = "$DC", "$Internet"
$Interface = Get-WmiObject Win32_NetworkAdapterConfiguration
Write-Host "$(Get-Date -format T):Registering DNS $dns for $server" -ForegroundColor Green
Write-Host $Interface.Name
Computer System information
get-wmiobject -Class win32_computersystem
Adtive Directory queries
Get-ADComputer -SearchBase "OU=vpfin,OU=central,DC=cntrlsrvs,DC=w2k,DC=vt,DC=edu" -Filter * Get-ADUser -server sawbones -SearchBase "OU=aoe,OU=vt,DC=w2k,DC=vt,DC=edu" -SearchScope 2 -Filter * ( Get-ADUser nomitav -properties * ) | Select-Object displayname, description, unixhomedirectory, whencreated, whenchanged, userpricipalname, passwordlastset | format-list
cntrlsrvs.w2k.vt.edu
University Active Directory
Two domains relevant to AOE. the first one seems to be the parent domain
- w2k.vt.edu
- HOKIES users (and computers?)
- sawbones.cc.vt.edu
- gordon.cc.vt.edu
- cntrlsrvs.w2k.vt.edu
- cntrlsrvs(?) users and computers
- aoe has an OU in this domain
- cntrlsrvsdc1.cntrlsrvs.w2k.vt.edu
- cntrlsrvsdc2.cntrlsrvs.w2k.vt.edu
- aoe-hokies-users group is added in this domain with the members of the AOE users in w2k.vt.edu/vt/aoe
Querering w2k.vt.edu works:
Get-ADUser -server sawbones -SearchBase "OU=aoe,OU=vt,DC=w2k,DC=vt,DC=edu" -SearchScope 2 -Filter *
But cntrlsrvs.w2k.vt.edu not work as of recently (works now):
get-adcomputer -SearchBase "OU=aoe,OU=central,DC=cntrlsrvs,DC=w2k,DC=vt,DC=edu" -Filter * get-adcomputer : Unable to find a default server with Active Directory Web Services running.
Work-around as posted by techsupport user:
new-psdrive -PSProvider ActiveDirectory -Name "AD" -Root "" -Server "w2k.vt.edu" -GlobalCatalog -Credential (get-credential) cd AD:\ get-adcomputer -SearchBase "OU=aoe,OU=central,DC=cntrlsrvs,DC=w2k,DC=vt,DC=edu" -Filter *
Bigfix integration
ipv6 dns servers
https://developer.bigfix.com/relevance/reference/ipv6-address.html
ipv6 dns server of <network adapter> : ipv6 address dns server of <network adapter> : network address list ipv4or6 dns server of <network adapter> : ipv4or6 address