====== 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
>>> {
>>> $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 "Generated by IT
" -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
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
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 ======
https://blogs.technet.microsoft.com/heyscriptingguy/2014/01/15/using-powershell-to-find-connected-network-adapters/
===== 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 : ipv6 address
dns server of : network address list
ipv4or6 dns server of : ipv4or6 address