Windows PowerShell Basics: Part 3

Overview

In lesson 1 and lesson 2 we looked at the Where-Object cmdlet.  The example we looked at was:

Get-Service | Where-object {$_.status -like "running"}

Notice that the cmdlet takes a comparison operation as a parameter.  This operation, called a script block, is contained in curly braces.  Other cmdlets can take script blocks as parameters, or launch a code block as a response, such as in the following example:

if ($varA -gt $varB)
{ Write-Host "Condition evaluates to true." }
else
{ Write-Host "Condition evaluates to false." }

Script blocks can span more than one line.  Script blocks can also nest other script blocks.  The following example  uses the Windows Event log provider to search the Windows system log for events with a source of W32Time.  It then uses the Foreach-Object cmdlet to  format the color of the event based on the level of the event (using the EntryType property).

$eventcol = get-eventlog -logname system |where-object {$_.source -eq "W32Time"}
foreach($item in $eventcol){
if($item.EntryType -eq "Error"){
Write-host $item.EntryType," ID:",$item.EventID,"Time:",$item.TimeGenerated -foregroundcolor "red"
}
else {
if($item.EntryType -eq "Warning"){
Write-host $item.EntryType," ID:",$item.EventID,"Time:",$item.TimeGenerated -foregroundcolor "Yellow"
}
else {
write-host $item.EntryType," ID:",$item.EventID,"Time:",$item.TimeGenerated -foregroundcolor "green"
}
}
}

Looking at the script block in more detail, the ForEach cmdlet takes the $eventcol collection we created in the previous line, and assigns each object in the collection to the $item variable.  The internal command, if, looks at the EntryType property of each item and sends the output to the write-host cmdlet.

Grouping objects

The group-object cmdlet can group object that have the same value for a property.  The following example reads the 1000 most recent events from the system event log into a collection.  We then group the objects by source first, then by event ID and sort by the count of similar instances.  Note that the count property is created by the group-object cmdlet, not by the get-eventlog cmdlet.

$events = get-eventlog -logname system -newest 1000
$events | group-object source,eventid |sort-object count -descending | format-list

Using other Providers and Application-specific Cmdlets

The following examples use many of the topics explored previously and provide examples of the versatility and usefulness of Windows Powershell. 

Using the Windows Registry Provider

List subkeys for a registry key:
Get-childitem hklm:\software\microsoft\windows\currentversion |format-list

Display all values from a registry key (but not child keys. Will include powershell attributes as well):
Get-itemproperty hklm:\software\microsoft\windows\currentversion

Using the WMI Provider

Uses the put() method of Win32_computersystem to change the caption property of the local computer.

========================================================================

$myob2 = get-WmiObject win32_computersystem
$myob2.Caption = "My New Value"
$myob2.put()

Display an alphabetical listing of all WBEM namespaces on a remote computer (pre-defined by the $target variable):

get-wmiobject -computer $target -namespace root -class __Namespace| Select-object Name | Sort-object Name

Get list of machines from a text file.  Check WMI to see if the Automatic Updates service is running. Start the AU service if it is not running.  Write the results to the screen:

$erroractionpreference = "SilentlyContinue"
$a = get-content "C:\Temp\Machinelist.txt"
Foreach ($i in $a)
{$b = get-wmiobject win32_service -computername $i -Filter "Name = 'wuauserv'"
If ($b.state -eq "stopped")
{$b.startservice()
write-host "Window update service is started for $i"}
else
{write-host "Window update service is already started for $i"}
}

Working with files

Find a file on the C:\ drive.  Rename the file with the .bak extension and replace it with a new file.  Note: Because of the structure of the CIM_DataFile class, we need to split File Name and Extension into two variables:

$strFileName = "TestFile"
$strFileExt = "doc"
$strNewFileName = "TestFile2.doc"

$colFiles = get-wmiobject -query "Select * from CIM_Datafile where FileName = '$strFileName' and extension = '$strFileExt' and drive ='C:'"
Foreach ($objfile in $colfiles)
{
Ren $objfile.name -newname ($objfile.filename +".bak")
copy-item $strNewFileName -destination ($objfile.drives + $objfile.path)
}

Get a list of files (but not folders) in the Windows directory. List Name, Length (in bytes), Length (in KB, rounded down).

Sort descending by file length.  Display as a table with column width automatically sized:

dir C:\windows |where-object {$_.mode -notlike "d*"}| Select-object Name, Length, @{n='Length In KB';e={(($_.Length / 1024)-($_.Length % 1024 / 1024))}}| sort-object Length -desc |ft -a

Working with Active Directory

LDAP query for all computers in a domain:

$DC = <domain controller name>
$DomainName = <Domain Netbios Name>
$DomainExt = <Top Level Domain Name (com, net, etc)>

$root=[ADSI]"LDAP://" + $DC + "/dc=" + $DomainName + ",dc=" + DomainExt

$searchAD = new-object System.DirectoryServices.DirectorySearcher($root)
$searchAD.PageSize = 10000
$searchAD.Filter = "(objectClass=computer)"
$searchResults = $searchAD.FindAll()

foreach ($result in $searchResults){
$temp = $result.getDirectoryEntry()
$temp
}

Creating COM Objects with Powershell

Use Powershell to open an IE window and browse to the MSN.com homepage:

$ie = new-object -COMObject InternetExplorer.Application
$ie.visible = $True
$ie.Navigate("https://www.msn.com")

Formatting Output to HTML

Get current date, convert output to HTML file, change table format to include border with size of 1:

get-date |convertto-html -title "Date Table" | foreach { $_ -replace "<Table>","<Table border=1>" } > C:\test.html

Explore on your own:

  1. Use the write-host cmdlet to display the even numbers from 2 through 12.
  2. In the example above, use the Foregroundcolor parameter to output dark green text and the Backgroundcolor parameter to display a white background.
  3. Use the Foreach-object cmdlet and write-host cmdlet to display the numbers 1-20.  Display odd numbers in light green text and even numbers in light blue text.
  4. Read the Windows Application event log and get the count of Warnings and Errors that occurred each of the last 7 days using the group-object cmdlet.

For further review, read the following help files:

Help write-host -full
Help foreach-object -full
Help group-object -full
Help about_script_block

Richard Pesenko | Support Escalation Engineer