September 4, 2011 12:16 PM
Posted by: Richard Siddaway
Active Directory,
PowerShell v2,
WMILast 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
Posted by: Richard Siddaway
Active Directory,
PowerShell v2,
WMINow 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.
September 3, 2011 1:31 PM
Posted by: Richard Siddaway
Active Directory,
PowerShell v2,
WMIWith 24 logging options to choose from its difficult to keep track of them. We already have the data in a ash table so lets just display it
function get-logsettingoptions{
PROCESS{
1..$logtype.Count |
foreach {
$logtype["$_"]
}
}#process
END{}#end
<#
.SYNOPSIS
Displays logging options
.DESCRIPTION
Displays logging options
.EXAMPLE
get-logsettingoptions
#>
}
A simple loop through the hash table and we get this display
1 Knowledge Consistency Checker
2 Security Events
3 ExDS Interface Events
4 MAPI Interface Events
5 Replication Events
6 Garbage Collection
7 Internal Configuration
8 Directory Access
9 Internal Processing
10 Performance Counters
11 Initialization/Termination
12 Service Control
13 Name Resolution
14 Backup
15 Field Engineering
16 LDAP Interface Events
17 Setup
18 Global Catalog
19 Inter-site Messaging
20 Group Caching
21 Linked-Value Replication
22 DS RPC Client
23 DS RPC Server
24 DS Schema
We can filter down the results using where-object or just copy the names to use when we set the logging options
September 3, 2011 6:09 AM
Posted by: Richard Siddaway
Books
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
Posted by: Richard Siddaway
Active Directory,
WMII 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:
- Check the log settings
- Clear all log settings
- 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
Posted by: Richard Siddaway
PowerShell v2With 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
Posted by: Richard Siddaway
PowerShell v2,
WMII 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
Posted by: Richard Siddaway
PowerShell v2A 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
Posted by: Richard Siddaway
Books,
PowerShell v2PowerShell 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