PowerShell for Windows Admins


September 3, 2011  6:09 AM

Book offers

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

 

Manning has a good offer on its books this weekend

Saturday, September 3: Save 50% on all eBooks.
Sunday, September 4 : Save 50% on all print books.
Monday, September 5 : Save 50% on your entire purchase.

see www.manning.com for details

September 3, 2011  5:18 AM

Active Directory Logging

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

I had a problem come up recently where I needed to check the level of logging applied to the AD database. This is configurable via registry settings. See http://support.microsoft.com/kb/314980 for details.

Checking one machine is OK by RDP but when you want to check a set of machines its time to dig out the PowerShell.  While I was at it I decided I might as well create a set of functions that:

  1. Check the log settings
  2. Clear all log settings
  3. Set individual log settings

We are dealing with 24 values in the registry so I need to have those available in a variable. I also need to deal with 5 possible logging levels. I originally thought of using enums (my new shiny toy) but the value names have spaces so that didn’t work.  Plan B is hash tables as shown below

$logtype = DATA {            
ConvertFrom-StringData -StringData @'
 1 = 1 Knowledge Consistency Checker
 2 = 2 Security Events
 3 = 3 ExDS Interface Events
 4 = 4 MAPI Interface Events
 5 = 5 Replication Events
 6 = 6 Garbage Collection
 7 = 7 Internal Configuration
 8 = 8 Directory Access
 9 = 9 Internal Processing
 10 = 10 Performance Counters
 11 = 11 Initialization/Termination
 12 = 12 Service Control
 13 = 13 Name Resolution
 14 = 14 Backup
 15 = 15 Field Engineering
 16 = 16 LDAP Interface Events
 17 = 17 Setup
 18 = 18 Global Catalog
 19 = 19 Inter-site Messaging
 20 = 20 Group Caching
 21 = 21 Linked-Value Replication
 22 = 22 DS RPC Client
 23 = 23 DS RPC Server
 24 = 24 DS Schema
'@            
}            
            
$loglevel = DATA {            
ConvertFrom-StringData -StringData @'
 0 = None
 1 = Minimal
 2 = Basic
 3 = Extensive
 4 = Verbose
 5 = Internal
'@            
}             
            
            
            
## functions            
. $psScriptRoot/Get-LogSetting.ps1            
            
            
Export-ModuleMember -Function * -Variable logtype, loglevel

By default variables don’t export from modules so I need to force that with Export-ModuleMember

The function to get the logging levels is this

function get-logsetting{             
[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\NTDS\Diagnostics"            
             
 1..$logtype.Count |            
 foreach {            
  $value = $logtype["$_"]            
  $level = $reg.GetDwordValue($HKLM, $key, $value)  ## REG_DWORD            
              
  New-Object -TypeName PSObject -Property @{            
    Name = $value            
    Level = $loglevel["$($level.uValue)"]            
  }            
}            
            
}#process             
END{}#end            
            
}

The computer name comes in as a mandatory parameter. Then we get the WMI class for the registry and set the key. The values are found by looping through the $logtype hashtable. The results are displayed via an object.

I might add the computer name to the object & I need to create some help before publishing as part of the PAM modules


September 1, 2011  11:27 AM

PowerShell Deep Dive abstracts

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

With the Deep Dive just over 6 weeks away the programme is shaping up.Abstracts of some of the sessions can be viewed

http://blogs.msdn.com/b/powershell/archive/2011/09/01/8-abstracts-for-the-powershell-deep-dive-in-frankfurt.aspx

 

I will also be doing a session on working with events in PowerShell – WMI, .NET and the PowerShell engine

The discounted registration is open until 6 September  – see http://blogs.msdn.com/b/powershell/archive/2011/08/02/extending-discounted-registration-amp-session-proposal-deadline.aspx for details.

 

This is going to be a fantastic event – if you use PowerShell you need to be there


August 30, 2011  12:51 PM

Webcast: Get the most from PowerShell and WMI

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

I will be presenting the above webcast next week.

Date: Wednesday, September 7, 2011

Time: 12:00 PM – 1:00 PM CST

 

Thats 6pm UK time

 

Register for the web cast at

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


August 30, 2011  12:41 PM

Testing services

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

A forum question about testing services and if they weren’t running got me thinking. I created an function to solve the question

function test-service{             
[CmdletBinding(SupportsShouldProcess=$true)]             
param (             
[parameter(Position=0,            
   ValueFromPipeline=$true,             
   ValueFromPipelineByPropertyName=$true)]            
   [Alias("CN", "ComputerName")]              
   [string]$computer="." ,            
               
   [string]$service="BITS" ,            
               
[parameter(Mandatory=$true)]            
   [string]$file            
               
)             
BEGIN {            
 if (!(Test-Path -Path $file)){Throw "log file not found"}            
}            
PROCESS {            
$result =  Get-WmiObject -Class Win32_Service -ComputerName $computer -Filter "Name='$service'"            
            
Write-Verbose "$($result.State)"            
            
if ($($result.State) -eq "Running"){            
  $logdata = "{0,14} {1} {2}" -f $computer, $($result.State), (get-date -Format f )            
}            
else{             
 $start = $result.StartService()             
 if ($start.ReturnValue -eq 0){            
   $logdata = "{0,14} {1} {2}" -f $computer, "Service Started", (get-date -Format f )            
 }            
 else {            
  $logdata = "{0,14} {1} {2}" -f $computer, "Service FAILED to Start", (get-date -Format f )            
 }              
}            
Add-Content -Path $file -Value $logdata             
}            
} ## end function

But I don’t like the answer for a number of reasons:

  • end up out putting text
  • log files involve extra work in parsing
  • will other people know where the log file is

A better solution, in my mind, is to write the data to the event log.  In this case I would use the system log because we are testing services. The application log could be used or we could even create a specific event log for the purpose.

 

function test-service2{             
[CmdletBinding(SupportsShouldProcess=$true)]             
param (             
[parameter(Position=0,            
   ValueFromPipeline=$true,             
   ValueFromPipelineByPropertyName=$true)]            
   [Alias("CN", "ComputerName")]              
   [string]$computer="." ,            
               
   [string]$service="BITS"            
)             
PROCESS {            
$result =  Get-WmiObject -Class Win32_Service -ComputerName $computer -Filter "Name='$service'"            
            
Write-Verbose "$($result.State)"            
            
if ($($result.State) -eq "Running"){            
  $type = "Information"            
  $msg = "$computer - $service is $($result.State) "            
}            
else{             
 $start = $result.StartService()             
 if ($start.ReturnValue -eq 0){            
   $type = "Warning"            
   $msg = "$computer - $service  was started "            
 }            
 else {            
   $type = "Error"            
   $msg = "$computer - $service  FAILED to start"            
 }              
}            
Write-EventLog -LogName Application -Source ServiceTest -EntryType $type -Message $msg -EventId 9999            
            
}            
} ## end function

 

before using the function run this to create the event log source

New-EventLog -LogName Application -Source ServiceTest

The actions are all written to the event log as information, Warning or Error messages as appropriate.

Get-EventLog -LogName Application -Source ServiceTest

Shows the messages.

Enjoy


August 29, 2011  3:05 AM

Deal of the Day–PowerShell

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

PowerShell and WMI is Manning’s deal of the day – 50% off print or e-book.

 

The deal also extends to PowerShell in Practice and PowerShell in Action 2E

See www.manning.com for details


August 28, 2011  1:39 PM

Reminder: TechEd Australia PowerShell conference

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

The TechEd Australia PowerShell conference starts tomorrow at midnight UK time (9am in Australia).  Details from

http://msmvps.com/blogs/richardsiddaway/archive/2011/08/22/teched-australia-powershell-conference.aspx

 

I will be presenting on WSMAN and WMI


August 28, 2011  1:28 PM

Network Adapter vendors

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

The NDis WMI classes expose some information about the vendors that produce the various adapters in our systems

function get-adaptervendor {            
param(            
 [string]$computer="."            
)            
Get-WmiObject -Namespace root\wmi -Class MSNdis_CoVendorDescription `
-ComputerName $computer |            
foreach {            
                
  $id = Get-WmiObject -Namespace root\wmi  `
  -Class MSNdis_CoVendorId -ComputerName $computer `
  -Filter "InstanceName='$($_.InstanceName)'"            
            
  New-Object -TypeName PSobject -Property @{            
    Computer = $_.__SERVER            
    Adapter = $_.InstanceName            
    Active = $_.Active            
    Description = $_.NdisCoVendorDescription            
    Vendorid = $id.NdisCoVendorID            
  }            
}            
}


August 27, 2011  3:18 PM

Msndis class

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

The MSNdis class from the root\wmi namespace calls the MSNdis_CoHardwareStatus and MSNdis_CoDriverVersion classes. On my Windows 7 system it tries to call something else but I get a “Get-WmiObject : Not supported” error. Neither of these classes seems to have much in the way of documentation available.

Rather than calling MSNdis and getting a lot of WMI objects it would be better to combine the output. There are a set of MSNdis-co* classes

gwmi -Namespace root\wmi -List *ndis_co* | sort name

MSNdis_CoDriverVersion
MSNdis_CoHardwareStatus
MSNdis_CoLinkSpeed
MSNdis_CoMacOptions
MSNdis_CoMediaConnectStatus
MSNdis_CoMediaInUse
MSNdis_CoMediaSupported
MSNdis_CoMinimumLinkSpeed
MSNdis_CoReceivePduErrors
MSNdis_CoReceivePdusNoBuffer
MSNdis_CoReceivePdusOk
MSNdis_CoTransmitPduErrors
MSNdis_CoTransmitPdusOk
MSNdis_CountedString
MSNdis_CoVendorDescription
MSNdis_CoVendorDriverVersion
MSNdis_CoVendorId

Lets see what we can find out about them

 

 

function get-adaptercoinfo {            
param(            
 [string]$computer="."            
)            
Get-WmiObject -Namespace root\wmi -Class MSNdis_CoHardwareStatus `
-ComputerName $computer |            
foreach {            
                
  $drv = Get-WmiObject -Namespace root\wmi  `
  -Class MSNdis_CoDriverVersion -ComputerName $computer `
  -Filter "InstanceName='$($_.InstanceName)'"            
            
  New-Object -TypeName PSobject -Property @{            
    Computer = $_.__SERVER            
    Adapter = $_.InstanceName            
    Active = $_.Active            
    HardwareStatus = $_.NdisCoHardwareStatus            
    DriverVersion = $drv.NdisCoDriverVersion             
  }            
}            
}

Start with the MSNdis_CoHardwareStatus and match to MSNdis_CoDriverVersion  on instance name (associators don’t seem to be created for these classes). Put the appropriate properties into an object and output.

The output is best displayed like this

get-adaptercoinfo | ft -a


August 26, 2011  12:59 PM

European PowerShell Deep Dive–presenting

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

I was notified last night that my submission to the Deep Dive was successful and I will be presenting. There will be a good number of PowerShell MVPs attending. This will be the PowerShell event of the year in Europe. The one in April in the USA was brilliant – this will be at least as good.

Event details from http://blogs.msdn.com/b/powershell/archive/2011/08/02/extending-discounted-registration-amp-session-proposal-deadline.aspx


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: