Skip to content

Instantly share code, notes, and snippets.

@smaglio81
Created August 18, 2018 22:01
Show Gist options
  • Save smaglio81/5e033ffb25633558369ab692eb6fb0ab to your computer and use it in GitHub Desktop.
Save smaglio81/5e033ffb25633558369ab692eb6fb0ab to your computer and use it in GitHub Desktop.
Takes a procdump of the w3wp process associated with a given url (either locally or remote). Transfer the process dump to a communal shared location for retrieval.
if($global:WebAdmin -eq $null) {
$global:WebAdmin = @{}
}
# http://stackoverflow.com/questions/1183183/path-of-currently-executing-powershell-script
$root = Split-Path $MyInvocation.MyCommand.Path -Parent;
$global:WebAdmin.ProcDumpLocalPath = "$root\Resources\procdump.exe"
<#
.SYNOPSIS
Uses sysinternal procdump to get a proc dump of a w3wp service on a webserver. The file will
be transfered to a shared location for distribution.
.PARAMETER ServerName
The server to pull a proc dump from.
.PARAMETER Url
The url of the website to get a proc dump from
.EXAMPLE
Command:
New-WebProcDumpUcsb -ServerName SA177 -Url my.dev.sa.ucsb.edu/aaa
Output:
#>
Function New-WebProcDump {
[CmdletBinding()]
Param (
[Parameter(Mandatory=$false)]
[string] $ServerName = $env:COMPUTERNAME,
[Parameter(Mandatory=$true)]
[string] $Url
)
# setup variables
$appPoolName = ConvertTo-UrlBasedAppPoolName -Url $Url
$isLocalMachine = Test-IsLocalComputerName -ComputerName $ServerName
if((Test-WebAppExists -ServerName $ServerName -Url $Url) -eq $false) {
throw "IIS $env:COMPUTERNAME - No webapp could be found for url $Url on $ServerName"
}
# ensure procdump exists on the remote server
if((Test-Path $global:WebAdmin.ProcDumpLocalPath) -eq $false) {
throw "IIS $env:COMPUTERNAME - Cannot find local copy of procdump.exe in WebAdministrationUcsb module ($($global:WebAdministrationUcsb.ProcDumpLocalPath)). Ensure it exists before running again."
}
if($isLocalMachine) {
# gonna run procdump locally so the local procdump in the module will be used.
} else {
# gonna run this on a remote server, so ensure that procdump is on the server
$utilRemotePath = "\\{0}\C$\IT\Utilities" -f $ServerName
if((Test-Path $utilRemotePath) -eq $false) {
New-Item -Path $utilRemotePath -ItemType Directory | Out-Null
}
$procdumpRemotePath = "$utilRemotePath\procdump.exe"
if((Test-Path $procdumpRemotePath) -eq $false) {
Copy-Item -Path $global:WebAdministrationUcsb.ProcDumpLocalPath -Destination $utilRemotePath | Out-Null
}
}
# get the process info from the remote server
$processScript = {
if($appPoolName -eq $null) {
$appPoolName = $args[0]
}
Import-Module WebAdministration
$webModule = Get-Module WebAdministration
if(-not $webModule) {
Import-Module WebAdministration
}
$processes = dir "IIS:\AppPools\$appPoolName\WorkerProcesses"
return $processes
}
$params = @($appPoolName)
if($isLocalMachine) {
$w = . $processScript
} else {
$w = Invoke-Command -ComputerName $ServerName -ScriptBlock $processScript -ArgumentList $params
}
if($w -eq $null) {
throw "IIS $env:COMPUTERNAME - No process for appPool $appPoolName on $ServerName could be found."
}
if(@($w).Count -gt 1) {
throw "IIS $env:COMPUTERNAME - Multiple processes for appPool $appPoolName on $ServerName were found. This is weird, contact an administrator. Process Count: $(@($w).Count)"
}
# run the dump remotely
$dumpScript = {
if($processId -eq $null) {
$processId = $args[0]
}
if($procdump -eq $null) {
$procdump = "C:\IT\Utilities\procdump.exe"
}
cd "C:\Users\$($env:USERNAME)\AppData\Local\Temp"
$out = . $procdump -ma -accepteula $processId
$line = $out |? { $_ -match "Dump 1 initiated" }
$ix = $line.IndexOf("ed: ")
$path = $line.Substring($ix + 4)
return $path
}
$processId = $w.processId
$procdump = $global:WebAdmin.ProcDumpLocalPath
if($isLocalMachine) {
$path = . $dumpScript
} else {
$path = Invoke-Command -ComputerName $ServerName -ScriptBlock $dumpScript -ArgumentList $processId
}
# copy dump to local storage
$sharepath = ""
if([string]::IsNullOrWhiteSpace($path) -eq $false) {
$nwPath = $path -replace "C:\\", "\\$ServerName\C$\"
if(Test-Path $nwPath) {
$parent = Split-Path $nwPath -Parent
$leaf = Split-Path $nwPath -Leaf
$null = . robocopy "$parent" "D:\Temp\" /r:1 /w:1 $leaf
$locpath = "D:\Temp\$leaf"
$curnttime = [DateTime]::Now.ToString("yyyyMMddHHmm")
$newfilename = "$ServerName-$appPoolName-w3wp-$curnttime.dmp"
$newpath = "D:\Temp\$newfilename"
mv $locpath $newpath
del $nwPath -Force -ErrorAction SilentlyContinue
$sharepath = "\\$($env:COMPUTERNAME)\d\temp\$newfilename"
}
}
return $sharepath
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment