Create process memory dump

Version: 2.4.7
Creator Name: Guy Leech
Date Created: 2018-12-01
Date Modified: 2020-06-04
Scripting language: PS
Download Count: 66

Creates a full process memory dump of the chosen process to a file in the folder specified. If the chosen process is werfault.exe then its parent process will be dumped instead Arguments: Dump Folder - the folder in which to create the dump file in the format ..dmp
Tags: process, memory dump, debugging

The Script

#requires -version 3
<#
    Create a dump file for a process

    Modification History:

    25/08/19  GRL   Dump parent process if process is werfault

    @guyrleech 2018
#>

[int]$thePid = $args[0]
[string]$dumpFilePath = $args[1]

## http://sysadminconcombre.blogspot.com/2015/09/powershell-dbghelp-reflexion-to-write.html
$MethodDefinition = @'
[DllImport("DbgHelp.dll", CharSet = CharSet.Unicode)]
public static extern bool MiniDumpWriteDump(
    IntPtr hProcess,
    uint processId,
    IntPtr hFile,
    uint dumpType,
    IntPtr expParam,
    IntPtr userStreamParam,
    IntPtr callbackParam
    );
'@

$dbghelp = Add-Type -MemberDefinition $MethodDefinition -Name 'dbghelp' -Namespace 'Win32' -PassThru

[uint32]$miniDumpWithFullMemory = 2 ## https://docs.microsoft.com/en-gb/windows/desktop/api/minidumpapiset/ne-minidumpapiset-_minidump_type
if( ! ( $process = Get-Process -Id $thePid ) )
{
    Throw "Unable to locate process PID $thePid"
}

if( $process.Name -eq 'werfault' )
{
    if( $parentProcess = Get-CimInstance -ClassName win32_process -Filter "ProcessId = '$thePid'" | Select-Object -ExpandProperty ParentProcessId )
    {
        if( ! ( $process = Get-Process -Id $parentProcess ) )
        {
            Throw "Failed to get parent process id $parentProcess for werfault pid $thePid"
        }
        else
        {
            Write-Output -InputObject "Process $thePid is werfault.exe so dumping parent which is $($process.Name) (pid $($process.Id))"
        }
    }
    else
    {
        Throw "Failed to get parent process id for werfault pid $thePid"
    }
}

if( ! ( $processDumpPath = Join-Path -Path $dumpFilePath -ChildPath "$($process.Name).$thePid.$(Get-Date -Format 'yyMMdd.HHmmss').dmp" -ErrorAction SilentlyContinue ) )
{
    Throw "Path `"$dumpFilePath`" for dump file is invalid"
}

$props = $null

try
{
    $props = Get-ItemProperty -Path $processDumpPath -ErrorAction SilentlyContinue
}
catch
{
    $props = $null
}

if( $props )
{
    Write-Error ("Cannot write dump as dump file `"{0}`" already exists - created {1}, size {2} MB" -f $processDumpPath , (Get-Date $props.CreationTime -Format G) , [math]::Round( $props.Length / 1MB ) )
    exit 1
}

if( ! ( $fileStream = New-Object IO.FileStream( $processDumpPath , [IO.FileMode]::Create) ))
{
    Throw "Failed to open dump file `"$processDumpPath`" for writing"
}

try
{
    if( ! ( $result = $dbghelp::MiniDumpWriteDump( $process.Handle , $process.Id , $fileStream.SafeFileHandle.DangerousGetHandle() , $miniDumpWithFullMemory ,[IntPtr]::Zero,[IntPtr]::Zero,[IntPtr]::Zero) ) )
    {
        Write-Error "Error : cannot dump the process PID $thePid"
    }
    else
    {
        if( $props = Get-ItemProperty -Path $processDumpPath -ErrorAction SilentlyContinue )
        {
            Write-Output ("Dump file `"{0}`" created ok, size {1} MB" -f $processDumpPath , [math]::Round( $props.Length / 1MB ) )
        }
        else
        {
            Write-Error "MiniDumpWriteDump() appeared to succeed but dump file `"$processDumpPath`" does not exist"
        }
    }
}
catch
{
    Write-Error "Error : cannot dump the process PID $thePid - $($_.Exception.Message)"
}
finally
{
    $fileStream.Close()
}