Tag Archives: Windows

Configure Windows crash behaviour with PowerShell

When there is a OS-handled crash (a blue screen), there are some settings in the Startup and Recovery Control Panel, which tells Windows how it should behave. For example, whether it restarts automatically or not , whether it writes a small memory dump (aka minidump), a kernel dump or a full dump, and where it saves the dump file :

Startup and Recovery Window

If you want to troubleshoot a recurrent crash, you may want to alter this behaviour, for example, you may need to set the system not to restart automatically to be able to see the blue screen. You may also need a complete memory dump to facilitate your investigations or to send to Microsoft Support.

Here is how to do this using PowerShell :

These settings correspond to properties of the WMI class : Win32_OSRecoveryConfiguration, so let’s start by checking what we have in there :

 
C:\ > $CrashBehaviour = Get-WmiObject Win32_OSRecoveryConfiguration -EnableAllPrivileges
C:\ > $CrashBehaviour | Format-List *


PSComputerName             : DESKTOP
__GENUS                    : 2
__CLASS                    : Win32_OSRecoveryConfiguration
__SUPERCLASS               : CIM_Setting
__DYNASTY                  : CIM_Setting
__RELPATH                  : Win32_OSRecoveryConfiguration.Name="Microsoft Windows 7 Ultimate
                             |C:\\Windows|\\Device\\Harddisk0\\Partition3"
__PROPERTY_COUNT           : 15
__DERIVATION               : {CIM_Setting}
__SERVER                   : DESKTOP
__NAMESPACE                : root\cimv2
__PATH                     : \\DESKTOP\root\cimv2:Win32_OSRecoveryConfiguration.Name="Microsoft Windows 7
                             Ultimate |C:\\Windows|\\Device\\Harddisk0\\Partition3"
AutoReboot                 : True
Caption                    :
DebugFilePath              : %SystemRoot%\MEMORY.DMP
DebugInfoType              : 2
Description                :
ExpandedDebugFilePath      : C:\Windows\MEMORY.DMP
ExpandedMiniDumpDirectory  : C:\Windows\Minidump
KernelDumpOnly             : False
MiniDumpDirectory          : %SystemRoot%\Minidump
Name                       : Microsoft Windows 7 Ultimate |C:\Windows|\Device\Harddisk0\Partition3
OverwriteExistingDebugFile : True
SendAdminAlert             : False
SettingID                  :
WriteDebugInfo             : True
WriteToSystemLog           : True
Scope                      : System.Management.ManagementScope
Path                       : \\DESKTOP\root\cimv2:Win32_OSRecoveryConfiguration.Name="Microsoft Windows 7
                             Ultimate |C:\\Windows|\\Device\\Harddisk0\\Partition3"
Options                    : System.Management.ObjectGetOptions
ClassPath                  : \\DESKTOP\root\cimv2:Win32_OSRecoveryConfiguration
Properties                 : {AutoReboot, Caption, DebugFilePath, DebugInfoType...}
SystemProperties           : {__GENUS, __CLASS, __SUPERCLASS, __DYNASTY...}
Qualifiers                 : {dynamic, Locale, provider, UUID}
Site                       :
Container                  :

The parameter -EnableAllPrivileges will allow us to manipulate the properties of this WMI object if the current Powershell host was run as Administrator.

Here is how to prevent Windows to restart automatically after a system failure :

 $CrashBehaviour | Set-WmiInstance -Arguments @{AutoReboot=$False}
 

Let’s check if our change is effective :

No auto restart highlight

Woohoo, it worked !

Now, we are going to configure the type of memory dump: small, kernel, or complete. As you can see above, the default value is 2, which corresponds to kernel dump.
Here are the possible values and their meaning :
0 = None
1 = Complete memory dump
2 = Kernel memory dump
3 = Small memory dump

Here is how to configure Windows to save full dumps :

I had some difficulties to make it work using the variable $CrashBehaviour, so here is how to do it :

 Get-WmiObject -Class "Win32_OSRecoveryConfiguration" -EnableAllPrivileges  |
Set-WmiInstance -Arguments @{DebugInfoType=1}
 

And how to verify our change :

DebugInfoType Full Dump

If you have recurrent crashes and you want to check if it is the same type of failure every time, you may want to keep any existing memory dump when writing a new dump to disk. Be careful though, this may consume a large amount of disk space, especially with full dumps.

 $CrashBehaviour | Set-WmiInstance -Arguments @{OverwriteExistingDebugFile=$False}
 

 

Now, if you want to change where the dump files will be written, perhaps on a volume with more free space, here is how to change the location of the memory dumps :

 $CrashBehaviour | Set-WmiInstance -Arguments @{DebugFilePath="E:\MEMORY.DMP"}
 

And how to verify the modification :

DebugFilePath

By default, an OS-handled crash will write an event in the System event log. I’m not sure why you would want to change this behaviour, but in case you do, here is how to do it :

 $CrashBehaviour | Set-WmiInstance -Arguments @{WriteToSystemLog=$False}
 

Getting the CPU time and status of threads in a process with Powershell

If there is a process hanging or consuming CPU resources and you have no idea why, a good place to start is to have a look at its threads and what they are doing.

Fortunately, Threads are a property of the object you get when run Get-Process :

SelectThreads.png

Here, we just see an array of numbers, not very informative.

But these objects returned by Get-Process are very rich and their “Threads” property have their own set of properties and methods :

ThreadsMembers.png

I cut the output for brevity, but there are a total of 16 properties for the ProcessThread objects, so we have a lot to play with !

Here are the most interesting properties to see the threads which are consuming CPU time, what kind of CPU time and, if they are waiting, what they are waiting for:

InterestingProperties.png

This is showing a lot of potential but the property values are not very human-readable.
So, I did some member-massaging (that sounds wrong) properties customization and addition, to get the times in a more usable format : percentage and seconds.
I ended up with a function, which takes one or more process IDs from a parameter called ID :

#Requires -Version 2
function Get-ProcessThreadsInfo {
 
    [cmdletbinding()]
    param(
        [Parameter(Mandatory=$true)]
        [int32[]]$ID
    )
    $Processes = Get-Process -Id $ID
 
    Foreach ($Process in $Processes) {
 
        # Displaying the process name
        Write-Output $Process.ProcessName.ToUpper()
        Write-Output "`r"
 
        # Displaying of threads and the number of threads consuming CPU time in this process
        $NumberOfThreads = ($Process | Select-Object -ExpandProperty Threads | Measure-Object).count
        $NumberofThreadsWithCPUTime = ($Process | Select-Object -ExpandProperty Threads |
        Where-Object { $_.TotalProcessorTime.Ticks -ne 0 } | Measure-Object).count

        Write-Output "Number of threads in this process : $NumberOfThreads "
        Write-Output "Number of threads consuming CPU time in this process : $NumberofThreadsWithCPUTime "
 
        # Extracting the threads objects from each process
        $ProcessThreads = $Process | Select-Object -ExpandProperty Threads | Where { $_.TotalProcessorTime.Ticks -ne 0 }
 
        Foreach ($ProcessThread in $ProcessThreads) {
 
            # Building custom properties for my threads objects
            $ThreadID = @{L="ThreadID";E={ $ProcessThread.Id }}
            $CPUTimeProperty = @{L="CPU Time (Sec)";E={ [math]::round($ProcessThread.TotalProcessorTime.TotalSeconds,2) }}
            $UserCPUTimeProperty = @{ L="User CPU Time (%)";E={ [math]::round((($ProcessThread.UserProcessorTime.ticks / $ProcessThread.TotalProcessorTime.ticks)*100),1) }}
            $SystemCPUTimeProperty = @{L="System CPU Time (%)";E={ [math]::round((($ProcessThread.privilegedProcessorTime.ticks / $ProcessThread.TotalProcessorTime.ticks)*100),1) }}
            $State = @{L="State";E={ $ProcessThread.ThreadState }}
 
            # Mapping the possible values of WaitReason to their actual meaning (source: https://msdn.microsoft.com/en-us/library/tkhtkxxy(v=vs.110).aspx)
            switch ($ProcessThread.WaitReason) {
                EventPairHigh { $Wait_ReasonPropertyValue =
                "Waiting for event pair high.Event pairs are used to communicate with protected subsystems." ; break }
                
                EventPairLow { $Wait_ReasonPropertyValue =
                "Waiting for event pair low. Event pairs are used to communicate with protected subsystems." ; break }
                
                ExecutionDelay { $Wait_ReasonPropertyValue =
                "Thread execution is delayed." ; break }
                
                Executive { $Wait_ReasonPropertyValue =
                "The thread is waiting for the scheduler." ; break }
                
                FreePage { $Wait_ReasonPropertyValue =
                "Waiting for a free virtual memory page." ; break }
                
                LpcReceive { $Wait_ReasonPropertyValue =
                "Waiting for a local procedure call to arrive."; break }
                
                LpcReply { $Wait_ReasonPropertyValue =
                "Waiting for reply to a local procedure call to arrive." ; break }
                
                PageIn { $Wait_ReasonPropertyValue =
                "Waiting for a virtual memory page to arrive in memory." ; break }
                
                PageOut { $Wait_ReasonPropertyValue =
                "Waiting for a virtual memory page to be written to disk." ; break }
                
                Suspended { $Wait_ReasonPropertyValue =
                "Thread execution is suspended." ; break }
                
                SystemAllocation { $Wait_ReasonPropertyValue =
                "Waiting for a memory allocation for its stack." ; break }
                
                Unknown { $Wait_ReasonPropertyValue =
                "Waiting for an unknown reason." ; break }
                
                UserRequest { $Wait_ReasonPropertyValue =
                "The thread is waiting for a user request." ; break }
                
                VirtualMemory { $Wait_ReasonPropertyValue =
                "Waiting for the system to allocate virtual memory." ; break }
                
                Default { $Wait_ReasonPropertyValue = " " ; break }
            }
 
            # Creating the custom output object
            $ProcessThread | Select-Object -Property $ThreadID, StartTime, $CPUTimeProperty, $UserCPUTimeProperty, $SystemCPUTimeProperty, $State |
            Add-Member -NotePropertyName "Wait Reason" -NotePropertyValue $Wait_ReasonPropertyValue -PassThru 
        }
    }
}

The output looks like this :

Get-ProcessThreadsInfo.png

This is not exhaustive or deep information by any means, but it can be a starting point to drill down further with other tools.

As you can see, Internet Explorer (iexplore) is waiting for me, so… gotta go.