PowerShell for Windows Admins


September 14, 2011  1:57 PM

The Experts Conference April 2011–My session

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

Dmitry has just posted the video of the session I did at the PowerShell deep dive @ TEC in April

http://dmitrysotnikov.wordpress.com/2011/09/14/video-richard-siddaway-wmi-gems-and-gotchas/

 

The session was entitled WMI: Hidden Gems and Gotchas

Links to the slides and demo scripts are also available on the post

September 14, 2011  1:12 PM

Windows 8 and PowerShell 3

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

You will have started to see blogs about Windows 8 and PowerShell 3 due to Microsoft releasing a developers preview version on MSDN.  I’m currently building Windows 8 and Server 8 machines – more news when they are up and running


September 8, 2011  2:46 PM

Quirks of Get-member and WMI objects

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

I have been asked about discovering the methods available on a WMI object. I’ve mentioned the GetMethodParameters method a few times but it can be difficult to find.  Normally if we want to discover the methods on an object we would do this

 

Get-WmiObject Win32_Service | Get-Member -MemberType method

 

which gives this list

Change

ChangeStartMode

Delete

GetSecurityDescriptor

InterrogateService

PauseService

ResumeService

SetSecurityDescriptor

StartService

StopService

UserControlService

we will ignore the terminal services object that also appears

 

To dig into the underlying object we use .psbase (or Get-Member -MemberType method –View base)

 

(Get-WmiObject Win32_Service).psbase | Get-Member -MemberType method

 

gives us this list

Address

Clone

CopyTo

Equals

Get

GetEnumerator

GetHashCode

GetLength

GetLongLength

GetLowerBound

GetType

GetUpperBound

GetValue

Initialize

Set

SetValue

ToString

 

Note that the object type is System.Management.Automation.PSMemberSet

 

When we use Get-WmiObject we are looking at an instance of the WMI class. To look at the class itself

 

[wmiclass]"Win32_Service" | Get-Member -MemberType method

 

but this just shows a Create method

 

If we drop into the base object now

 

([wmiclass]"Win32_Service").psbase | Get-Member -MemberType method

 

we get

Clone

CompareTo

CopyTo

CreateInstance

CreateObjRef

Delete

Derive

Dispose

Equals

Get

GetHashCode

GetInstances

GetLifetimeService

GetMethodParameters

GetPropertyQualifierValue

GetPropertyValue

GetQualifierValue

GetRelated

GetRelatedClasses

GetRelationshipClasses

GetRelationships

GetStronglyTypedClassCode

GetSubclasses

GetText

GetType

InitializeLifetimeService

InvokeMethod

Put

SetPropertyQualifierValue

SetPropertyValue

SetQualifierValue

ToString

 

Which shows the Method we want and a few other potentially interesting methods to test out.


September 8, 2011  1:40 PM

PowerShell User Group–20 September 2011

Richard Siddaway Richard Siddaway Profile: Richard Siddaway


When: Tuesday, Sep 20, 2011 7:30 PM (BST)


Where:

*~*~*~*~*~*~*~*~*~*

Aleksandar Nikolic presents on PowerShell remoting and the customisation of remoting end points.
Aleksandar’s presentation at the PowerShell Deep Dive was excellent – don’t miss this one

Notes


Richard Siddaway has invited you to attend an online meeting using Live Meeting.
Join the meeting.
Audio Information
Computer Audio
To use computer audio, you need speakers and microphone, or a headset.
First Time Users:
To save time before the meeting, check your system to make sure it is ready to use Microsoft Office Live Meeting.
Troubleshooting
Unable to join the meeting? Follow these steps:

  1. Copy this address and paste it into your web browser:
    https://www.livemeeting.com/cc/usergroups/join
  2. Copy and paste the required information:
    Meeting ID: 3GJGF5
    Entry Code: d6`S<^zjM
    Location: https://www.livemeeting.com/cc/usergroups

If you still cannot enter the meeting, contact support

Notice
Microsoft Office Live Meeting can be used to record meetings. By participating in this meeting, you agree that your communications may be monitored or recorded at any time during the meeting.


September 6, 2011  11:29 AM

Test for domain membership

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

Quick function to determine if a given machine is in a domain or workgroup

function test-domain{             
[CmdletBinding()]             
param (             
[parameter(Position=0,            
   Mandatory=$true,            
   ValueFromPipeline=$true,             
   ValueFromPipelineByPropertyName=$true)]            
   [string]$computer="."             
)             
BEGIN{}#begin             
PROCESS{            
 Get-WmiObject -Class Win32_ComputerSystem -ComputerName $computer |            
 select Name, Domain            
            
}#process             
END{}#end            
            
}

Feed the function a computer name or IP address and it will return the name and domain. If the computer is in the domain we get the full domain name – if its in a workgroup we get the workgroup name (WORKGROUP by default)


September 6, 2011  11:11 AM

Invoke-WmiMethod–Type mismatch error

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

Sometimes when we try to use Invoke-WmiMethod with an argument list we get an error

PS> Invoke-WmiMethod -Class Win32_Share -Name Create -ArgumentList "c:\test", "Test57", 0
Invoke-WmiMethod : Type mismatch
At line:1 char:17
+ Invoke-WmiMethod <<<<  -Class Win32_Share -Name Create -ArgumentList "c:\test", "Test57", 0
    + CategoryInfo          : InvalidOperation: (:) [Invoke-WmiMethod], ManagementException
    + FullyQualifiedErrorId : InvokeWMIManagementException,Microsoft.PowerShell.Commands.InvokeWmiMethod

 

Going back to basics this technique works – its how we did things in PowerShell and it still works great.

$s = [wmiclass]"Win32_Share"
$s.Create("c:\test", "Test57", 0)

As we have seen – this fails

Invoke-WmiMethod -Class Win32_Share -Name Create -ArgumentList "c:\test", "Test57", 0

According to the documentation the full list of the parameters for the method is:

Path
Name
Type
MaximumAllowed
Description
Password
Access

so we are really doing this

$path = "c:\test"
$name = "Test57"
$type = 0
$password = ""
$description = ""
$max = 100
$access = $null
$s = [wmiclass]"Win32_Share"
$s.Create($path, $name, $type, $max, $description, $password, $access)

when we did this

$s.Create("c:\test", "Test57", 0)

we were just ignoring the last four parameters.

BUT

if we look at the parameter list using
$s.psbase.GetMethodParameters("Create")

it shows the parameters in this order
Access
Description
MaximumAllowed
Name
Password
Path
Type

so this works
Invoke-WmiMethod -Class Win32_Share -Name Create -ArgumentList $access, $description, $max, $name, $password, $path, $type

If you get the Type mismatch error then its a good time to check the parameter order.

PS – I haven’t verified that the Invoke-WmiMethod expects the parameters in alphabetical order


September 5, 2011  12:45 PM

PowerShell and WMI webcast

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

 

Webcast: Get the most from PowerShell and WMI

I will be presenting the above webcast next week.

Date: Wednesday, September 7, 2011.  Thats tomorrow

Time: 12:00 PM – 1:00 PM CDT

Thats 6pm UK time

Register for the web cast at

http://powershell.com/cs/media/p/11256.aspx


September 5, 2011  12:33 PM

Find the Time Server

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

No its not the latest Internet game.

Active Directory synchronises the computer clock times. To know what server is being used

function get-timeserver{             
[CmdletBinding(SupportsShouldProcess=$true)]             
param (             
[parameter(Position=0,            
   Mandatory=$true,            
   ValueFromPipeline=$true,             
   ValueFromPipelineByPropertyName=$true)]            
   [string]$computer             
)             
BEGIN{            
 $HKLM = 2147483650            
}#begin             
            
PROCESS{            
 $reg = [wmiclass]"\\$computer\root\default:StdRegprov"            
            
 $key = "SYSTEM\CurrentControlSet\Services\W32Time\Parameters"            
             
 switch ($computer){            
   "."         {$computername = $env:COMPUTERNAME}            
   "localhost" {$computername = $env:COMPUTERNAME}            
   default     {$computername = $computer}            
 }            
             
 $value = "NtpServer"            
 $server = $reg.GetStringValue($HKLM, $key, $value)  ## REG_SZ            
 $server.sValue -split ","            
              
}#process             
END{}#end            
            
}

Read the "SYSTEM\CurrentControlSet\Services\W32Time\Parameters" key for the Ntpserver value.  Its a string so use GetstringValue(). It is possible to define multiple time servers so split the string on “,”

Ignore the final value of 0×9


September 4, 2011  12:16 PM

Clearing AD logging

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

Last time we looked at turning on logging – for one or more criteria. The normal state of diagnostic logging is None i.e. the options are set to zero. If we have only a few options set we can use set-logsetting to revert to no logging. Alternatively we can reset all logging to a zero state

function reset-logsetting{             
[CmdletBinding(SupportsShouldProcess=$true)]             
param (             
[parameter(Position=0,            
   Mandatory=$true,            
   ValueFromPipeline=$true,             
   ValueFromPipelineByPropertyName=$true)]            
   [string]$computer             
)             
BEGIN{            
 $HKLM = 2147483650            
}#begin             
            
PROCESS{            
 Write-Verbose "Display Current Settings"            
 get-logsetting -computer $computer            
             
 $reg = [wmiclass]"\\$computer\root\default:StdRegprov"            
            
 $key = "SYSTEM\CurrentControlSet\Services\NTDS\Diagnostics"            
             
 switch ($computer){            
   "."         {$computername = $env:COMPUTERNAME}            
   "localhost" {$computername = $env:COMPUTERNAME}            
   default     {$computername = $computer}            
 }            
             
 1..$logtype.Count |            
 foreach {            
  $value = $logtype["$_"]            
  $level = $reg.SetDwordValue($HKLM, $key, $value, 0)  ## REG_DWORD            
}            
            
Write-Verbose "Display New Settings"            
""            
get-logsetting -computer $computer            
            
}#process             
END{}#end            
            
<# 
.SYNOPSIS
Resets all AD diagnostic logging levels to none

.DESCRIPTION
Resets all AD diagnostic logging levels to none

.PARAMETER  Computer
Computer Name


.EXAMPLE
reset-logsetting

User will be prompted for server name

.EXAMPLE
reset-logsetting -computer server02

.LINK

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

#>            
            
}

This loops through the options and sets each to zero.


September 4, 2011  3:32 AM

Setting AD logging

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

Now that we know what the options are we can look at switching them on.

function set-logsetting{             
[CmdletBinding(SupportsShouldProcess=$true)]             
param (             
[parameter(Position=0,            
   Mandatory=$true,            
   ValueFromPipeline=$true,             
   ValueFromPipelineByPropertyName=$true)]            
   [string]$computer,            
               
   [string]$setting,            
               
   [ValidateRange(0,5)]            
   [int]$level             
)             
BEGIN{            
 $HKLM = 2147483650            
}#begin             
            
PROCESS{            
 if ($logtype.Values -notcontains $setting){            
   Throw "Incorrect setting - please use get-logsettingoptions"            
 }            
             
 $reg = [wmiclass]"\\$computer\root\default:StdRegprov"            
            
 $key = "SYSTEM\CurrentControlSet\Services\NTDS\Diagnostics"            
             
 switch ($computer){            
   "."         {$computername = $env:COMPUTERNAME}            
   "localhost" {$computername = $env:COMPUTERNAME}            
   default     {$computername = $computer}            
 }            
             
 $result = $reg.SetDwordValue($HKLM, $key, $setting, $level)  ## REG_DWORD            
            
}#process             
END{}#end            
            
<# 
.SYNOPSIS
Sets AD diagnostic logging levels 

.DESCRIPTION
Sets AD diagnostic logging levels 

.PARAMETER  Computer
Computer Name

.PARAMETER  Setting
The setting to be logged

.PARAMETER  Level
The level of logging to be applied

.EXAMPLE
set-logsetting -computer server02 -setting "5 Replication Events" -level 1

.EXAMPLE
get-logsettingoptions | 
foreach {set-logsetting -computer server02 -setting $_ -level 2}

.EXAMPLE
get-logsettingoptions | 
where {$_ -like "19*"} | 
foreach {set-logsetting -computer server02 -setting $_ -level 5}

.LINK

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

#>            
            
}

The setting and level are input as parameters. The level can be checked as a range – the setting to log is checked against the hash table of logging types. The WMI SetDWord method is used to perform the change. A few of the ways the setting to use can be input are shown in the help examples.


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: