PowerShell for Windows Admins


January 3, 2010  8:36 AM

Disks Part 1

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

Disk storage and everything associated with that is a big part of administering our servers. We need to be able to discover, and where necessary, work with the storage system. WMI gives us a number of classes for working with disks

PS> Get-WmiObject -List Win32_*disk* | select name

Name
—-
Win32_LogicalDisk
Win32_MappedLogicalDisk
Win32_DiskPartition
Win32_DiskDrive
Win32_LogicalDiskRootDirectory
Win32_DiskQuota
Win32_LogonSessionMappedDisk
Win32_LogicalDiskToPartition
Win32_DiskDrivePhysicalMedia
Win32_DiskDriveToDiskPartition
Win32_PerfFormattedData_PerfDisk_LogicalDisk
Win32_PerfRawData_PerfDisk_LogicalDisk
Win32_PerfFormattedData_PerfDisk_PhysicalDisk
Win32_PerfRawData_PerfDisk_PhysicalDisk

PS> Get-WmiObject -List Win32_*volume* | select name

Name
—-
Win32_VolumeChangeEvent
Win32_Volume
Win32_VolumeQuota
Win32_VolumeQuotaSetting
Win32_VolumeUserQuota
Win32_ShadowVolumeSupport
Win32_ShadowDiffVolumeSupport

PS> Get-WmiObject -List Win32_*drive* | select name

Name
—-
Win32_DiskDrive
Win32_FloppyDrive
Win32_TapeDrive
Win32_CDROMDrive
Win32_DiskDrivePhysicalMedia
Win32_DiskDriveToDiskPartition

Note that the last list has been edited to exclude those classes to work with drivers

Our starting point has to be the physical drives.

PS> Get-WmiObject -Class Win32_DiskDrive

Partitions : 3
DeviceID   : \\.\PHYSICALDRIVE0
Model      : ST9250320AS ATA Device
Size       : 250056737280
Caption    : ST9250320AS ATA Device

As with the Operating System there is a lot of information behind this – details from http://msdn.microsoft.com/en-us/library/aa394132(VS.85).aspx

We’ll dig further into disks in the next series of posts

Technorati Tags: ,,

January 1, 2010  5:06 AM

Downloading PowerShell version 2

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

The PowerShell version 2 download seems to be difficult to find. It is part of the Windows Management Framework (PowerShell 2.0, WinRM 2.0 and (where applicable BITS 4.0).

The install packages for various Operating Systems – Vista, Windows 2008, Windows 2003 and Windows XP are available in 32 and 64 bit versions from

http://support.microsoft.com/kb/968929

BITS 4.0 is only supported on Windows 2008 & Vista

Happy New-Year


December 29, 2009  12:21 PM

Hotfixes

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

We have seen how to get information on the Operating System installed on our computers. We can round that out by looking at the hotfixes that are installed on the machine.

Get-WmiObject -Class Win32_QuickFixEngineering

Source        Description      HotFixID      InstalledBy          InstalledOn
——        ———–      ——–      ———–          ———–
RSLAPTOP01    Update           KB972636      RSLAPTOP01\Richard   08/07/2009 00:00:00
RSLAPTOP01    Security Update  KB973525      NT AUTHORITY\SYSTEM
RSLAPTOP01    Update           KB973874      NT AUTHORITY\SYSTEM
RSLAPTOP01    Update           KB974332      RSLAPTOP01\Richard
RSLAPTOP01    Update           KB974431      NT AUTHORITY\SYSTEM
RSLAPTOP01    Security Update  KB974455      NT AUTHORITY\SYSTEM
RSLAPTOP01    Security Update  KB974571      NT AUTHORITY\SYSTEM
RSLAPTOP01    Update           KB975364      RSLAPTOP01\Richard   11/01/2009 00:00:00
RSLAPTOP01    Hotfix           KB975467      NT AUTHORITY\SYSTEM
RSLAPTOP01    Update           KB976098      NT AUTHORITY\SYSTEM
RSLAPTOP01    Security Update  KB976325      NT AUTHORITY\SYSTEM  12/11/2009 00:00:00
RSLAPTOP01    Update           KB976749      RSLAPTOP01\Richard   11/04/2009 00:00:00

This displays all hotfixes. Sometimes we may just want to test for a single fix

Get-WmiObject -Class Win32_QuickFixEngineering -Filter “HotFixID=’KB972636′”

of for a set of machines

“RSLAPTOP01”, “127.0.0.1” | foreach {
if (Get-WmiObject -Class Win32_QuickFixEngineering -Filter “HotFixID=’KB972636′”)
{Write-Host “$($_) has KB972636 installed”}
}

With PowerShell v2 If we want to learn more about a particular fix we can do this

Get-WmiObject -Class Win32_QuickFixEngineering -Filter “HotFixID=’KB972636′” | foreach {Start-Process $_.caption}

The caption property conatins  a URL e.g. http://support.microsoft.com/?kbid=972636

A get-hotfix cmdlet has been introduced that simplifies this

Get-HotFix -Id KB972636 | foreach {Start-Process $_.Caption}

We have finished our look at the OS – next time we will start looking at disks.

Happy New Year

Technorati Tags: ,,


December 21, 2009  11:41 AM

Class Descriptions

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

We have seen how to find the classes associated with a particular aspect of our system e.g.

Get-WmiObject  -List  *disk*

We will see this one again soon when we turn our attention to disks

One thing we can’t get directly is a description of the class so we can confirm it does what we think.  Well, with a little bit of digging in Powershell 2 we can use the –ammended parameter to display a description

PS> ((Get-WmiObject -List Win32_OperatingSystem -Amended).Qualifiers | Where {$_.Name -eq "Description"}).Value

The Win32_OperatingSystem class represents an operating system installed on a Win32 computer system. Any operating system that can be installed on a Win32 system is a descendent (or member) of this class.
Example: Microsoft Windows 95.

We list the class we are interested in and select the qualifiers. A where statement is used to filter for the description qualifier and then we display its value.

We don’t normally display the description because it is a more expensive operation.

Technorati Tags: ,,


December 21, 2009  7:23 AM

Working with the OS

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

We’ve seen what information we can derive on the Operating System from Win32_OperatingSystem but is there anything we can actually do to our systems?

There are a handful of methods available to us – mainly to do with shutting down the system

PS> Get-WmiObject -Class Win32_OperatingSystem | Get-Member -MemberType Method | Format-Table Name, Definition -Wrap

Name                                                  Definition
—-                                                        ———-
Reboot                                                System.Management.ManagementBaseObject Reboot()
SetDateTime                                     System.Management.ManagementBaseObject SetDateTime(System.S
                                                             tring LocalDateTime)
Shutdown                                           System.Management.ManagementBaseObject Shutdown()
Win32Shutdown                               System.Management.ManagementBaseObject Win32Shutdown(System
                                                             .Int32 Flags, System.Int32 Reserved)
Win32ShutdownTracker                 System.Management.ManagementBaseObject Win32ShutdownTracker
                                                             (System.UInt32 Timeout, System.String Comment, System.UInt3
                                                             2 ReasonCode, System.Int32 Flags)

Details from http://msdn.microsoft.com/en-us/library/aa394239(VS.85).aspx but

Reboot will shutdown and restart the system. SetDatetime ssts computer date and time (shouldn’t be needed with Time synchronisation in the domain)

Shutdown unloads programs and dlls so computer can be turned off

Win32Shutdown gives us options

0 (0x0) = Log Off
4 (0x4) = Forced Log Off (0 + 4)
1 (0x1) = Shutdown
5 (0x5) = Forced Shutdown (1 + 4)
2 (0x2) = Reboot
6 (0x6) = Forced Reboot (2 + 4)
8 (0x8) = Power Off
12 (0xC) = Forced Power Off (8 + 4)

On Vista\Win2008 and above we can use

Win32ShutdownTracker   to add a comment into the event log and and shutdown dialog box

We can use Win32Shutdown like this

$computer = Get-WmiObject -Class Win32_OperatingSystem -ComputerName .
$computer.Win32Shutdown(5)

If we put this into a loop and feed a set of computer names into it we can shut down our whole environment. Not a frequent occurrence – but one I needed to do recently when moving a datacentre.


December 19, 2009  7:13 AM

Using a script

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

We have seen how to use our script to access information on the local machine. Ideally we want to be accessing this information from many machines across our enterprise. If we save the script to get-os.ps1 we can use it in a few ways.

if we just want information on a handful of computers we can pipe them into the script like this.

“.”, “127.0.0.1”, “rslaptop01” | foreach {“`n $_”; .\Get-OS.ps1 -computer $_ }

I’m running these scripts from the folder where I saved the script which is why I need ./ to represent the path of the current folder.  $_ is the object on the pipeline and `n is the way a new line is thrown.  A ; is used as a line terminator in PowerShell. It is only really used when we are typing at the prompt like this.

Import-Csv ./computers.csv | foreach { “`n”; $_.Computer ; .\Get-OS.ps1 -computer $_.Computer}

If we have a lot of computers – and we want to use the list in a number of scripts we can create a csv file. use a single column with a header of computer like this

Computer
.
localhost
127.0.0.1
rslaptop01

We can input computer names or IP addresses.

Now we know how to access information about our machine’s OS its time to see what else we can do.


December 19, 2009  4:45 AM

System Discovery Part 4

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

This is out last look at Win32_OperatingSystem.  I’ve taken the script we had last time and added a few more calculated fields to determine language, country, locale and codeset information.  I’ve left the URLs where I found the information as comments. If you are not UK based you will want to add extra values from the tables I’ve referenced.

The other change I’ve made at the beginning of the script is to allow it to accept a computer name as a parameter. Up to now we have just been looking at the local machine. We can now extend this to cover remote machines because we’ve added the –computername parameter to the Get-WmiObject call.

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
param ([string]$computer = “.”  ) 
$os = DATA {
ConvertFrom-StringData -StringData @’
14 = MSDOS
15 = WIN3X
16 = WIN95
17 = WIN98
18 = WINNT
19 = WINCE
‘@

}##
## for language and locale settings see
## http://msdn.microsoft.com/en-us/goglobal/bb964664.aspx
##

$lang = DATA {
ConvertFrom-StringData -StringData @’
1033 = English US
2057 = English UK
‘@

}

$loc = DATA {
ConvertFrom-StringData -StringData @’
0409 = English US
0809 = English UK
‘@

}

## codeset info
## http://msdn.microsoft.com/en-us/goglobal/bb964654.aspx
$code = DATA {
ConvertFrom-StringData -StringData @’
1252 = Latin I
‘@

}

## country codes
##http://msdn.microsoft.com/en-us/library/dd387951(VS.85).aspx
$country = DATA {
ConvertFrom-StringData -StringData @’
1 = USA
44 = United Kingdom
‘@

}

Get-WmiObject -Class Win32_OperatingSystem -ComputerName $computer | 
Format-List CSName, Caption, ServicePackMajorVersion, 
ServicePackMinorVersion, BuildNumber, Version, OSArchitecture,
SystemDevice, SystemDrive, WindowsDirectory, SystemDirectory, 
@{Name=“OS Language”; Expression={$lang[“$($_.OSLanguage)”]}}, 
OSProductSuite, 
@{Name=“OS Type”; Expression={$os[“$($_.OSType)”]}}, 
@{Name=“Code Set”; Expression={$code[“$($_.CodeSet)”]}}, 
@{Name=“Country Code”; Expression={$country[“$($_.CountryCode)”]}}, 
EncryptionLevel, 
ForegroundApplicationBoost, DataExecutionPrevention_32BitApplications,
DataExecutionPrevention_Available, DataExecutionPrevention_Drivers, 
DataExecutionPrevention_SupportPolicy, 
@{Name=”Installation Date”; Expression={$_.ConvertToDateTime($_.InstallDate)}},
@{Name=”Last Bootup time”; Expression={$_.ConvertToDateTime($_.LastBootUpTime)}},
@{Name=”Local Date Time”; Expression={$_.ConvertToDateTime($_.LocalDateTime)}}, 
@{Name=“Locale “; Expression={$loc[“$($_.Locale)”]}},
@{Name=“Free Physical Memory (GB)”; Expression={“{0:F3}” -f $($_.FreePhysicalMemory/1GB*1kb)}},
@{Name=“Size Stored In Paging Files (GB)”; Expression={“{0:F3}” -f $($_.SizeStoredInPagingFiles *1kb /1GB)}},
@{Name=“Free Space In Paging Files (GB)”; Expression={“{0:F3}” -f $($_.FreeSpaceInPagingFiles *1kb /1GB)}},
@{Name=“Total Visible Memory Size (GB)”; Expression={“{0:F3}” -f $($_.TotalVisibleMemorySize *1kb /1GB)}}, 
@{Name=“Total Virtual Memory Size (GB)”; Expression={“{0:F3}” -f $($_.TotalVirtualMemorySize *1kb /1GB)}}, 
@{Name=“Free Virtual Memory (GB)”; Expression={“{0:F3}” -f $($_.FreeVirtualMemory*1kb /1GB)}}

 

 

 

 

 

The final change is at the end of the script where I’ve added calculated fields to convert the memory fields to GB from the KB they are reported in. These fields all take the same form

@{Name=”Free Virtual Memory (GB)”; Expression={“{0:F3}” -f $($_.FreeVirtualMemory*1kb /1GB)}}

Create a new name for the field and then multiply the field by 1kb to turn it to bytes and the divide by 1GB to get gigabytes.  PowerShell recognises kb, mb, gb, tb and pb as kilobytes, megabytes etc (tb and pb are only in PowerShell 2). They are case insensitive so kb and KB both work.  I then take the calculated result and format it into a string using the –f operator.  The formatting restricts the display to 3 decimal places.

I’ve shown a number of steps in the evolution of this script as it reflects they way these things are often developed. Start with the raw display from the WMI object and then refine to give more meaningful information. In future scripts I’ll just jump straight to the end point, usually, as I used this example to show case the techniques we can use.


December 16, 2009  3:27 PM

System Discovery Part 3

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

The class description for Win32_OperatingSystem can be found here.  Access to the WMI reference information starts at http://msdn.microsoft.com/en-us/library/aa394572(VS.85).aspx

If we look at the Win32_OperatingSystem class description we will see that there are a number of properties where we can get numeric values returned. These don’t tell us a lot unless we happened to have memorised the table of values. There may be a test later!

Lets see what we have at the moment

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
CSName                                    : RSLAPTOP01
Caption                                   : Microsoft Windows 7 Ultimate 
ServicePackMajorVersion                   : 0
ServicePackMinorVersion                   : 0
BuildNumber                               : 7600
Version                                   : 6.1.7600
OSArchitecture                            : 32-bit
SystemDevice                              : \Device\HarddiskVolume2
SystemDrive                               : C:
WindowsDirectory                          : C:\Windows
SystemDirectory                           : C:\Windows\system32
OSLanguage                                : 1033
OSProductSuite                            : 256
OSType                                    : 18
CodeSet                                   : 1252
CountryCode                               : 44
EncryptionLevel                           : 256
ForegroundApplicationBoost                : 2
DataExecutionPrevention_32BitApplications : True
DataExecutionPrevention_Available         : True
DataExecutionPrevention_Drivers           : True
DataExecutionPrevention_SupportPolicy     : 2
Installation Date                         : 07/08/2009 11:38:52
Last Bootup time                          : 16/12/2009 14:02:58
Local Date Time                           : 16/12/2009 20:53:30
Locale                                    : 0809
FreePhysicalMemory                        : 1498944
SizeStoredInPagingFiles                   : 2881972
FreeSpaceInPagingFiles                    : 2683264
TotalVisibleMemorySize                    : 2881972
TotalVirtualMemorySize                    : 5763944
FreeVirtualMemory                         : 3921460

 

Now some of these look like candidates for translation.  I am not going to show all possible answers as some of these tables get quite large as you will see when examining the documentation.  I’ll give a couple of examples that work for the environments I work in.

We can modify our script as follows

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
$os = DATA {
ConvertFrom-StringData -StringData @’
14 = MSDOS
15 = WIN3X
16 = WIN95
17 = WIN98
18 = WINNT
19 = WINCE
‘@

}

Get-WmiObject -Class Win32_OperatingSystem | Format-List CSName, Caption, `
ServicePackMajorVersion, ServicePackMinorVersion, BuildNumber, Version, `
OSArchitecture, SystemDevice, SystemDrive, WindowsDirectory, SystemDirectory, `
OSLanguage, OSProductSuite, `
@{Name=“OS Type”; Expression={$os[“$($_.OSType)”]}}, `
CodeSet, CountryCode, EncryptionLevel, `
ForegroundApplicationBoost, DataExecutionPrevention_32BitApplications, `
DataExecutionPrevention_Available, DataExecutionPrevention_Drivers, `
DataExecutionPrevention_SupportPolicy, `
@{Name=”Installation Date”; Expression={$_.ConvertToDateTime($_.InstallDate)}}, `
@{Name=”Last Bootup time”; Expression={$_.ConvertToDateTime($_.LastBootUpTime)}}, `
@{Name=”Local Date Time”; Expression={$_.ConvertToDateTime($_.LocalDateTime)}}, `
Locale, FreePhysicalMemory, SizeStoredInPagingFiles, FreeSpaceInPagingFiles, `
TotalVisibleMemorySize, TotalVirtualMemorySize, FreeVirtualMemory

 

We create a hash table of the numeric values and their translated meaning.  I’ve truncated the possible OS types that can be returned because I am only expecting Windows Operating Systems.

We can create another calculated field to get the value returned from the hash table.

I’ll work out the others and post a single script with them all in.  We also need to do something with the memory fields as they are current quoted in KB which isn’t the easiest of levels to work with.


December 15, 2009  4:04 PM

System Discovery Part 2

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

This is our script to examine the Operating System. I’ve made it a bit easier to read by using the line continuation character ` (that’s a back tick not an apostrophe) Get-WmiObject -Class Win32_OperatingSystem | Format-List CSName, Caption, `
ServicePackMajorVersion, ServicePackMinorVersion, BuildNumber, Version, `
OSArchitecture, SystemDevice, SystemDrive, WindowsDirectory, SystemDirectory, `
OSLanguage, OSProductSuite, OSType, CodeSet, CountryCode, EncryptionLevel, `
ForegroundApplicationBoost, DataExecutionPrevention_32BitApplications, `
DataExecutionPrevention_Available, DataExecutionPrevention_Drivers, `
DataExecutionPrevention_SupportPolicy, InstallDate, LastBootUpTime, LocalDateTime, `
Locale, FreePhysicalMemory, SizeStoredInPagingFiles, FreeSpaceInPagingFiles, `
TotalVisibleMemorySize, TotalVirtualMemorySize, FreeVirtualMemory

One problem with this is that the dates are reported like this
InstallDate           : 20090807113852.000000+060
LastBootUpTime  : 20091215080951.359600+000
LocalDateTime     : 20091215213858.961000+000

Which isn’t very readable.
If we look at the object produced by Win32_OperatingSystem using
Get-WmiObject -Class Win32_OperatingSystem | Get-Member
We can see that there are a couple of methods we can use to manipulate dates.
ConvertFromDateTime
ConvertToDateTime

We want to convert to a date and time that we can read. In order to do this we need to create a calculated field.

@{Name=”Installation Date”; Expression={$_.ConvertToDateTime($_.InstallDate)}}

We create a hash table (associative array) where the first element defines the name we want to give the field and the second element defines an expression to calculate the value.

$_ represents the object coming down the pipeline so we use the ConvertToDateTime method of that object and feed it the InstallDate property.
Likewise the other two fields can be calculated

@{Name=”Last Bootup time”; Expression={$_.ConvertToDateTime($_.LastBootUpTime)}}, `
@{Name=”Local Date Time”; Expression={$_.ConvertToDateTime($_.LocalDateTime)}},

The three dates then become
Installation Date : 07/08/2009 11:38:52
Last Bootup time : 15/12/2009 08:09:51
Local Date Time  : 15/12/2009 21:52:51

I’m in the UK so my dates are DD/MM/YYYY format.

Our whole script becomes
Get-WmiObject -Class Win32_OperatingSystem | Format-List CSName, Caption, `
ServicePackMajorVersion, ServicePackMinorVersion, BuildNumber, Version, `
OSArchitecture, SystemDevice, SystemDrive, WindowsDirectory, SystemDirectory, `
OSLanguage, OSProductSuite, OSType, CodeSet, CountryCode, EncryptionLevel, `
ForegroundApplicationBoost, DataExecutionPrevention_32BitApplications, `
DataExecutionPrevention_Available, DataExecutionPrevention_Drivers, `
DataExecutionPrevention_SupportPolicy, `
@{Name=”Installation Date”; Expression={$_.ConvertToDateTime($_.InstallDate)}}, `
@{Name=”Last Bootup time”; Expression={$_.ConvertToDateTime($_.LastBootUpTime)}}, `
@{Name=”Local Date Time”; Expression={$_.ConvertToDateTime($_.LocalDateTime)}}, `
Locale, FreePhysicalMemory, SizeStoredInPagingFiles, FreeSpaceInPagingFiles, `
TotalVisibleMemorySize, TotalVirtualMemorySize, FreeVirtualMemory

We will look at unravelling some of the numeric values next


December 14, 2009  12:12 PM

WMI and Windows firewall

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

Windows Server 2008 and R2 install with the Windows firewall enabled. This will prevent the sort of remote administration we have been discussing. If you try it there will be a long wait before the command times out or you will get some kind of error stating that the server cannot be found or connected to.

This is a bit of road block.

We can get round this by running these commands on the remote machine.

Netsh firewall set service RemoteAdmin

Netsh advfirewall set currentprofile settings remotemanagement enable

They will open the correct firewall ports to allow remote connection and management via WMI.

If we are using the PowerShell v2 remoting capability running Enable-Remoting will configure the firewall for access by WSMAN but not WMI we still need these commands.


Forgot Password

No problem! Submit your e-mail address below. We'll send you an e-mail containing your password.

Your password has been sent to: