├── src
├── OETW
│ ├── MsoEtwAS.res
│ ├── MsoEtwCM.res
│ ├── MsoEtwDQ.res
│ ├── MsoEtwTP.res
│ ├── MsoEtwDQ.man
│ ├── MsoEtwTP.man
│ ├── MsoEtwAS.man
│ ├── MsoEtwCM.man
│ └── ReadMe.txt
├── BETA
│ ├── OETW
│ │ ├── EdgeETW.res
│ │ ├── ChromeETW.res
│ │ ├── ChromeETW.man
│ │ ├── ReadMe.txt
│ │ └── EdgeETW.man
│ ├── ADDIN
│ │ └── ReadMe.txt
│ ├── Generate-PmuRegFile.bat
│ ├── TracePMC.bat
│ ├── TraceEdgeChrome.bat
│ ├── TraceNetwork.bat
│ ├── ReadMe.txt
│ ├── PMCs.bat
│ ├── PMC.bat
│ ├── WPRP
│ │ └── RPC.wprp
│ ├── WPAP
│ │ └── Network.wpaProfile
│ └── TraceEdgeChrome.ps1
├── NetBlame
│ ├── .editorconfig
│ ├── Providers
│ │ ├── OTaskPool.Classic.cs
│ │ ├── WinsockNameRes.cs
│ │ ├── WebIO-Layout.md
│ │ ├── WebIO.Connection.cs
│ │ ├── WebIO.Session.cs
│ │ ├── WThreadPool.cs
│ │ └── Thread.Classic.cs
│ ├── NetBlameAddIn.csproj
│ ├── NetBlameAddIn.sln
│ ├── ClassicDataProcessor.cs
│ ├── README.md
│ ├── NetBlameDataSource.cs
│ ├── .gitattributes
│ ├── Auxiliary
│ │ ├── GeoLocation.cs
│ │ └── Extensions.cs
│ └── .gitignore
├── PreWin10
│ ├── TraceCPU.bat
│ ├── TraceHeap.bat
│ ├── TraceHandles.bat
│ ├── TraceHeapEx.bat
│ ├── TraceMemory.bat
│ ├── TraceMondo.bat
│ ├── TraceNetwork.bat
│ ├── TraceOffice.bat
│ ├── TraceOutlook.bat
│ ├── TraceFileDiskIO.bat
│ ├── WPRP
│ │ ├── JS.wprp
│ │ ├── CLR.wprp
│ │ ├── ThreadPool.wprp
│ │ ├── VirtualAlloc.wprp
│ │ ├── Defender.wprp
│ │ ├── Handles.wprp
│ │ └── CPU.wprp
│ ├── TraceNetwork.ps1
│ ├── TraceMondo.ps1
│ ├── TraceCPU.ps1
│ ├── TraceFileDiskIO.ps1
│ ├── TraceHandles.ps1
│ └── TraceMemory.ps1
├── WPAP
│ ├── ETW-Overhead-for-CPU.stacktags
│ ├── ETW-Overhead.wpaProfile
│ ├── OfficeSpecial.regions.xml
│ ├── VirtualAlloc.stacktags
│ └── Threads.wpaProfile
├── ResetWPA.bat
├── SymbolScan.bat
├── TraceCPU.bat
├── TraceHeap.bat
├── TraceHandles.bat
├── TraceHeapEx.bat
├── TraceMemory.bat
├── TraceMondo.bat
├── TraceNetwork.bat
├── TraceOffice.bat
├── TraceOutlook.bat
├── TraceRegistry.bat
├── TraceFileDiskIO.bat
├── ResetWPA.ps1
├── WPRP
│ ├── CLR.wprp
│ └── ThreadPool.wprp
├── ReadMe.txt
├── SymbolScan.ps1
└── TraceRegistry.ps1
├── CODE_OF_CONDUCT.md
├── LICENSE
├── .github
└── workflows
│ └── release.yml
├── make
└── CreateRelease.ps1
├── SUPPORT.md
├── SECURITY.md
└── README.md
/src/OETW/MsoEtwAS.res:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/MSO-Scripts/HEAD/src/OETW/MsoEtwAS.res
--------------------------------------------------------------------------------
/src/OETW/MsoEtwCM.res:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/MSO-Scripts/HEAD/src/OETW/MsoEtwCM.res
--------------------------------------------------------------------------------
/src/OETW/MsoEtwDQ.res:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/MSO-Scripts/HEAD/src/OETW/MsoEtwDQ.res
--------------------------------------------------------------------------------
/src/OETW/MsoEtwTP.res:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/MSO-Scripts/HEAD/src/OETW/MsoEtwTP.res
--------------------------------------------------------------------------------
/src/BETA/OETW/EdgeETW.res:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/MSO-Scripts/HEAD/src/BETA/OETW/EdgeETW.res
--------------------------------------------------------------------------------
/src/BETA/OETW/ChromeETW.res:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/MSO-Scripts/HEAD/src/BETA/OETW/ChromeETW.res
--------------------------------------------------------------------------------
/src/NetBlame/.editorconfig:
--------------------------------------------------------------------------------
1 | [*.cs]
2 |
3 | # IDE0024: Use block body for operators
4 | csharp_style_expression_bodied_operators = false:silent
5 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Microsoft Open Source Code of Conduct
2 |
3 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
4 |
5 | Resources:
6 |
7 | - [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/)
8 | - [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/)
9 | - Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns
10 |
--------------------------------------------------------------------------------
/src/PreWin10/TraceCPU.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | setlocal
3 |
4 | REM The powershell script has the same path and base name as this batch script.
5 | set _CMD=-file "%~dpn0.ps1" %*
6 | echo PowerShell %_CMD%
7 |
8 | REM Set a temporary Bypass execution policy in Process scope to run the PowerShell script without interruption.
9 | REM https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_execution_policies?#powershell-execution-policies
10 | PowerShell -EP Unrestricted %_CMD%
11 |
--------------------------------------------------------------------------------
/src/PreWin10/TraceHeap.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | setlocal
3 |
4 | REM The powershell script has the same path and base name as this batch script.
5 | set _CMD=-file "%~dpn0.ps1" %*
6 | echo PowerShell %_CMD%
7 |
8 | REM Set a temporary Bypass execution policy in Process scope to run the PowerShell script without interruption.
9 | REM https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_execution_policies?#powershell-execution-policies
10 | PowerShell -EP Unrestricted %_CMD%
11 |
--------------------------------------------------------------------------------
/src/PreWin10/TraceHandles.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | setlocal
3 |
4 | REM The powershell script has the same path and base name as this batch script.
5 | set _CMD=-file "%~dpn0.ps1" %*
6 | echo PowerShell %_CMD%
7 |
8 | REM Set a temporary Bypass execution policy in Process scope to run the PowerShell script without interruption.
9 | REM https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_execution_policies?#powershell-execution-policies
10 | PowerShell -EP Unrestricted %_CMD%
11 |
--------------------------------------------------------------------------------
/src/PreWin10/TraceHeapEx.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | setlocal
3 |
4 | REM The powershell script has the same path and base name as this batch script.
5 | set _CMD=-file "%~dpn0.ps1" %*
6 | echo PowerShell %_CMD%
7 |
8 | REM Set a temporary Bypass execution policy in Process scope to run the PowerShell script without interruption.
9 | REM https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_execution_policies?#powershell-execution-policies
10 | PowerShell -EP Unrestricted %_CMD%
11 |
--------------------------------------------------------------------------------
/src/PreWin10/TraceMemory.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | setlocal
3 |
4 | REM The powershell script has the same path and base name as this batch script.
5 | set _CMD=-file "%~dpn0.ps1" %*
6 | echo PowerShell %_CMD%
7 |
8 | REM Set a temporary Bypass execution policy in Process scope to run the PowerShell script without interruption.
9 | REM https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_execution_policies?#powershell-execution-policies
10 | PowerShell -EP Unrestricted %_CMD%
11 |
--------------------------------------------------------------------------------
/src/PreWin10/TraceMondo.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | setlocal
3 |
4 | REM The powershell script has the same path and base name as this batch script.
5 | set _CMD=-file "%~dpn0.ps1" %*
6 | echo PowerShell %_CMD%
7 |
8 | REM Set a temporary Bypass execution policy in Process scope to run the PowerShell script without interruption.
9 | REM https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_execution_policies?#powershell-execution-policies
10 | PowerShell -EP Unrestricted %_CMD%
11 |
--------------------------------------------------------------------------------
/src/PreWin10/TraceNetwork.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | setlocal
3 |
4 | REM The powershell script has the same path and base name as this batch script.
5 | set _CMD=-file "%~dpn0.ps1" %*
6 | echo PowerShell %_CMD%
7 |
8 | REM Set a temporary Bypass execution policy in Process scope to run the PowerShell script without interruption.
9 | REM https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_execution_policies?#powershell-execution-policies
10 | PowerShell -EP Unrestricted %_CMD%
11 |
--------------------------------------------------------------------------------
/src/PreWin10/TraceOffice.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | setlocal
3 |
4 | REM The powershell script has the same path and base name as this batch script.
5 | set _CMD=-file "%~dpn0.ps1" %*
6 | echo PowerShell %_CMD%
7 |
8 | REM Set a temporary Bypass execution policy in Process scope to run the PowerShell script without interruption.
9 | REM https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_execution_policies?#powershell-execution-policies
10 | PowerShell -EP Unrestricted %_CMD%
11 |
--------------------------------------------------------------------------------
/src/PreWin10/TraceOutlook.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | setlocal
3 |
4 | REM The powershell script has the same path and base name as this batch script.
5 | set _CMD=-file "%~dpn0.ps1" %*
6 | echo PowerShell %_CMD%
7 |
8 | REM Set a temporary Bypass execution policy in Process scope to run the PowerShell script without interruption.
9 | REM https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_execution_policies?#powershell-execution-policies
10 | PowerShell -EP Unrestricted %_CMD%
11 |
--------------------------------------------------------------------------------
/src/PreWin10/TraceFileDiskIO.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | setlocal
3 |
4 | REM The powershell script has the same path and base name as this batch script.
5 | set _CMD=-file "%~dpn0.ps1" %*
6 | echo PowerShell %_CMD%
7 |
8 | REM Set a temporary Bypass execution policy in Process scope to run the PowerShell script without interruption.
9 | REM https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_execution_policies?#powershell-execution-policies
10 | PowerShell -EP Unrestricted %_CMD%
11 |
--------------------------------------------------------------------------------
/src/BETA/ADDIN/ReadMe.txt:
--------------------------------------------------------------------------------
1 | Copyright (c) Microsoft Corporation. Licensed under the MIT License.
2 |
3 | This component uses the free IP-GeoLocation API from ip-api at: https://ip-api.com
4 |
5 | This is the _only_ folder with binary executable code, consisting of WPA add-ins.
6 | It can be removed with only limited loss of functionality for the WPA viewer.
7 |
8 | https://github.com/microsoft/MSO-Scripts/wiki/Network-Activity#plugin
9 |
10 | This version is for use with:
11 | WPA.exe v11.7.383+
12 | Microsoft.Performance.SDK.dll v1.2.2+
13 |
--------------------------------------------------------------------------------
/src/NetBlame/Providers/OTaskPool.Classic.cs:
--------------------------------------------------------------------------------
1 | // Copyright(c) Microsoft Corporation.
2 | // Licensed under the MIT License.
3 |
4 | /*
5 | Generate the Office TaskPool events from the raw generic events.
6 | Ideally we shouldn't need to do this.
7 | However, it is not uncommon that the manifest for this provider is missing or out-of-date.
8 | That causes an exception storm in WPA's GenericEvents mechanism, and we lose the events.
9 | */
10 |
11 | namespace NetBlameCustomDataSource.OTaskPool.Classic
12 | {
13 | // TODO: Do this or not!?
14 | }
15 |
--------------------------------------------------------------------------------
/src/OETW/MsoEtwDQ.man:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
9 |
10 |
11 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/src/OETW/MsoEtwTP.man:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
9 |
10 |
11 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/src/BETA/OETW/ChromeETW.man:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/src/WPAP/ETW-Overhead-for-CPU.stacktags:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
9 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/src/OETW/MsoEtwAS.man:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/src/ResetWPA.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | setlocal
3 |
4 | REM The powershell script has the same path and base name as this batch script.
5 | set _PATH="%~dpn0.ps1"
6 | set _ARGS=%*
7 |
8 | REM Detect, warn, and remove Mark of the Web.
9 | (more < "%~dpn0.ps1:Zone.Identifier") >nul 2>nul && (
10 | echo Unblocking downloaded PowerShell script: %~n0.ps1
11 | echo https://github.com/microsoft/MSO-Scripts/wiki/Frequently-Asked-Questions#policy
12 | echo:>"%~dpn0.ps1:Zone.Identifier"
13 | powershell unblock-file '%~dpn0.ps1' 2>nul
14 | echo:
15 | )
16 |
17 | REM Escape spaces and quotes for use with: -command
18 | set _CMD=-command %_PATH: =` %
19 | if defined _ARGS set _CMD=%_CMD% %_ARGS:"='%
20 | echo PowerShell %_CMD%
21 |
22 | REM Set a temporary execution policy in Process scope to run the PowerShell script without interruption.
23 | REM https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_execution_policies?#powershell-execution-policies
24 | PowerShell -EP Unrestricted %_CMD%
25 |
--------------------------------------------------------------------------------
/src/SymbolScan.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | setlocal
3 |
4 | REM The powershell script has the same path and base name as this batch script.
5 | set _PATH="%~dpn0.ps1"
6 | set _ARGS=%*
7 |
8 | REM Detect, warn, and remove Mark of the Web.
9 | (more < "%~dpn0.ps1:Zone.Identifier") >nul 2>nul && (
10 | echo Unblocking downloaded PowerShell script: %~n0.ps1
11 | echo https://github.com/microsoft/MSO-Scripts/wiki/Frequently-Asked-Questions#policy
12 | echo:>"%~dpn0.ps1:Zone.Identifier"
13 | powershell unblock-file '%~dpn0.ps1' 2>nul
14 | echo:
15 | )
16 |
17 | REM Escape spaces and quotes for use with: -command
18 | set _CMD=-command %_PATH: =` %
19 | if defined _ARGS set _CMD=%_CMD% %_ARGS:"='%
20 | echo PowerShell %_CMD%
21 |
22 | REM Set a temporary execution policy in Process scope to run the PowerShell script without interruption.
23 | REM https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_execution_policies?#powershell-execution-policies
24 | PowerShell -EP Unrestricted %_CMD%
25 |
--------------------------------------------------------------------------------
/src/BETA/Generate-PmuRegFile.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | setlocal
3 |
4 | REM The powershell script has the same path and base name as this batch script.
5 | set _PATH="%~dpn0.ps1"
6 | set _ARGS=%*
7 |
8 | REM Detect, warn, and remove Mark of the Web.
9 | (more < "%~dpn0.ps1:Zone.Identifier") >nul 2>nul && (
10 | echo Unblocking downloaded PowerShell script: %~n0.ps1
11 | echo https://github.com/microsoft/MSO-Scripts/wiki/Frequently-Asked-Questions#policy
12 | echo:>"%~dpn0.ps1:Zone.Identifier"
13 | powershell unblock-file '%~dpn0.ps1' 2>nul
14 | echo:
15 | )
16 |
17 | REM Escape spaces and quotes for use with: -command
18 | set _CMD=-command %_PATH: =` %
19 | if defined _ARGS set _CMD=%_CMD% %_ARGS:"='%
20 | echo PowerShell %_CMD%
21 |
22 | REM Set a temporary execution policy in Process scope to run the PowerShell script without interruption.
23 | REM https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_execution_policies?#powershell-execution-policies
24 | PowerShell -EP Unrestricted %_CMD%
25 |
--------------------------------------------------------------------------------
/src/OETW/MsoEtwCM.man:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
9 |
10 |
11 |
16 |
17 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/src/TraceCPU.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | setlocal
3 |
4 | REM The powershell script has the same path and base name as this batch script.
5 | set _PATH="%~dpn0.ps1"
6 | set _ARGS=%*
7 |
8 | REM Detect, warn, and remove Mark of the Web.
9 | set TraceThis=%~n0.ps1
10 | set Include=INCLUDE*.ps1
11 | (more < "%~dp0%TraceThis%:Zone.Identifier") >nul 2>nul && (
12 | echo Unblocking downloaded PowerShell scripts: %TraceThis%, %Include%
13 | echo https://github.com/microsoft/MSO-Scripts/wiki/Frequently-Asked-Questions#policy
14 | for %%f in ("%~dp0%TraceThis%","%~dp0%Include%") do echo %%~nxf & echo:>"%%~f:Zone.Identifier"
15 | echo:
16 | )
17 |
18 | REM Escape spaces and quotes for use with: -command
19 | set _CMD=-command %_PATH: =` %
20 | if defined _ARGS set _CMD=%_CMD% %_ARGS:"='%
21 | echo PowerShell %_CMD%
22 |
23 | REM Set a temporary execution policy in Process scope to run the PowerShell script without interruption.
24 | REM https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_execution_policies?#powershell-execution-policies
25 | PowerShell -EP Unrestricted %_CMD%
26 |
--------------------------------------------------------------------------------
/src/TraceHeap.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | setlocal
3 |
4 | REM The powershell script has the same path and base name as this batch script.
5 | set _PATH="%~dpn0.ps1"
6 | set _ARGS=%*
7 |
8 | REM Detect, warn, and remove Mark of the Web.
9 | set TraceThis=%~n0.ps1
10 | set Include=INCLUDE*.ps1
11 | (more < "%~dp0%TraceThis%:Zone.Identifier") >nul 2>nul && (
12 | echo Unblocking downloaded PowerShell scripts: %TraceThis%, %Include%
13 | echo https://github.com/microsoft/MSO-Scripts/wiki/Frequently-Asked-Questions#policy
14 | for %%f in ("%~dp0%TraceThis%","%~dp0%Include%") do echo %%~nxf & echo:>"%%~f:Zone.Identifier"
15 | echo:
16 | )
17 |
18 | REM Escape spaces and quotes for use with: -command
19 | set _CMD=-command %_PATH: =` %
20 | if defined _ARGS set _CMD=%_CMD% %_ARGS:"='%
21 | echo PowerShell %_CMD%
22 |
23 | REM Set a temporary execution policy in Process scope to run the PowerShell script without interruption.
24 | REM https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_execution_policies?#powershell-execution-policies
25 | PowerShell -EP Unrestricted %_CMD%
26 |
--------------------------------------------------------------------------------
/src/TraceHandles.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | setlocal
3 |
4 | REM The powershell script has the same path and base name as this batch script.
5 | set _PATH="%~dpn0.ps1"
6 | set _ARGS=%*
7 |
8 | REM Detect, warn, and remove Mark of the Web.
9 | set TraceThis=%~n0.ps1
10 | set Include=INCLUDE*.ps1
11 | (more < "%~dp0%TraceThis%:Zone.Identifier") >nul 2>nul && (
12 | echo Unblocking downloaded PowerShell scripts: %TraceThis%, %Include%
13 | echo https://github.com/microsoft/MSO-Scripts/wiki/Frequently-Asked-Questions#policy
14 | for %%f in ("%~dp0%TraceThis%","%~dp0%Include%") do echo %%~nxf & echo:>"%%~f:Zone.Identifier"
15 | echo:
16 | )
17 |
18 | REM Escape spaces and quotes for use with: -command
19 | set _CMD=-command %_PATH: =` %
20 | if defined _ARGS set _CMD=%_CMD% %_ARGS:"='%
21 | echo PowerShell %_CMD%
22 |
23 | REM Set a temporary execution policy in Process scope to run the PowerShell script without interruption.
24 | REM https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_execution_policies?#powershell-execution-policies
25 | PowerShell -EP Unrestricted %_CMD%
26 |
--------------------------------------------------------------------------------
/src/TraceHeapEx.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | setlocal
3 |
4 | REM The powershell script has the same path and base name as this batch script.
5 | set _PATH="%~dpn0.ps1"
6 | set _ARGS=%*
7 |
8 | REM Detect, warn, and remove Mark of the Web.
9 | set TraceThis=%~n0.ps1
10 | set Include=INCLUDE*.ps1
11 | (more < "%~dp0%TraceThis%:Zone.Identifier") >nul 2>nul && (
12 | echo Unblocking downloaded PowerShell scripts: %TraceThis%, %Include%
13 | echo https://github.com/microsoft/MSO-Scripts/wiki/Frequently-Asked-Questions#policy
14 | for %%f in ("%~dp0%TraceThis%","%~dp0%Include%") do echo %%~nxf & echo:>"%%~f:Zone.Identifier"
15 | echo:
16 | )
17 |
18 | REM Escape spaces and quotes for use with: -command
19 | set _CMD=-command %_PATH: =` %
20 | if defined _ARGS set _CMD=%_CMD% %_ARGS:"='%
21 | echo PowerShell %_CMD%
22 |
23 | REM Set a temporary execution policy in Process scope to run the PowerShell script without interruption.
24 | REM https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_execution_policies?#powershell-execution-policies
25 | PowerShell -EP Unrestricted %_CMD%
26 |
--------------------------------------------------------------------------------
/src/TraceMemory.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | setlocal
3 |
4 | REM The powershell script has the same path and base name as this batch script.
5 | set _PATH="%~dpn0.ps1"
6 | set _ARGS=%*
7 |
8 | REM Detect, warn, and remove Mark of the Web.
9 | set TraceThis=%~n0.ps1
10 | set Include=INCLUDE*.ps1
11 | (more < "%~dp0%TraceThis%:Zone.Identifier") >nul 2>nul && (
12 | echo Unblocking downloaded PowerShell scripts: %TraceThis%, %Include%
13 | echo https://github.com/microsoft/MSO-Scripts/wiki/Frequently-Asked-Questions#policy
14 | for %%f in ("%~dp0%TraceThis%","%~dp0%Include%") do echo %%~nxf & echo:>"%%~f:Zone.Identifier"
15 | echo:
16 | )
17 |
18 | REM Escape spaces and quotes for use with: -command
19 | set _CMD=-command %_PATH: =` %
20 | if defined _ARGS set _CMD=%_CMD% %_ARGS:"='%
21 | echo PowerShell %_CMD%
22 |
23 | REM Set a temporary execution policy in Process scope to run the PowerShell script without interruption.
24 | REM https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_execution_policies?#powershell-execution-policies
25 | PowerShell -EP Unrestricted %_CMD%
26 |
--------------------------------------------------------------------------------
/src/TraceMondo.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | setlocal
3 |
4 | REM The powershell script has the same path and base name as this batch script.
5 | set _PATH="%~dpn0.ps1"
6 | set _ARGS=%*
7 |
8 | REM Detect, warn, and remove Mark of the Web.
9 | set TraceThis=%~n0.ps1
10 | set Include=INCLUDE*.ps1
11 | (more < "%~dp0%TraceThis%:Zone.Identifier") >nul 2>nul && (
12 | echo Unblocking downloaded PowerShell scripts: %TraceThis%, %Include%
13 | echo https://github.com/microsoft/MSO-Scripts/wiki/Frequently-Asked-Questions#policy
14 | for %%f in ("%~dp0%TraceThis%","%~dp0%Include%") do echo %%~nxf & echo:>"%%~f:Zone.Identifier"
15 | echo:
16 | )
17 |
18 | REM Escape spaces and quotes for use with: -command
19 | set _CMD=-command %_PATH: =` %
20 | if defined _ARGS set _CMD=%_CMD% %_ARGS:"='%
21 | echo PowerShell %_CMD%
22 |
23 | REM Set a temporary execution policy in Process scope to run the PowerShell script without interruption.
24 | REM https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_execution_policies?#powershell-execution-policies
25 | PowerShell -EP Unrestricted %_CMD%
26 |
--------------------------------------------------------------------------------
/src/TraceNetwork.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | setlocal
3 |
4 | REM The powershell script has the same path and base name as this batch script.
5 | set _PATH="%~dpn0.ps1"
6 | set _ARGS=%*
7 |
8 | REM Detect, warn, and remove Mark of the Web.
9 | set TraceThis=%~n0.ps1
10 | set Include=INCLUDE*.ps1
11 | (more < "%~dp0%TraceThis%:Zone.Identifier") >nul 2>nul && (
12 | echo Unblocking downloaded PowerShell scripts: %TraceThis%, %Include%
13 | echo https://github.com/microsoft/MSO-Scripts/wiki/Frequently-Asked-Questions#policy
14 | for %%f in ("%~dp0%TraceThis%","%~dp0%Include%") do echo %%~nxf & echo:>"%%~f:Zone.Identifier"
15 | echo:
16 | )
17 |
18 | REM Escape spaces and quotes for use with: -command
19 | set _CMD=-command %_PATH: =` %
20 | if defined _ARGS set _CMD=%_CMD% %_ARGS:"='%
21 | echo PowerShell %_CMD%
22 |
23 | REM Set a temporary execution policy in Process scope to run the PowerShell script without interruption.
24 | REM https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_execution_policies?#powershell-execution-policies
25 | PowerShell -EP Unrestricted %_CMD%
26 |
--------------------------------------------------------------------------------
/src/TraceOffice.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | setlocal
3 |
4 | REM The powershell script has the same path and base name as this batch script.
5 | set _PATH="%~dpn0.ps1"
6 | set _ARGS=%*
7 |
8 | REM Detect, warn, and remove Mark of the Web.
9 | set TraceThis=%~n0.ps1
10 | set Include=INCLUDE*.ps1
11 | (more < "%~dp0%TraceThis%:Zone.Identifier") >nul 2>nul && (
12 | echo Unblocking downloaded PowerShell scripts: %TraceThis%, %Include%
13 | echo https://github.com/microsoft/MSO-Scripts/wiki/Frequently-Asked-Questions#policy
14 | for %%f in ("%~dp0%TraceThis%","%~dp0%Include%") do echo %%~nxf & echo:>"%%~f:Zone.Identifier"
15 | echo:
16 | )
17 |
18 | REM Escape spaces and quotes for use with: -command
19 | set _CMD=-command %_PATH: =` %
20 | if defined _ARGS set _CMD=%_CMD% %_ARGS:"='%
21 | echo PowerShell %_CMD%
22 |
23 | REM Set a temporary execution policy in Process scope to run the PowerShell script without interruption.
24 | REM https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_execution_policies?#powershell-execution-policies
25 | PowerShell -EP Unrestricted %_CMD%
26 |
--------------------------------------------------------------------------------
/src/TraceOutlook.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | setlocal
3 |
4 | REM The powershell script has the same path and base name as this batch script.
5 | set _PATH="%~dpn0.ps1"
6 | set _ARGS=%*
7 |
8 | REM Detect, warn, and remove Mark of the Web.
9 | set TraceThis=%~n0.ps1
10 | set Include=INCLUDE*.ps1
11 | (more < "%~dp0%TraceThis%:Zone.Identifier") >nul 2>nul && (
12 | echo Unblocking downloaded PowerShell scripts: %TraceThis%, %Include%
13 | echo https://github.com/microsoft/MSO-Scripts/wiki/Frequently-Asked-Questions#policy
14 | for %%f in ("%~dp0%TraceThis%","%~dp0%Include%") do echo %%~nxf & echo:>"%%~f:Zone.Identifier"
15 | echo:
16 | )
17 |
18 | REM Escape spaces and quotes for use with: -command
19 | set _CMD=-command %_PATH: =` %
20 | if defined _ARGS set _CMD=%_CMD% %_ARGS:"='%
21 | echo PowerShell %_CMD%
22 |
23 | REM Set a temporary execution policy in Process scope to run the PowerShell script without interruption.
24 | REM https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_execution_policies?#powershell-execution-policies
25 | PowerShell -EP Unrestricted %_CMD%
26 |
--------------------------------------------------------------------------------
/src/TraceRegistry.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | setlocal
3 |
4 | REM The powershell script has the same path and base name as this batch script.
5 | set _PATH="%~dpn0.ps1"
6 | set _ARGS=%*
7 |
8 | REM Detect, warn, and remove Mark of the Web.
9 | set TraceThis=%~n0.ps1
10 | set Include=INCLUDE*.ps1
11 | (more < "%~dp0%TraceThis%:Zone.Identifier") >nul 2>nul && (
12 | echo Unblocking downloaded PowerShell scripts: %TraceThis%, %Include%
13 | echo https://github.com/microsoft/MSO-Scripts/wiki/Frequently-Asked-Questions#policy
14 | for %%f in ("%~dp0%TraceThis%","%~dp0%Include%") do echo %%~nxf & echo:>"%%~f:Zone.Identifier"
15 | echo:
16 | )
17 |
18 | REM Escape spaces and quotes for use with: -command
19 | set _CMD=-command %_PATH: =` %
20 | if defined _ARGS set _CMD=%_CMD% %_ARGS:"='%
21 | echo PowerShell %_CMD%
22 |
23 | REM Set a temporary execution policy in Process scope to run the PowerShell script without interruption.
24 | REM https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_execution_policies?#powershell-execution-policies
25 | PowerShell -EP Unrestricted %_CMD%
26 |
--------------------------------------------------------------------------------
/src/WPAP/ETW-Overhead.wpaProfile:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/src/BETA/TracePMC.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | setlocal
3 |
4 | REM The powershell script has the same path and base name as this batch script.
5 | set _PATH="%~dpn0.ps1"
6 | set _ARGS=%*
7 |
8 | REM Detect, warn, and remove Mark of the Web.
9 | set TraceThis=%~n0.ps1
10 | set Include=..\INCLUDE*.ps1
11 | (more < "%~dp0%TraceThis%:Zone.Identifier") >nul 2>nul && (
12 | echo Unblocking downloaded PowerShell scripts: %TraceThis%, %Include%
13 | echo https://github.com/microsoft/MSO-Scripts/wiki/Frequently-Asked-Questions#policy
14 | for %%f in ("%~dp0%TraceThis%","%~dp0%Include%") do echo %%~nxf & echo:>"%%~f:Zone.Identifier"
15 | echo:
16 | )
17 |
18 | REM Escape spaces and quotes for use with: -command
19 | set _CMD=-command %_PATH: =` %
20 | if defined _ARGS set _CMD=%_CMD% %_ARGS:"='%
21 | echo PowerShell %_CMD%
22 |
23 | REM Set a temporary execution policy in Process scope to run the PowerShell script without interruption.
24 | REM https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_execution_policies?#powershell-execution-policies
25 | PowerShell -EP Unrestricted %_CMD%
26 |
--------------------------------------------------------------------------------
/src/TraceFileDiskIO.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | setlocal
3 |
4 | REM The powershell script has the same path and base name as this batch script.
5 | set _PATH="%~dpn0.ps1"
6 | set _ARGS=%*
7 |
8 | REM Detect, warn, and remove Mark of the Web.
9 | set TraceThis=%~n0.ps1
10 | set Include=INCLUDE*.ps1
11 | (more < "%~dp0%TraceThis%:Zone.Identifier") >nul 2>nul && (
12 | echo Unblocking downloaded PowerShell scripts: %TraceThis%, %Include%
13 | echo https://github.com/microsoft/MSO-Scripts/wiki/Frequently-Asked-Questions#policy
14 | for %%f in ("%~dp0%TraceThis%","%~dp0%Include%") do echo %%~nxf & echo:>"%%~f:Zone.Identifier"
15 | echo:
16 | )
17 |
18 | REM Escape spaces and quotes for use with: -command
19 | set _CMD=-command %_PATH: =` %
20 | if defined _ARGS set _CMD=%_CMD% %_ARGS:"='%
21 | echo PowerShell %_CMD%
22 |
23 | REM Set a temporary execution policy in Process scope to run the PowerShell script without interruption.
24 | REM https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_execution_policies?#powershell-execution-policies
25 | PowerShell -EP Unrestricted %_CMD%
26 |
--------------------------------------------------------------------------------
/src/BETA/TraceEdgeChrome.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | setlocal
3 |
4 | REM The powershell script has the same path and base name as this batch script.
5 | set _PATH="%~dpn0.ps1"
6 | set _ARGS=%*
7 |
8 | REM Detect, warn, and remove Mark of the Web.
9 | set TraceThis=%~n0.ps1
10 | set Include=..\INCLUDE*.ps1
11 | (more < "%~dp0%TraceThis%:Zone.Identifier") >nul 2>nul && (
12 | echo Unblocking downloaded PowerShell scripts: %TraceThis%, %Include%
13 | echo https://github.com/microsoft/MSO-Scripts/wiki/Frequently-Asked-Questions#policy
14 | for %%f in ("%~dp0%TraceThis%","%~dp0%Include%") do echo %%~nxf & echo:>"%%~f:Zone.Identifier"
15 | echo:
16 | )
17 |
18 | REM Escape spaces and quotes for use with: -command
19 | set _CMD=-command %_PATH: =` %
20 | if defined _ARGS set _CMD=%_CMD% %_ARGS:"='%
21 | echo PowerShell %_CMD%
22 |
23 | REM Set a temporary execution policy in Process scope to run the PowerShell script without interruption.
24 | REM https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_execution_policies?#powershell-execution-policies
25 | PowerShell -EP Unrestricted %_CMD%
26 |
--------------------------------------------------------------------------------
/src/BETA/TraceNetwork.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | setlocal
3 |
4 | REM The powershell script has the same path and base name as this batch script.
5 | set _PATH="%~dpn0.ps1"
6 | set _ARGS=%*
7 |
8 | REM Detect, warn, and remove Mark of the Web.
9 | set TraceThis=%~n0.ps1
10 | set Include=..\INCLUDE*.ps1
11 | (more < "%~dp0%TraceThis%:Zone.Identifier") >nul 2>nul && (
12 | echo Unblocking downloaded PowerShell scripts: %TraceThis%, %Include%
13 | echo https://github.com/microsoft/MSO-Scripts/wiki/Frequently-Asked-Questions#policy
14 | for %%f in ("%~dp0%TraceThis%","%~dp0%Include%") do echo %%~nxf & echo:>"%%~f:Zone.Identifier"
15 | echo:
16 | )
17 |
18 | REM Escape spaces and quotes for use with: -command
19 | set _CMD=-command %_PATH: =` %
20 | if defined _ARGS set _CMD=%_CMD% %_ARGS:"='%
21 | echo PowerShell %_CMD%
22 |
23 | REM Set a temporary execution policy in Process scope to run the PowerShell script without interruption.
24 | REM https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_execution_policies?#powershell-execution-policies
25 | PowerShell -EP Unrestricted %_CMD%
26 |
--------------------------------------------------------------------------------
/src/NetBlame/NetBlameAddIn.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net6.0
5 | AnyCPU
6 | true
7 | 1.6.0
8 |
9 |
10 |
11 | AUX_TABLES
12 |
13 |
14 |
15 | AUX_TABLES
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) Microsoft Corporation.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE
22 |
--------------------------------------------------------------------------------
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | name: make-release
2 |
3 | on:
4 | workflow_dispatch:
5 | inputs:
6 | version:
7 | description: 'Release version'
8 | required: true
9 | type: string
10 |
11 | jobs:
12 | create-release:
13 | runs-on: windows-latest
14 | permissions:
15 | contents: write
16 | steps:
17 | - name: Check out repository
18 | uses: actions/checkout@v4
19 |
20 | - name: Setup .NET
21 | uses: actions/setup-dotnet@v4
22 | with:
23 | dotnet-version: '6.0'
24 |
25 | - name: Build NetBlame addin
26 | run: |
27 | dotnet build src\NetBlame\NetBlameAddIn.sln --configuration Release -p:Version=${{ inputs.version }}
28 | shell: cmd
29 |
30 | - name: Create ZIP archive with all scripts and binaries
31 | shell: pwsh
32 | run: make\CreateRelease.ps1 -NetBlameBuild "src\NetBlame\bin\Release\net6.0" -WorkingDir bin -OutputZip "bin\MSO-Scripts-${{ inputs.version }}.zip"
33 |
34 | - name: Publish release
35 | run: gh release create version_${{ inputs.version }} --title "Release ${{ inputs.version }}" "bin\MSO-Scripts-${{ inputs.version }}.zip" --notes "Manual release"
36 | env:
37 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
38 |
--------------------------------------------------------------------------------
/src/BETA/ReadMe.txt:
--------------------------------------------------------------------------------
1 | Copyright (c) Microsoft Corporation. Licensed under the MIT License.
2 |
3 | Tracing CPU Counters / Processor Performance Monitor Unit (PMU) Events
4 |
5 | https://learn.microsoft.com/en-us/windows-hardware/test/wpt/recording-pmu-events
6 | https://devblogs.microsoft.com/performance-diagnostics/recording-hardware-performance-pmu-events-with-complete-examples/
7 |
8 | - To list available CPU Counters, run: WPR -PMCSources
9 | Or run: XPerf -PMCSources
10 | If there is only one counter listed, your machine is probably configured for HYPER-V.
11 |
12 | - To add additional CPU-specific counters:
13 | For Intel CPUs, run: Generate-PmuRegFile -Description
14 | Then run RegEdit on the generated .REG file. Then restart the OS.
15 |
16 | - To trace Cycles per Instruction, run: TracePMC Start -CPI
17 | Or run: PMC.bat
18 |
19 | - To trace Branch Mispredicts and Cache Misses, run: TracePMC Start -PMC *
20 | Or run: PMCs.bat
21 |
22 | - To sample-trace specific CPU counters, run: TracePMC start -PMC Counter1[,Counter2[,...]]
23 | Or run: PMCs.bat Counter1 [Counter2 [...]]
24 |
25 | - To trace specific CPU counters at each CSwitch, run: PMC Counter1 [Counter2 [...]]
26 |
27 | - To view the resulting trace file, run: TracePMC View [-Path \.etl]
28 | Or run: WPA \.etl -profile .\WPAP\CPUCounters.wpaProfile
29 |
--------------------------------------------------------------------------------
/src/NetBlame/Providers/WinsockNameRes.cs:
--------------------------------------------------------------------------------
1 | // Copyright(c) Microsoft Corporation.
2 | // Licensed under the MIT License.
3 |
4 | using System;
5 | using System.Net;
6 |
7 | using Microsoft.Windows.EventTracing.Events;
8 |
9 |
10 | namespace NetBlameCustomDataSource.WinsockNameRes
11 | {
12 | public class WinsockNameResolution
13 | {
14 | public static readonly Guid guid = new Guid("{55404e71-4db9-4deb-a5f5-8f86e46dde56}"); // Microsoft-Windows-Winsock-NameResolution
15 |
16 | readonly AllTables allTables;
17 |
18 | public WinsockNameResolution(in AllTables _allTables) { this.allTables = _allTables; }
19 |
20 | public void Dispatch(in IGenericEvent evtGeneric)
21 | {
22 | const int GetAddrInfo_Stop = 1001;
23 | const int GetAddrInfoX_Stop = 1004;
24 | const uint S_OK = 0;
25 |
26 | switch (evtGeneric.Id)
27 | {
28 | case GetAddrInfo_Stop:
29 | case GetAddrInfoX_Stop:
30 | if (evtGeneric.GetUInt32("Status") == S_OK)
31 | {
32 | // If the server name is NOT an address, add it to the DNS table.
33 | string strNodeName = evtGeneric.GetString("NodeName");
34 | if (String.IsNullOrWhiteSpace(strNodeName) || !IPAddress.TryParse(strNodeName, out IPAddress ipAddress))
35 | {
36 | this.allTables.dnsTable.ParseDNSEntries(strNodeName, evtGeneric.GetString("Result"));
37 | }
38 | }
39 | break;
40 | }
41 | }
42 | }
43 | }
--------------------------------------------------------------------------------
/src/BETA/OETW/ReadMe.txt:
--------------------------------------------------------------------------------
1 | Copyright (c) Microsoft Corporation. Licensed under the MIT License.
2 |
3 | These are manifest files for Office ETW logging providers.
4 | https://learn.microsoft.com/en-us/windows-hardware/test/weg/instrumenting-your-code-with-etw#implementing-etw-instrumentation
5 |
6 | MSO-Scripts registers these providers automatically when needed.
7 |
8 | A. MSEdge_Stable {3A5F2396-5C8F-4F1F-9B67-6CCA6C990E61} EdgeETW.man
9 | B. MSEdge_Canary {C56B8664-45C5-4E65-B3C7-A8D6BD3F2E67} EdgeETW.man
10 | C. MSEdge_Beta {BD089BAA-4E52-4794-A887-9E96868570D2} EdgeETW.man
11 | D. MSEdge_Dev {D30B5C9F-B58F-4DC9-AFAF-134405D72107} EdgeETW.man
12 | E. MSEdge_Internal {49C85E08-E8A5-49D6-81EA-7270531EC8AF} EdgeETW.man
13 | F. MSEdge_WebView {E16EC3D2-BB0F-4E8F-BDB8-DE0BEA82DC3D} EdgeETW.man
14 | G. Chrome {D2D578D9-2936-45B6-A09f-30E32715F42D} ChromeETW.man
15 |
16 | Present in:
17 | .\WPRP\MSEdge.wprp
18 | ..\WPRP\EdgeChrome.wprp
19 |
20 | To register the provider in a Trace* script:
21 | - Call: EnsureETWProvider(".\OETW\MsoEtwXX.man")
22 |
23 | To manually register the provider on your machine:
24 | - Copy MsoEtwXX.man and MsoEtwXX.res to your machine.
25 | - Run as Admin: wevtutil im \MsoEtwXX.man /rf:"\MsoEtwXX.res" /mf:"\MsoEtwXX.res"
26 |
27 | To manually unregister the provider:
28 | - Run as Admin: wevtutil um \MsoEtwXX.man
29 |
--------------------------------------------------------------------------------
/src/NetBlame/NetBlameAddIn.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.30320.27
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NetBlameAddIn", "NetBlameAddIn.csproj", "{1EC08A8C-7085-46E6-9360-6A6FF7CA062E}"
7 | EndProject
8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{89CCB51E-BA45-4F6A-8C22-1EC840263081}"
9 | ProjectSection(SolutionItems) = preProject
10 | .editorconfig = .editorconfig
11 | EndProjectSection
12 | EndProject
13 | Global
14 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
15 | Debug|Any CPU = Debug|Any CPU
16 | Release|Any CPU = Release|Any CPU
17 | EndGlobalSection
18 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
19 | {1EC08A8C-7085-46E6-9360-6A6FF7CA062E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
20 | {1EC08A8C-7085-46E6-9360-6A6FF7CA062E}.Debug|Any CPU.Build.0 = Debug|Any CPU
21 | {1EC08A8C-7085-46E6-9360-6A6FF7CA062E}.Release|Any CPU.ActiveCfg = Release|Any CPU
22 | {1EC08A8C-7085-46E6-9360-6A6FF7CA062E}.Release|Any CPU.Build.0 = Release|Any CPU
23 | EndGlobalSection
24 | GlobalSection(SolutionProperties) = preSolution
25 | HideSolutionNode = FALSE
26 | EndGlobalSection
27 | GlobalSection(ExtensibilityGlobals) = postSolution
28 | SolutionGuid = {6E14B2BE-D7E9-4B12-8950-5149603255D5}
29 | EndGlobalSection
30 | EndGlobal
31 |
--------------------------------------------------------------------------------
/src/OETW/ReadMe.txt:
--------------------------------------------------------------------------------
1 | Copyright (c) Microsoft Corporation. Licensed under the MIT License.
2 |
3 | These are manifest files for Office ETW logging providers.
4 | https://learn.microsoft.com/en-us/windows-hardware/test/weg/instrumenting-your-code-with-etw#implementing-etw-instrumentation
5 |
6 | MSO-Scripts registers these providers automatically when needed.
7 |
8 | A. Microsoft-Office-Events {8736922d-E8B2-47eb-8564-23E77E728CF3} MsoEtwCM.man
9 | B. OfficeLoggingLiblet {F50D9315-E17E-43C1-8370-3EDF6CC057BE} MsoEtwCM.man
10 | C. Microsoft-Office-Threadpool {a019725f-cff1-47e8-8c9e-8fe2635b6388} MsoEtwTP.man
11 | D. OfficeDispatchQueue {559a5658-8100-4d84-b756-0a47a476280c} MsoEtwDQ.man
12 | E. OfficeAirSpace {f562bb8e-422d-4b5c-b20e-90d710f7d11c} MsoEtwAS.man
13 |
14 | Present in:
15 | A. Microsoft-Office-Events is present in most WPRP files. It is (usually) pre-registered.
16 | B. OfficeProviders.wprp
17 | C. ThreadPool*.wprp, Network*.wprp
18 | D. ThreadPool*.wprp, Network*.wprp
19 | E. OfficeProviders.wprp
20 |
21 | To register the provider in a Trace* script:
22 | - Call: EnsureETWProvider(".\OETW\MsoEtwXX.man")
23 |
24 | To manually register the provider on your machine:
25 | - Copy MsoEtwXX.man and MsoEtwXX.res to your machine.
26 | - Run as Admin: wevtutil im \MsoEtwXX.man /rf:"\MsoEtwXX.res" /mf:"\MsoEtwXX.res"
27 |
28 | To manually unregister the provider:
29 | - Run as Admin: wevtutil um \MsoEtwXX.man
30 |
--------------------------------------------------------------------------------
/make/CreateRelease.ps1:
--------------------------------------------------------------------------------
1 | Param
2 | (
3 | [string]$NetBlameBuild,
4 | [string]$WorkingDir,
5 | [string]$OutputZip
6 | )
7 |
8 | $WorkingDir = "$WorkingDir\MSO-Scripts"
9 |
10 | # Create working directory to copy artifacts
11 | New-Item -ItemType Directory -Path $WorkingDir
12 |
13 | # Copy all main scripts
14 | Get-ChildItem -Path "src" -File | Copy-Item -Destination $WorkingDir
15 |
16 | # Copy BETA scripts
17 | Copy-Item -Path "src\BETA" -Destination "$WorkingDir\BETA" -Recurse
18 |
19 | # Copy ADDIN binaries from NetBlame build
20 | $AddinDir = "$WorkingDir\BETA\ADDIN"
21 | Get-ChildItem -Path $NetBlameBuild -File | Copy-Item -Destination $AddinDir
22 |
23 | $Platforms = 'arm64', 'x64'
24 | $Binaries = 'msdia140.dll', 'perfcore.dll', 'perf_nt.dll', 'perf_dynamic.dll', 'symcache.dll', 'symsrv.dll'
25 |
26 | ForEach ($platform in $Platforms) {
27 | $PlatformDir = "$AddinDir\$platform"
28 | New-Item -ItemType Directory -Path "$PlatformDir\wpt"
29 | ForEach ($binary in $Binaries) {
30 | Copy-Item -Path "$NetBlameBuild\$platform\wpt\$binary" -Destination "$PlatformDir\wpt"
31 | }
32 | }
33 |
34 | # Copy remaing data
35 | Copy-Item -Path "src\OETW" -Destination "$WorkingDir\OETW" -Recurse
36 | Copy-Item -Path "src\PreWin10" -Destination "$WorkingDir\PreWin10" -Recurse
37 | Copy-Item -Path "src\WPAP" -Destination "$WorkingDir\WPAP" -Recurse
38 | Copy-Item -Path "src\WPRP" -Destination "$WorkingDir\WPRP" -Recurse
39 |
40 | Compress-Archive -Path $WorkingDir -DestinationPath $OutputZip
41 |
--------------------------------------------------------------------------------
/SUPPORT.md:
--------------------------------------------------------------------------------
1 | # Support
2 |
3 | MSO-Scripts facilitates the use of Microsoft's Event Tracing for Windows ([ETW](https://learn.microsoft.com/en-us/windows-hardware/drivers/devtest/event-tracing-for-windows--etw-)) technology, including [WPR](https://learn.microsoft.com/en-us/windows-hardware/test/wpt/introduction-to-wpr) and [WPA](https://learn.microsoft.com/en-us/windows-hardware/test/wpt/windows-performance-analyzer).
4 |
5 | The scripts are intended to be self-service, [well documented](../../wiki), and highly customizable:
6 | - Start with the 'CUSTOMIZE THIS' section of any script file: Trace*.ps1
7 | - Run any script (Trace*.ps1) with `-Verbose` to reveal its underlying actions and how it invokes WPR or WPA.
8 | - Refer to the wiki topic: [Customize Tracing](../../wiki/Customize-Tracing)
9 |
10 | For new combinations of tracing and logging providers to suit your needs, please make use of these resources to create your own customized version.
11 |
12 | ## How to file issues and get help
13 |
14 | These scripts are designed to simplify complex tracing/logging scenarios on Microsoft Windows and also handle potential error conditions. The ever evolving Windows platform may necessitate occasional script updates and corrections to operate well in common environments. Similarly, [stacktags](https://learn.microsoft.com/en-us/windows-hardware/test/wpt/stack-tags) are based on module and function names, while [regions-of-interested](https://learn.microsoft.com/en-us/windows-hardware/test/wpt/creating-a-regions-of-interest-file) are based on internal logging mechanisms, all of which are subject to change.
15 |
16 | Contributions are welcome.
17 |
18 | This project uses GitHub Issues to track bugs and feature requests. Please search the existing issues before filing new issues to avoid duplicates.
19 |
20 | ## Microsoft Support Policy
21 |
22 | Support for this **PROJECT or PRODUCT** is limited to the resources listed above.
23 |
--------------------------------------------------------------------------------
/src/NetBlame/Providers/WebIO-Layout.md:
--------------------------------------------------------------------------------
1 | Copyright (c) Microsoft Corporation. Licensed under the MIT License.
2 |
3 | ```
4 | WebIO (the core of the WinHTTP Network Stack)
5 | Session -> Request -> Connection -> Socket -> (TCB)
6 |
7 | There may be multiple Requests per Session.
8 | Connections may be shared/reused across Requests.
9 | Here, separate/linked Connection objects represent a shared Connection, one copy per Request.
10 | A Connection can link to several Sockets, when several IP addresses correspond to a server.
11 | Each socket is tied to a TCB: Transfer Control Block (TcpIp)
12 |
13 | Session1
14 | Request1 <- Connection1a -> Socket1a -> TCB1
15 | ^ / Socket1b -> TCB2
16 | Session2 | / Socket1c -> TCB3
17 | Request2 <- Connection1b/
18 |
19 | Session1
20 | Request3 <- Connection2 -> Socket2 -> TCB4
21 |
22 |
23 | Session Request Connection Socket | TCB
24 | ID ID ID ID | ID
25 | Times Times Times Times | Times
26 | iReqFirst-> URL ----- URLx -- | PID
27 | XLink ---- XLink <-iRequest iTCB-> | TID
28 | <-iSession PID ^ TID | cbSend
29 | Method iCxnNext \ <-iCxn | cbRecv
30 | iDNS iAddr ^ |
31 | iSocketFirst->iSocketNext \ |
32 | cbSend
33 | cbRecv
34 |
35 | XLink = callstack info which is also linked to their invoking threadpool objects
36 | iDNS = index into the DNS table: server & various IP Addresses
37 | iAddr = index into the IP Address list of a DNS entry
38 | iSocketFirst/Next = linked list (by index) of related Sockets
39 | iCxn/Next = linked list (by index) of Connection objects which represent a connection shared across Request objects
40 |
41 | Traversal links look like this, with Sockets and Connections also linking themselves into subgroups.
42 | TCB <- Socket[<] -> Connection[<] -> Request -> Session
43 | ```
--------------------------------------------------------------------------------
/src/NetBlame/ClassicDataProcessor.cs:
--------------------------------------------------------------------------------
1 | // Copyright(c) Microsoft Corporation.
2 | // Licensed under the MIT License.
3 |
4 | using System;
5 | using System.Collections.Generic;
6 |
7 | using Microsoft.Windows.EventTracing; // ClassicEvent
8 |
9 | using NetBlameCustomDataSource.Thread;
10 | using NetBlameCustomDataSource.Thread.Classic;
11 | using NetBlameCustomDataSource.WThreadPool;
12 | using NetBlameCustomDataSource.WThreadPool.Classic;
13 |
14 | using static NetBlameCustomDataSource.Util;
15 |
16 | using Addr32 = System.UInt32;
17 | using Addr64 = System.UInt64;
18 |
19 |
20 | namespace NetBlameCustomDataSource.Classic
21 | {
22 | /*
23 | Parse classic events as they are pre-processed via: traceProcessor.Process()
24 | */
25 | class ClassicEventConsumer : IFilteredEventConsumer
26 | {
27 | public WThreadPoolEventConsumer wtpEventConsumer;
28 | public ThreadEventConsumer threadEventConsumer;
29 |
30 | public IReadOnlyList ProviderIds { get; }
31 |
32 | public ClassicEventConsumer(Guid[] rgGuid)
33 | {
34 | this.ProviderIds = rgGuid;
35 |
36 | wtpEventConsumer = new WThreadPoolEventConsumer();
37 | threadEventConsumer = new ThreadEventConsumer();
38 | }
39 |
40 | public void Process(EventContext ectx)
41 | {
42 | AssertCritical(ectx.Event.IsClassic);
43 |
44 | var evtClassic = ectx.Event.AsClassicEvent;
45 |
46 | if (!evtClassic.HasValue) return;
47 | if (evtClassic.Data.IsEmpty) return;
48 |
49 | if (evtClassic.ProviderId == WThreadPoolTable.guid) // Windows-ThreadPool
50 | {
51 | if (evtClassic.Is32Bit)
52 | wtpEventConsumer.WThreadPoolEvent(in evtClassic);
53 | else
54 | wtpEventConsumer.WThreadPoolEvent(in evtClassic);
55 | }
56 | else if (evtClassic.ProviderId == ThreadTable.guid) // Thread
57 | {
58 | threadEventConsumer.Process(in evtClassic);
59 | }
60 | else
61 | {
62 | AssertCritical(false);
63 | }
64 | } // Process
65 | } // ClassicEventConsumer
66 | } // NetBlameCustomDataSource.Classic
--------------------------------------------------------------------------------
/src/BETA/OETW/EdgeETW.man:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
12 |
13 |
19 |
20 |
26 |
27 |
33 |
34 |
40 |
41 |
47 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/src/NetBlame/README.md:
--------------------------------------------------------------------------------
1 | Copyright (c) Microsoft Corporation. Licensed under the MIT License.
2 |
3 | # NetBlame Add-in
4 |
5 | This add-in analyzes and summarizes network and thread pool ETW events:
6 |
7 | Microsoft-Windows-Winsock-NameResolution {55404e71-4db9-4deb-a5f5-8f86e46dde56}
8 | Microsoft-Windows-Winsock-AFD {e53c6823-7bb8-44bb-90dc-3f86090d48a6}
9 | Microsoft-Windows-DNS-Client {1c95126e-7eea-49a9-a3fe-a378b03ddb4d}
10 | Microsoft-Windows-WinINet {43d1a55c-76d6-4f7e-995c-64c711e5cafe}
11 | Microsoft-Windows-WinHttp {7d44233d-3055-4b9c-ba64-0d47ca40a232}
12 | Microsoft-Windows-WebIO {50b3e73c-9370-461d-bb9f-26f32d68887d}
13 | Microsoft-Windows-TCPIP {2f07e2ee-15db-40f1-90ef-9d7ba282188a}
14 | Windows-ThreadPool {c861d0e2-a2c1-4d36-9f9c-970bab943a12}
15 | Office-ThreadPool {A019725F-CFF1-47E8-8C9E-8FE2635B6388}
16 | OfficeDispatchQueue {559A5658-8100-4D84-B756-0A47A476280C}
17 |
18 | It is based on the [Microsoft Performance Toolkit SDK](https://github.com/microsoft/microsoft-performance-toolkit-sdk)
19 |
20 | This product includes GeoLocation data created by ip-api, available at https://ip-api.com
21 |
22 | # Build
23 |
24 | When a Release of this project is downloaded and unzipped, the NetBlame plug-in is ready to go.
25 |
26 | When this repository is cloned, the NetBlame plug-in must be built.
27 |
28 | See: https://github.com/microsoft/MSO-Scripts/wiki/Network-Activity#plugin
29 |
30 | `DotNet.exe build -c Release`
31 |
32 | # Run
33 |
34 | Requires WPA v11.7.383+ and SDK v1.2.2+
35 |
36 | `c:\MSO-Scripts\BETA\TraceNetwork View`
37 |
38 | The above script executes this WPA command to load the NetBlame plug-in and process the ETW trace:
39 |
40 | ```
41 | WPA -i "$Env:LocalAppData\MSO-Scripts\MSO-Trace-Network.etl"
42 | -processors "Event Tracing for Windows","Office_NetBlame"
43 | -addsearchdir "c:\MSO_Scripts\NetBlame\bin\Release\net6.0"
44 | -profile "c:\MSO-Scripts\BETA\WPAP\Network.wpaProfile"
45 | ```
46 |
47 | The script chooses one of these paths for -addsearchdir :
48 | - `"c:\MSO_Scripts\NetBlame\bin\Release\net6.0"`
49 | - `"c:\MSO_Scripts\NetBlame\bin\Debug\net6.0"`
50 | - `"c:\MSO_Scripts\BETA\ADDIN"`
51 |
--------------------------------------------------------------------------------
/src/NetBlame/NetBlameDataSource.cs:
--------------------------------------------------------------------------------
1 | // Copyright(c) Microsoft Corporation.
2 | // Licensed under the MIT License.
3 |
4 | using System.Collections.Generic;
5 | using System.Linq;
6 |
7 | using Microsoft.Performance.SDK; // Guard
8 | using Microsoft.Performance.SDK.Processing;
9 |
10 |
11 | namespace NetBlameCustomDataSource
12 | {
13 | // In order for a CustomDataSource to be recognized, it MUST satisfy the following:
14 | // a) Be a public type
15 | // b) Have a public parameterless constructor
16 | // c) Implement the ICustomDataSource interface
17 | // d) Be decorated with the CustomDataSource[Attribute] attribute
18 | // e) Be decorated with at least one of the derivatives of the DataSource[Attribute] attribute
19 |
20 | [ProcessingSource(
21 | "{67AE371A-9D97-4584-BCC1-F62B4D14737A}", // The GUID must be unique for your Custom Data Source.
22 | "Office_NetBlame", // The Custom Data Source MUST have a name.
23 | "Data source for the NetBlame Tool")] // The Custom Data Source MUST have a description.
24 | [FileDataSource(
25 | ".etl", // A file extension is REQUIRED.
26 | "Event Trace Log")] // A description is OPTIONAL. The description is what appears in the file open menu to help users understand what the file type actually is.
27 |
28 | public class NetBlameDataSource : ProcessingSource
29 | {
30 | public override ProcessingSourceInfo GetAboutInfo()
31 | {
32 | return new ProcessingSourceInfo()
33 | {
34 | Owners = null,
35 | ProjectInfo = new ProjectInfo() { Uri = "https://github.com/microsoft/MSO-Scripts" },
36 | CopyrightNotice = $"Copyright (C) Microsoft Corporation. Licensed under the MIT License.",
37 | LicenseInfo = null,
38 | AdditionalInformation = new string[] { GeoLocation.Attribution }
39 | };
40 | }
41 |
42 | protected override ICustomDataProcessor CreateProcessorCore(
43 | IEnumerable files,
44 | IProcessorEnvironment processorEnvironment,
45 | ProcessorOptions options)
46 | {
47 | Guard.NotNull(files, nameof(files));
48 | IDataSource[] allFiles = files.ToArray();
49 | Guard.IsTrue(allFiles.Length == 1);
50 |
51 | return new NetBlameDataProcessor(
52 | allFiles[0].Uri.LocalPath,
53 | options,
54 | this.ApplicationEnvironment,
55 | processorEnvironment);
56 | }
57 |
58 | // Already limited to ETL via: [FileDataSource()]
59 | protected override bool IsDataSourceSupportedCore(IDataSource ids) => true;
60 | }
61 |
62 | } // NetBlameCustomDataSource
63 |
--------------------------------------------------------------------------------
/src/NetBlame/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | ## Security
4 |
5 | Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet) and [Xamarin](https://github.com/xamarin).
6 |
7 | If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/security.md/definition), please report it to us as described below.
8 |
9 | ## Reporting Security Issues
10 |
11 | **Please do not report security vulnerabilities through public GitHub issues.**
12 |
13 | Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/security.md/msrc/create-report).
14 |
15 | If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/security.md/msrc/pgp).
16 |
17 | You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc).
18 |
19 | Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue:
20 |
21 | * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)
22 | * Full paths of source file(s) related to the manifestation of the issue
23 | * The location of the affected source code (tag/branch/commit or direct URL)
24 | * Any special configuration required to reproduce the issue
25 | * Step-by-step instructions to reproduce the issue
26 | * Proof-of-concept or exploit code (if possible)
27 | * Impact of the issue, including how an attacker might exploit the issue
28 |
29 | This information will help us triage your report more quickly.
30 |
31 | If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/security.md/msrc/bounty) page for more details about our active programs.
32 |
33 | ## Preferred Languages
34 |
35 | We prefer all communications to be in English.
36 |
37 | ## Policy
38 |
39 | Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/security.md/cvd).
40 |
41 |
42 |
--------------------------------------------------------------------------------
/src/NetBlame/Providers/WebIO.Connection.cs:
--------------------------------------------------------------------------------
1 | // Copyright(c) Microsoft Corporation.
2 | // Licensed under the MIT License.
3 |
4 | using System.Diagnostics;
5 | using IDVal = System.Int32; // type of Event.pid/tid / ideally: System.UInt32
6 | using QWord = System.UInt64;
7 |
8 | using static NetBlameCustomDataSource.Util;
9 |
10 | namespace NetBlameCustomDataSource.WebIO
11 | {
12 | public class Connection
13 | {
14 | public QWord qwConnection; // Other Requests may reference this Connection value.
15 | public uint cbSend;
16 | public uint cbRecv;
17 | public uint error;
18 | public Socket socket; // Other Requests may reference this socket.
19 | public string strHeader;
20 |
21 | // Thread for matching TcpIpEvents: ConnectionSocketConnect_Start matches TcpRequestConnect
22 | public IDVal tidTCB;
23 |
24 | // Thread of most recent Receive activity: ConnectionSocketReceive_Stop
25 | public IDVal tidRecv;
26 |
27 | // Because of a defect in the way ConnectionSocketSend.Stop works (in earlier versions of Windows),
28 | // we may have to collect cbSend indirectly. See SendSocketTCB.
29 |
30 | // Thread of most recent Send activity, between: ConnectionSocketSend_Start/Stop
31 | public IDVal tidSend;
32 | public uint cbSendTCB;
33 |
34 | public QWord ctxSend;
35 | public QWord ctxRecv;
36 |
37 | // There's another one of these used by an earlier Request.
38 | public bool fDuplicate;
39 | #if DEBUG
40 | public bool fOutdated;
41 | public bool fTransferred;
42 | #endif // DEBUG
43 |
44 | public Connection(QWord qwConnection, Socket socket)
45 | {
46 | this.qwConnection = qwConnection;
47 | this.socket = socket;
48 | socket?.AddRef();
49 | }
50 |
51 | public bool MatchTCB(uint iTCB, uint iDNS, uint iAddr, IDVal tid)
52 | {
53 | if (tid != 0 && this.tidTCB != tid) return false;
54 | if (this.socket.iTCB != 0)
55 | return this.socket.iTCB == iTCB; // TCB + maybe tid: fairly confident
56 | else if (tid != 0)
57 | return this.socket.iDNS == iDNS && this.socket.iAddr == iAddr; // DNS + tid: fairly confident
58 | else
59 | return false; // no TCB, no tid: very uncertain
60 | }
61 |
62 | [Conditional("DEBUG")]
63 | public void TestSocket(in Microsoft.Windows.EventTracing.Events.IGenericEvent evt, QWord qwCxn)
64 | {
65 | QWord qwSocket = evt.TryGetUInt64("SocketHandle"); // ConnectSocketStop, etc.
66 | if (qwSocket == 0)
67 | qwSocket = evt.TryGetUInt64("Socket"); // ConnectSocketClose
68 | #if DEBUG
69 | AssertCritical(qwSocket != 0);
70 | AssertCritical(this.socket != null);
71 | AssertImportant(this.socket.qwSocket == qwSocket || (this.socket.FClosed && qwSocket == QWord.MaxValue));
72 | AssertImportant(this.socket.qwConnection == qwCxn);
73 | AssertImportant(this.qwConnection == qwCxn);
74 | #endif // DEBUG
75 | }
76 | }
77 | }
--------------------------------------------------------------------------------
/src/BETA/PMCs.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 |
3 | REM Copyright (c) Microsoft Corporation.
4 | REM Licensed under the MIT License.
5 |
6 | setlocal
7 |
8 | set _ETL_PATH="%LOCALAPPDATA%\MSO-Scripts\PMCs_XPerf.etl"
9 |
10 | REM Min Interval is usually 4096. Run: XPerf -PMCSources
11 | set _INTERVAL_=4096
12 |
13 | call :ParsePMC CacheMisses BranchMispredictions
14 |
15 | if [%1]==[-?] goto :Usage
16 | if [%1]==[/?] goto :Usage
17 |
18 | if not [%1]==[] call :ParsePMC %*
19 |
20 | set _TEMP_PATH="%TEMP%\PMCs_xperfT.etl"
21 | set _XPERF_PARAMS=-on PROC_THREAD+LOADER+PMC_PROFILE -StackWalk PmcInterrupt -PmcProfile %_PROFILE% %_PROFINT% -f %_TEMP_PATH%
22 |
23 | if defined OVerbose echo xperf %_XPERF_PARAMS%
24 | call xperf %_XPERF_PARAMS% || (
25 | if not defined OVerbose echo xperf %_XPERF_PARAMS%
26 | echo:
27 | call :TestAdmin
28 | if errorlevel 1 echo Be sure to run with Administrator permissions.& exit /b 2
29 | echo Run: XPerf -PMCSources
30 | echo Check that the counter is listed: %_PROFILE%
31 | echo If there is only one entry listed then this may be a HyperV server.
32 | exit /b 3
33 | )
34 |
35 | echo Tracing has begun. Exercise the code.
36 | @pause
37 | echo Processing...
38 |
39 | set _XPERF_PARAMS=-stop -d %_ETL_PATH%
40 | if defined OVerbose echo xperf %_XPERF_PARAMS%
41 | call xperf %_XPERF_PARAMS% || (
42 | if not defined OVerbose echo xperf %_XPERF_PARAMS%
43 | exit /b errorlevel
44 | )
45 |
46 | set _WPA_PARAMS=%_ETL_PATH% -symbols
47 | if not defined _NT_SYMBOL_PATH if defined _NT_SYMCACHE_PATH (
48 | set _WPA_PARAMS=%_WPA_PARAMS% -symcacheonly
49 | if defined OVerbose echo: & echo Enabling only SymCache: %_NT_SYMCACHE_PATH%
50 | if defined OVerbose echo https://learn.microsoft.com/en-us/windows-hardware/test/wpt/loading-symbols#symcache-path
51 | )
52 | set _WPA_PARAMS=%_WPA_PARAMS% -profile "%~dp0WPAP\CPUCounters.wpaProfile"
53 | echo:
54 | echo Launching WPA
55 | if defined OVerbose echo wpa %_WPA_PARAMS%
56 | start "WPA" /MAX /ABOVENORMAL wpa %_WPA_PARAMS%
57 |
58 | exit /b errorlevel
59 |
60 | :ParsePMC
61 | REM Expect names of Processor Monitor Counters. Run: WPR -PMCSources
62 | set _PROFILE=%1
63 | set _PROFINT=-SetProfInt %1 4096
64 | :PMCLoop
65 | shift
66 | if [%1]==[] exit /b
67 | set _PROFILE=%_PROFILE%,%1
68 | set _PROFINT=%_PROFINT% -SetProfInt %1 %_INTERVAL_%
69 | goto :PMCLoop
70 |
71 | :TestAdmin
72 | net session >nul 2>&1
73 | exit /b errorlevel
74 |
75 | :Usage
76 | echo Usage:
77 | echo %~nx0
78 | echo Sampled profiling: %_PROFILE%
79 | echo:
80 | echo %~nx0 [PMC1 [PMC2 ...]]
81 | echo Sampled profiling: PMC1,PMC2,...
82 | echo:
83 | echo PMC = Processor/Performance Monitor Counter
84 | echo For a list of available PMCs, run: XPerf -PMCSources
85 | echo To expand the list, run: Generate-PmuRegFile
86 | if not defined OVerbose echo: & echo Verbose output: set OVerbose=1
87 | echo:
88 | echo https://github.com/microsoft/MSO-Scripts/wiki/Customize-Tracing#pmu
89 | echo https://learn.microsoft.com/en-us/windows-hardware/test/wpt/recording-pmu-events
90 | exit /b 1
91 |
--------------------------------------------------------------------------------
/src/WPAP/OfficeSpecial.regions.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
--------------------------------------------------------------------------------
/src/NetBlame/Providers/WebIO.Session.cs:
--------------------------------------------------------------------------------
1 | // Copyright(c) Microsoft Corporation.
2 | // Licensed under the MIT License.
3 |
4 | using System.Collections.Generic;
5 |
6 | using Microsoft.Windows.EventTracing.Symbols;
7 |
8 | using NetBlameCustomDataSource.Link;
9 |
10 | using static NetBlameCustomDataSource.Util;
11 |
12 | using TimestampUI = Microsoft.Performance.SDK.Timestamp;
13 |
14 | using IDVal = System.Int32; // type of Event.pid/tid / ideally: System.UInt32
15 | using QWord = System.UInt64;
16 |
17 |
18 | namespace NetBlameCustomDataSource.WebIO
19 | {
20 | public class Session
21 | {
22 | public readonly QWord qwSession;
23 | #if DEBUG
24 | public readonly QWord qwHandle;
25 | #endif // DEBUG
26 |
27 | public readonly TimestampUI timeOpen;
28 | public TimestampUI timeClose;
29 |
30 | public uint iRequestFirst;
31 |
32 | public IDVal pid;
33 | public IDVal tidStack;
34 | public IStackSnapshot stack;
35 | public XLink xlink;
36 |
37 | public Session(QWord qwSession, QWord qwHandle, in TimestampUI timeStamp)
38 | {
39 | this.qwSession = qwSession;
40 | #if DEBUG
41 | this.qwHandle = qwHandle;
42 | #endif // DEBUG
43 |
44 | this.timeOpen = timeStamp;
45 | this.timeClose.SetMaxValue();
46 | }
47 | }
48 |
49 | public class SessionTable : List
50 | {
51 | // TODO: smarter capacity?
52 | public SessionTable(int capacity) : base(capacity) { }
53 |
54 | // 1-based index -> session or null
55 | public Session SessionFromI(uint iSession) => (iSession != 0) ? this[(int)iSession - 1] : null;
56 |
57 | public uint IFindSession(QWord qwSession, QWord qwHandle, in TimestampUI timeStamp)
58 | {
59 | for (int iSession = this.Count - 1; iSession >= 0; --iSession)
60 | {
61 | Session session = this[iSession];
62 | if (session.qwSession == qwSession && timeStamp.Between(session.timeOpen, session.timeClose))
63 | {
64 | #if DEBUG
65 | AssertImportant(FImplies(qwHandle != 0, qwHandle == session.qwHandle));
66 | #endif // DEBUG
67 | return (uint)iSession+1;
68 | }
69 | }
70 | return 0;
71 | }
72 |
73 | public void AddSession(QWord qwSession, QWord qwHandle, IDVal pidT, IDVal tidT, in TimestampUI timeStampUI, in IStackSnapshot stackT, in Thread.ThreadTable threadTable)
74 | {
75 | AssertImportant(IFindSession(qwSession, qwHandle, in timeStampUI) == 0);
76 |
77 | Session session = new Session(qwSession, qwHandle, in timeStampUI)
78 | {
79 | pid = pidT,
80 | tidStack = tidT,
81 | stack = stackT
82 | };
83 | session.xlink.GetLink(tidT, timeStampUI, in threadTable);
84 | this.Add(session);
85 | }
86 |
87 | public void CloseSession(QWord qwSession, QWord qwHandle, in TimestampUI timeStamp)
88 | {
89 | uint iSession = IFindSession(qwSession, qwHandle, timeStamp);
90 | if (iSession != 0)
91 | {
92 | Session session = SessionFromI(iSession);
93 | AssertImportant(timeStamp.Between(session.timeOpen, session.timeClose));
94 | AssertImportant(session.timeClose.HasMaxValue());
95 | session.timeClose = timeStamp;
96 | }
97 | }
98 | } // SessionTable
99 | } // namespace NetBlameCustomDataSource.WebIO
--------------------------------------------------------------------------------
/src/PreWin10/WPRP/JS.wprp:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
13 |
14 |
15 |
16 |
17 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
47 |
48 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
63 |
64 |
65 |
66 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
--------------------------------------------------------------------------------
/src/BETA/PMC.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 |
3 | REM Copyright (c) Microsoft Corporation.
4 | REM Licensed under the MIT License.
5 |
6 | setlocal
7 |
8 | REM This is the kernel event which collects the PMC events.
9 | REM Run: XPerf -providers K
10 | set _COLLECTOR=CSWITCH
11 |
12 | REM Run: XPerf -help stackwalk
13 | set _CSTACK=CSWITCH
14 |
15 | set _ETL_PATH="%LOCALAPPDATA%\MSO-Scripts\PMC_XPerf.etl"
16 |
17 | call :ParsePMC TotalCycles InstructionRetired
18 |
19 | if [%1]==[-?] goto :Usage
20 | if [%1]==[/?] goto :Usage
21 |
22 | if not [%1]==[] call :ParsePMC %*
23 |
24 | set _TEMP_PATH="%TEMP%\PMC_xperfT.etl"
25 | set _XPERF_PARAMS=-on PROC_THREAD+LOADER+%_COLLECTOR% -stackwalk %_CSTACK% -Pmc %_PROFILE% %_COLLECTOR% strict -f %_TEMP_PATH%
26 |
27 | if defined OVerbose echo xperf %_XPERF_PARAMS%
28 | call xperf %_XPERF_PARAMS% || (
29 | if not defined OVerbose echo xperf %_XPERF_PARAMS%
30 | echo:
31 | call :TestAdmin
32 | if errorlevel 1 echo Be sure to run with Administrator permissions.& exit /b 2
33 | echo Run: XPerf -PMCSources
34 | echo Check that the counter is listed: %_PROFILE%
35 | echo If there is only one entry listed then this may be a HyperV server.
36 | exit /b 3
37 | )
38 |
39 | echo Exercise the code. Tracing has begun: %_PROFILE% on %_COLLECTOR%
40 | @pause
41 | echo Processing...
42 |
43 | set _XPERF_PARAMS=-stop -d %_ETL_PATH%
44 | if defined OVerbose echo xperf %_XPERF_PARAMS%
45 | call xperf %_XPERF_PARAMS% || (
46 | if not defined OVerbose echo xperf %_XPERF_PARAMS%
47 | exit /b errorlevel
48 | )
49 |
50 | set _WPA_PARAMS=%_ETL_PATH% -symbols
51 | if not defined _NT_SYMBOL_PATH if defined _NT_SYMCACHE_PATH (
52 | set _WPA_PARAMS=%_WPA_PARAMS% -symcacheonly
53 | if defined OVerbose echo: & echo Enabling only SymCache: %_NT_SYMCACHE_PATH%
54 | if defined OVerbose echo https://learn.microsoft.com/en-us/windows-hardware/test/wpt/loading-symbols#symcache-path
55 | )
56 | set _WPA_PARAMS=%_WPA_PARAMS% -profile "%~dp0WPAP\CPUCounters.wpaProfile"
57 | echo:
58 | echo Launching WPA
59 | if defined OVerbose echo wpa %_WPA_PARAMS%
60 | start "WPA" /MAX /ABOVENORMAL wpa %_WPA_PARAMS%
61 |
62 | exit /b errorlevel
63 |
64 | :ParsePMC
65 | REM Expect names of Processor Monitor Counters. Run: WPR -PMCSources
66 | set _PROFILE=%1
67 | :PMCLoop
68 | shift
69 | if [%1]==[] exit /b
70 | set _PROFILE=%_PROFILE%,%1
71 | goto :PMCLoop
72 |
73 | :TestAdmin
74 | net session >nul 2>&1
75 | exit /b errorlevel
76 |
77 | :Usage
78 | echo Usage:
79 | echo %~nx0
80 | echo Tracing: %_PROFILE%
81 | echo Collected at each %_COLLECTOR%
82 | echo This is the Cycles per Instruction (CPI) configuration understood by WPA.
83 | echo:
84 | echo %~nx0 [PMC1 [PMC2 ...]]
85 | echo Tracing: PMC1,PMC2,...
86 | echo:
87 | echo PMC = Processor/Performance Monitor Counter
88 | echo For a list of available PMCs, run: XPerf -PMCSources
89 | echo To expand the list, run: Generate-PmuRegFile
90 | if not defined OVerbose echo: & echo Verbose output: set OVerbose=1
91 | echo:
92 | echo https://github.com/microsoft/MSO-Scripts/wiki/Customize-Tracing#pmu
93 | echo https://learn.microsoft.com/en-us/windows-hardware/test/wpt/recording-pmu-events
94 | exit /b 1
95 |
--------------------------------------------------------------------------------
/src/ResetWPA.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .NOTES
3 |
4 | Copyright (c) Microsoft Corporation.
5 | Licensed under the MIT License.
6 |
7 | .SYNOPSIS
8 |
9 | Reset the Windows Performance Analyzer (WPA)
10 | by removing data and configuration files.
11 |
12 | Preserves Window Preferences (including the Symbol Paths) if not -All.
13 | Saves a copy of WindowPreferences.xml to %TEMP%.
14 | #>
15 | [CmdletBinding()]
16 | Param (
17 | # Remove All: Do not preserve Window Preferences or Symbol Settings.
18 | [switch]$All = $false
19 | )
20 |
21 | $WPA_1A = "$env:TEMP\WpaPackage"
22 | $WPA_1B = "$env:TEMP\WPA"
23 | $WPA_1C = "$env:TEMP\WPA Recovered Profile"
24 | $WPA_1D = "$env:TEMP\Windows Performance Analyzer"
25 | $WPA_2 = "$env:USERPROFILE\Documents\WPA Files"
26 | $WPA_3 = "$env:LOCALAPPDATA\Windows Performance Analyzer"
27 | $WPA_4 = "$env:LOCALAPPDATA\wpa"
28 | $WPA_PREF = "WindowPreferences.xml"
29 |
30 |
31 | function DeleteFolder
32 | {
33 | Param (
34 | [string]$Path
35 | )
36 | Write-Verbose "Testing: $Path"
37 |
38 | if (Test-Path $Path -ErrorAction:SilentlyContinue -ErrorVariable Err)
39 | {
40 | Write-Output "Removing: $Path"
41 |
42 | # Avoid overlong path issues by using CMD's rmdir:
43 | Invoke-Expression "cmd.exe /c rmdir /s /q `"$Path`" 2>&1" -ErrorVariable Err >$Null
44 | # rmdir -Recurse "$Path" -ErrorAction:SilentlyContinue -ErrorVariable Err
45 | }
46 |
47 | if ($Err)
48 | {
49 | $Err = $($Err[0] -split "`n") # convert to one line
50 | Write-Output "$Err : $Path"
51 | }
52 | }
53 |
54 | # Main
55 |
56 | Write-Output "Resetting WPA settings and storage."
57 |
58 | DeleteFolder $WPA_1A
59 |
60 | DeleteFolder $WPA_1B
61 |
62 | DeleteFolder $WPA_1C
63 |
64 | DeleteFolder $WPA_1D
65 |
66 | DeleteFolder $WPA_2
67 |
68 | if ($All)
69 | {
70 | DeleteFolder $WPA_4
71 | }
72 |
73 | # Delete the "Windows Performance Analyzer" folder, but optionally save/restore WPA Window Settings: WindowsPreferences.xml
74 |
75 | $WPA_PREF_Src = "$WPA_3\$WPA_PREF"
76 | $WPA_PREF_Dst = "$env:TEMP\$WPA_PREF"
77 |
78 | $Err = $True
79 | if (Test-Path -PathType Leaf $WPA_PREF_Src -ErrorAction:SilentlyContinue)
80 | {
81 | # Save a copy of WindowPreferences.xml to %TEMP%.
82 | # Possibly restore it.
83 |
84 | Copy-Item $WPA_PREF_Src -Destination $WPA_PREF_Dst -Force -ErrorAction:SilentlyContinue -ErrorVariable Err
85 | }
86 |
87 | DeleteFolder $WPA_3
88 |
89 | if (!$Err)
90 | {
91 | # A copy of the WPA Windows Settings file was successfully saved.
92 | # Either restore it or (verbose) note that it was saved.
93 |
94 | $dir = mkdir $WPA_3 -ErrorAction:SilentlyContinue
95 |
96 | if (!$All)
97 | {
98 | Copy-Item $WPA_PREF_Dst $WPA_PREF_Src -ErrorAction:SilentlyContinue -ErrorVariable Err2
99 |
100 | if (!$Err2)
101 | {
102 | Write-Output "Restoring WPA Window Settings"
103 | }
104 | else
105 | {
106 | Write-Output "WPA Window Settings could not be restored to: `"$WPA_PREF_Src`""
107 | Write-Output "A copy was saved to: `"$WPA_PREF_Dst`""
108 | }
109 | }
110 | else
111 | {
112 | Write-Verbose "WPA Windows Settings were saved to: `"$WPA_PREF_Dst`""
113 | Write-Verbose "From: `"$WPA_PREF_Src`""
114 | }
115 | }
116 |
--------------------------------------------------------------------------------
/src/WPAP/VirtualAlloc.stacktags:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
--------------------------------------------------------------------------------
/src/NetBlame/Providers/WThreadPool.cs:
--------------------------------------------------------------------------------
1 | // Copyright(c) Microsoft Corporation.
2 | // Licensed under the MIT License.
3 |
4 | using System;
5 |
6 | using NetBlameCustomDataSource.WThreadPool.Callback;
7 | using NetBlameCustomDataSource.WThreadPool.Classic;
8 | using NetBlameCustomDataSource.WThreadPool.Timer;
9 |
10 |
11 | namespace NetBlameCustomDataSource.WThreadPool
12 | {
13 | public enum WTP : byte
14 | {
15 | // These are opcodes, not record IDs.
16 | // See ntwmi.w "Event Types for ThreadPool"
17 |
18 | CallbackEnqueue = 0x20, // 32
19 | CallbackDequeue = 0x21, // 33
20 | CallbackStart = 0x22, // 34
21 | CallbackStop = 0x23, // 35
22 | CallbackCancel = 0x24, // 36
23 | /*
24 | PoolCreate = 0x25, // 37 // PoolId:PTR
25 | PoolClose = 0x26, // 38 // PoolId:PTR
26 | */
27 | TimerSet = 0x2A, // 42
28 | TimerCancel = 0x2B, // 43
29 | TimerSetNTTimer = 0x2C, // 44 // unused
30 | TimerExpireBegin = 0x2E, // 46
31 | TimerExpireEnd = 0x2F, // 47
32 | TimerExpiration = 0x30, // 48
33 | }
34 |
35 |
36 | public class WThreadPoolTable
37 | {
38 | public readonly WTPCallbackTable wtpCallbackTable;
39 | public readonly WTPTimerTable wtpTimerTable;
40 |
41 | public WThreadPoolTable(int capacity, in AllTables _allTables)
42 | {
43 | wtpCallbackTable = new WTPCallbackTable(capacity, in _allTables);
44 | wtpTimerTable = new WTPTimerTable(capacity, in _allTables);
45 | }
46 |
47 |
48 | public static readonly Guid guid = new Guid("{c861d0e2-a2c1-4d36-9f9c-970bab943a12}"); // Windows-ThreadPool
49 |
50 | public void Dispatch(in AltClassicEvent evtClassic)
51 | {
52 | switch (evtClassic.IdEvent)
53 | {
54 | // ThreadPool Callback Events
55 |
56 | case WTP.CallbackEnqueue:
57 | wtpCallbackTable.Enqueue(in evtClassic);
58 | break;
59 |
60 | case WTP.CallbackDequeue:
61 | // Ensure that this thread is marked as WThreadPool.
62 | wtpCallbackTable.allTables.threadTable.SetThreadPoolType(evtClassic.idThread, Thread.ThreadClass.WThreadPool);
63 |
64 | wtpCallbackTable.Dequeue(in evtClassic);
65 | break;
66 |
67 | case WTP.CallbackStart: // High Traffic?
68 | wtpCallbackTable.StartExec(in evtClassic);
69 | break;
70 |
71 | case WTP.CallbackStop: // High Traffic?
72 | wtpCallbackTable.EndExec(in evtClassic);
73 | break;
74 |
75 | case WTP.CallbackCancel: // TODO: Test this!
76 | wtpCallbackTable.Cancel(in evtClassic);
77 | break;
78 |
79 | // Timer Events
80 |
81 | case WTP.TimerSet:
82 | wtpTimerTable.Set(in evtClassic);
83 | break;
84 |
85 | case WTP.TimerExpiration:
86 | // Ensure that this thread is marked as WThreadPool.
87 | wtpTimerTable.allTables.threadTable.SetThreadPoolType(evtClassic.idThread, Thread.ThreadClass.WThreadPool);
88 |
89 | wtpTimerTable.Expiration(in evtClassic);
90 | break;
91 |
92 | case WTP.TimerExpireBegin: // TODO: DEBUG
93 | wtpTimerTable.ExpireBegin(in evtClassic);
94 | break;
95 |
96 | case WTP.TimerExpireEnd:
97 | wtpTimerTable.ExpireEnd(in evtClassic);
98 | break;
99 |
100 | case WTP.TimerCancel:
101 | wtpTimerTable.Cancel(in evtClassic);
102 | break;
103 | } // switch evtClassic.IdEvent
104 | } // Dispatch
105 | } // WThreadPool
106 | } // WThreadPoolNS
--------------------------------------------------------------------------------
/src/WPRP/CLR.wprp:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
13 |
14 |
15 |
16 |
17 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
53 |
54 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
72 |
73 |
74 |
75 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
--------------------------------------------------------------------------------
/src/PreWin10/WPRP/CLR.wprp:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
13 |
14 |
15 |
16 |
17 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
54 |
55 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
71 |
72 |
73 |
74 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # MSO-Scripts
2 |
3 | ### _Democratizing Windows Performance Analysis_
4 |
5 | ## Documentation
6 |
7 | MSO-Scripts substantially facilitates the use of Microsoft's Event Tracing for Windows (ETW) technology for analyzing the resource consumption (CPU, Memory, I/O, Handles, Registry, ...) and performance behavior of Windows and its applications, particularly Microsoft Office.
8 |
9 | MSO-Scripts also [reveals detailed network activity](https://github.com/microsoft/MSO-Scripts/wiki/Network-Activity) by way of an add-in for the Windows Performance Analyzer (WPA).
10 |
11 | Please see [the wiki](../../wiki) for detailed documentation.
12 |
13 | ## Quick Start
14 |
15 | There are eleven customizable scripts for tracing various system resources:
16 | * TraceCPU
17 | * TraceFileDiskIO
18 | * TraceHandles (_Kernel, GDI, and USER handles_)
19 | * TraceHeap (_Windows Heap + VirtualAlloc_)
20 | * TraceHeapEx (_Windows Heap + VirtualAlloc + Handles_)
21 | * TraceMemory (_RAM usage, etc._)
22 | * TraceMondo (_CPU + FileDiskIO + Handles + Network + Defender_)
23 | * TraceNetwork (_Chromium, WinHTTP, WinINet, LDAP, WinSock, TcpIp_)
24 | * TraceOffice (_Excel, OneNote, PowerPoint, Word: ETW Trace and Office Logs_)
25 | * TraceOutlook (_ETW Trace and Office/Outlook Logs_)
26 | * TraceRegistry
27 |
28 | The scripts accept these tracing commands: Start, Stop, View, Status, Cancel
29 | These commands, except View, require Administrator privilege.
30 |
31 | To trace CPU activity:
32 | * Download and unzip [a recent Release of MSO-Scripts](https://github.com/microsoft/MSO-Scripts/releases), or clone the Repository: `<> Code ↓`
33 | * _MSO-Scripts_\\`TraceCPU Start`
34 | _Exercise the application/scenario._
35 | * _MSO-Scripts_\\`TraceCPU Stop`
36 | * _MSO-Scripts_\\`TraceCPU View` _Launches the [Windows Performance Analyzer](https://devblogs.microsoft.com/performance-diagnostics/wpa-intro/)_
37 |
38 | List all options for TraceCPU:
39 | * _MSO-Scripts_\\`TraceCPU -?`
40 |
41 | [See the Wiki: TraceCPU](https://github.com/microsoft/MSO-Scripts/wiki/CPU-and-Threads)
42 |
43 | ## Contributing
44 |
45 | This project welcomes contributions and suggestions. Most contributions require you to agree to a
46 | Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us
47 | the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com.
48 |
49 | When you submit a pull request, a CLA bot will automatically determine whether you need to provide
50 | a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions
51 | provided by the bot. You will only need to do this once across all repos using our CLA.
52 |
53 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
54 | For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or
55 | contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
56 |
57 | ## Trademarks
58 |
59 | This project may contain trademarks or logos for projects, products, or services. Authorized use of Microsoft
60 | trademarks or logos is subject to and must follow
61 | [Microsoft's Trademark & Brand Guidelines](https://www.microsoft.com/en-us/legal/intellectualproperty/trademarks/usage/general).
62 | Use of Microsoft trademarks or logos in modified versions of this project must not cause confusion or imply Microsoft sponsorship.
63 | Any use of third-party trademarks or logos are subject to those third-party's policies.
64 |
--------------------------------------------------------------------------------
/src/ReadMe.txt:
--------------------------------------------------------------------------------
1 | Copyright (c) Microsoft Corporation. Licensed under the MIT License.
2 |
3 | GOALS
4 |
5 | - It's easy to capture basic ETW traces of Office and other apps: CPU, Wait Analysis, Memory, Handles, File & Disk I/O, etc.
6 | - It's easy to analyze and understand the results.
7 | - It's easy to modify and to configure many combinations of data providers.
8 | - It works on Windows 10/11+, and as far back as Windows 7 / Server 2008-R2.
9 | - It requires no extra executables to be installed for trace collection (if Windows 10+).
10 | - It works with PowerShell (v2+), WPR (Windows Performance Recorder), and WPA (Windows Performance Analyzer).
11 |
12 | CUSTOMIZING RECORDING PROFILES
13 |
14 | MSO-Scripts includes a set of optimized recording profiles that will work well for many situations.
15 | They can also be customized.
16 |
17 | In Trace*.ps1, customize the recording profiles here:
18 |
19 | $TraceParams =
20 | @{
21 | RecordingProfiles =
22 | @(
23 | # This is the base recording profile:
24 | ".\WPRP\.wprp!"
25 |
26 | # *** Additional recording profile strings go here. ***
27 | )
28 |
29 | ...
30 | }
31 |
32 | Note that no .wprp file can be used more than once in a profiling session.
33 |
34 | Recording Profiles (Trace Collection Configuration Files) can take several forms:
35 |
36 | 1) Local profiles: ".\WPRP\SomeProfile.wprp!ProfileName"
37 | To list available profile names, run: WPR -profiles .\WPRP\.wprp
38 |
39 | ".\WPRP\FileDiskIO.wprp!FileIO"
40 | ".\WPRP\Handles.wprp!KernelHandles"
41 |
42 | Certain .wprp files have a version number in their name, which corresponds to the minimum version of WPR.
43 | For example, if the WPR version is 10.0.15002 or greater, then the newer version of Network.wprp will be used:
44 |
45 | ".\WPRP\Network.wprp!NetworkFull" becomes: ".\WPRP\Network.15002.wprp!NetworkFull"
46 |
47 | 2) OR built-in profiles
48 | To see a complete list, run: WPR -profiles
49 |
50 | "Registry"
51 | "DotNet"
52 |
53 | 3) OR other WPRP Recording Profiles: "\MyRecordingProfile.wprp!ProfileName"
54 |
55 | To see a list of available profiles, run: WPR -profiles \MyRecordingProfile.wprp
56 | https://learn.microsoft.com/en-us/windows-hardware/test/wpt/recording-profile-xml-reference
57 |
58 | "c:\MyProfiles\MyRecordingProfile.wprp!ProfileName"
59 |
60 | OPTIONAL ENVIRONMENT VARIABLES
61 |
62 | TRACE_PATH
63 | Path which receives generated traces and intermediate files. (Default = %LocalAppData%\MSO-Scripts)
64 |
65 | WPT_PATH
66 | Find wpr.exe and/or wpa.exe here from the Windows Performance Toolkit.
67 |
68 | WPT_WPRP
69 | Semi-colon separated list of additional WPR Recording Profiles (in any of the three formats listed above).
70 |
71 | WPT_XPERF
72 | Plus-sign separated list of additional ETW Providers (in XPerf -ON format): GUID|Name:KeywordFlags:Level:Stack
73 |
74 | WPT_MODE
75 | Special tracing mode - Shutdown
76 |
77 | _NT_SYMBOL_PATH
78 | Defines where to find and store symbol files (*.PDB). *** These files can be HUGE! ***
79 |
80 | _NT_SYMCACHE_PATH
81 | Defines where to find and store optimized symbol files (*.symcache).
82 |
83 | SYMBOL RESOLUTION
84 |
85 | https://github.com/microsoft/MSO-Scripts/wiki/Symbol-Resolution#native
86 |
87 | https://github.com/microsoft/MSO-Scripts/wiki/Advanced-Symbols#optimize
88 |
89 | If the _NT_SYM*_PATH environment variables are not set, the script for launching WPA will set default values.
90 | _NT_SYMBOL_PATH=cache*C:\Symbols;srv*https://msdl.microsoft.com/download/symbols
91 | _NT_SYMCACHE_PATH=C:\SymCache
92 |
93 | OLDER VERSIONS of the Windows Performance Toolkit WPT / WPA / WPR
94 |
95 | Scripts under the PreWin10 subfolder are for earlier versions of the Windows Performance Toolkit (WPT).
96 | They should run automatically, or they can be run directly from the PreWin10 subfolder.
97 |
--------------------------------------------------------------------------------
/src/PreWin10/TraceNetwork.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .NOTES
3 |
4 | Copyright (c) Microsoft Corporation.
5 | Licensed under the MIT License.
6 |
7 | .SYNOPSIS
8 |
9 | Capture and View an ETW trace:
10 | Network Activity
11 |
12 | .DESCRIPTION
13 |
14 | .\TraceNetwork Start [-Loop] [-CLR] [-JS]
15 | .\TraceNetwork Stop [-WPA]
16 | .\TraceNetwork View [-Path \MSO-Trace-Network.etl]
17 | .\TraceNetwork Status
18 | .\TraceNetwork Cancel
19 | -CLR: Resolve call stacks for C# (Common Language Runtime).
20 | -JS: Resolve call stacks for JavaScript.
21 | -WPA: Launch the WPA viewer (Windows Performance Analyzer) with the collected trace.
22 | -Path: Optional path to a previously collected trace.
23 | -Verbose
24 |
25 | These scripts work with pre-Win10 versions of the Windows Performance Toolkit (WPT).
26 |
27 | .LINK
28 |
29 | https://learn.microsoft.com/en-us/windows-hardware/test/wpt/event-tracing-for-windows
30 | https://learn.microsoft.com/en-us/shows/defrag-tools/39-windows-performance-toolkit
31 | #>
32 |
33 | [CmdletBinding(DefaultParameterSetName = "Start")]
34 | Param(
35 | # "Start, Stop, Status, Cancel, View"
36 | [Parameter(Position=0)]
37 | [string]$Command,
38 |
39 | # Record only the last few minutes of activity (circular memory buffer).
40 | [Parameter(ParameterSetName="Start")]
41 | [switch]$Loop,
42 |
43 | # "Support Common Language Runtime / C#"
44 | [Parameter(ParameterSetName="Start")]
45 | [switch]$CLR,
46 |
47 | # "Support JavaScript"
48 | [Parameter(ParameterSetName="Start")]
49 | [switch]$JS,
50 |
51 | # "Launch WPA after collecting the trace"
52 | [Parameter(ParameterSetName="Stop")]
53 | [switch]$WPA,
54 |
55 | # "Optional path to a previously collected trace: MSO-Trace-Network.etl"
56 | [Parameter(ParameterSetName="View")]
57 | [string]$Path
58 |
59 | # [switch]$Verbose # implicit
60 | )
61 |
62 | if (!$Path) { $Path = $Null } # for PSv2
63 |
64 | # ===== CUSTOMIZE THIS =====
65 |
66 | $TraceParams =
67 | @{
68 | RecordingProfiles =
69 | @(
70 | # This XML file contains tracing parameters organized by ProfileName.
71 | # To see the available profiles, run: wpr -profiles .\WPRP\Network.wprp
72 | ".\WPRP\Network.wprp.Verbose"
73 | ".\WPRP\OfficeProviders.wprp.Light" # Code Markers
74 | <#
75 | ^^^ The first entry is the base recording profile for this script.
76 | vvv Additional recording profile string(s) follow. See ReadMe.txt
77 |
78 | "Registry" # Built-in
79 | ".\WPRP\FileDiskIO.wprp.Verbose"
80 | "c:\MyProfiles\MyRecordingProfile.wprp"
81 | #>
82 | )
83 |
84 | # This is the arbitrary name of the tracing session/instance.
85 | InstanceName = "MSO-Trace-Network"
86 | }
87 |
88 | $ViewerParams =
89 | @{
90 | # This configuration file organizes the data in the WPA viewer.
91 | # https://learn.microsoft.com/en-us/windows-hardware/test/wpt/view-profiles
92 | ViewerConfig = ".\WPAP\Network.wpaProfile"
93 |
94 | # The trace file name is: .etl
95 | TraceName = $TraceParams.InstanceName
96 |
97 | # Optional alternate path to a previously collected ETL trace:
98 | TraceFilePath = $Path
99 | }
100 | # ===== END CUSTOMIZE ====
101 |
102 | if (!$script:PSScriptRoot) { $script:PSScriptRoot = Split-Path -Parent -Path $script:MyInvocation.MyCommand.Definition } # for PSv2
103 | $script:ScriptHomePath = $PSScriptRoot
104 | $script:ScriptRootPath = Resolve-Path "$PSScriptRoot\.."
105 | $script:PSScriptParams = $script:PSBoundParameters # volatile
106 |
107 | . "$ScriptRootPath\INCLUDE.ps1"
108 |
109 | # Main
110 |
111 | $Result = ProcessTraceCommand $Command @TraceParams -Loop:$Loop -CLR:$CLR -JS:$JS
112 | ValidateResult "ProcessTraceCommand" $Result
113 |
114 | switch ($Result)
115 | {
116 | Started { Write-Msg "ETW Network tracing has begun.`nExercise the application, then run: $(GetScriptCommand) Stop [-WPA]`n" }
117 | Collected { WriteTraceCollected $TraceParams.InstanceName; if ($WPA) { LaunchViewer @ViewerParams } }
118 | View { LaunchViewer @ViewerParams }
119 | Error { exit 1 }
120 | }
121 |
122 | exit 0 # Success
123 |
--------------------------------------------------------------------------------
/src/BETA/WPRP/RPC.wprp:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
13 |
14 |
15 |
16 |
17 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
42 |
43 |
44 |
45 |
46 |
47 |
50 |
51 |
52 |
53 |
54 |
60 |
61 |
62 |
67 |
68 |
69 |
70 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
89 |
90 |
91 |
92 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
--------------------------------------------------------------------------------
/src/NetBlame/Auxiliary/GeoLocation.cs:
--------------------------------------------------------------------------------
1 | // Copyright(c) Microsoft Corporation.
2 | // Licensed under the MIT License.
3 |
4 | using System.Net;
5 | using System.Net.Http;
6 | using System.IO;
7 |
8 | using System.Text.Json;
9 | using System.Text.Json.Serialization;
10 |
11 | using static NetBlameCustomDataSource.Util;
12 |
13 | namespace NetBlameCustomDataSource
14 | {
15 | /*
16 | This component uses the free IP-GeoLocation API from ip-api.
17 | - Service: https://ip-api.com
18 | - Attribution: Geolocation data provided by ip-api.com
19 | - License: Free for non-commercial use only
20 | - Rate limit: 45 requests per minute (free tier)
21 | */
22 | static class GeoLocation
23 | {
24 | public static string Attribution => "\nIP GeoLocation powered by ip-api.com – the free, non-commercial API.\nhttps://www.ip-api.com";
25 |
26 | static string strGeoService = "ip-api.com";
27 | static string strGetGeoService1 = "http://ip-api.com/json/";
28 | static string strGetGeoService2 = "?fields=status,message,country,regionName,city";
29 |
30 | public class Place
31 | {
32 | [JsonPropertyName("status")]
33 | public string Status { get; set; }
34 |
35 | [JsonPropertyName("message")]
36 | public string Message { get; set; }
37 |
38 | [JsonPropertyName("country")]
39 | public string Country { get; set; }
40 |
41 | [JsonPropertyName("regionName")]
42 | public string Region { get; set; }
43 |
44 | [JsonPropertyName("city")]
45 | public string City { get; set; }
46 | }
47 |
48 | /*
49 | Return a string representing the geolocation of this IPAddress.
50 | Check first for special ranges representing LocalHost or a Local/Private Network.
51 | Then contact geoplugin.com to get a geo-location string.
52 | */
53 | public static string GetGeoLocation(IPAddress ipAddr)
54 | {
55 | if (ipAddr == null)
56 | return string.Empty;
57 |
58 | string strAddrType = Util.AddressType(ipAddr);
59 | if (strAddrType != null)
60 | return strAddrType;
61 |
62 | if (ipAddr.IsIPv4MappedToIPv6)
63 | ipAddr = ipAddr.MapToIPv4();
64 |
65 | string strRequest = strGetGeoService1 + ipAddr.ToString() + strGetGeoService2;
66 |
67 | Place place = null;
68 |
69 | try
70 | {
71 | HttpClient client = new HttpClient();
72 | using HttpResponseMessage response = client.GetAsync(strRequest).GetAwaiter().GetResult();
73 |
74 | if (response.StatusCode == HttpStatusCode.TooManyRequests)
75 | return "Too Many Requests: " + strGeoService;
76 |
77 | AssertImportant(response.StatusCode == HttpStatusCode.OK);
78 |
79 | response.EnsureSuccessStatusCode(); // may throw
80 |
81 | Stream stream = response.Content.ReadAsStreamAsync().GetAwaiter().GetResult();
82 | AssertImportant(stream?.CanRead ?? false);
83 |
84 | // Parse the response JSON into: Country / Region / City
85 |
86 | if (stream?.CanRead ?? false)
87 | place = JsonSerializer.Deserialize(stream);
88 | }
89 | catch (System.Exception x)
90 | {
91 | return x.Message;
92 | }
93 |
94 | if (place == null)
95 | return Util.strNA; // N/A
96 |
97 | if (!place.Status.Equals("success"))
98 | return place.Message;
99 |
100 | // Turn the three location strings into one.
101 |
102 | System.Text.StringBuilder sbLocation = new System.Text.StringBuilder(32);
103 |
104 | if (!string.IsNullOrWhiteSpace(place.Country))
105 | {
106 | if (!string.IsNullOrWhiteSpace(place.Region) && place.Country.Equals("United States"))
107 | place.Country = "USA";
108 |
109 | sbLocation.Append(place.Country);
110 | }
111 | if (!string.IsNullOrWhiteSpace(place.Region)) // This is the State if the Country is USA.
112 | {
113 | sbLocation.Append(" / ");
114 | sbLocation.Append(place.Region);
115 | }
116 | if (!string.IsNullOrWhiteSpace(place.City))
117 | {
118 | sbLocation.Append(" / ");
119 | sbLocation.Append(place.City);
120 | }
121 |
122 | AssertImportant(sbLocation.Length > 0);
123 | if (sbLocation.Length == 0)
124 | return Util.strNA; // N/A
125 |
126 | return sbLocation.ToString();
127 | } // GetGeoLocation
128 | } // class GeoLocation
129 | }
130 |
--------------------------------------------------------------------------------
/src/PreWin10/WPRP/ThreadPool.wprp:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
13 |
14 |
15 |
16 |
17 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
60 |
61 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
79 |
80 |
81 |
82 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
--------------------------------------------------------------------------------
/src/PreWin10/TraceMondo.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .NOTES
3 |
4 | Copyright (c) Microsoft Corporation.
5 | Licensed under the MIT License.
6 |
7 | .SYNOPSIS
8 |
9 | Capture and View an ETW trace:
10 | CPU Samples, Thread Dispatch, File I/O, Office Logging Providers, ThreadPool, Processes, Modules
11 |
12 | .DESCRIPTION
13 |
14 | .\TraceMondo Start [-Loop] [-CLR] [-JS]
15 | .\TraceMondo Stop [-WPA]
16 | .\TraceMondo View [-Path \MSO-Trace-CPU.etl]
17 | .\TraceMondo Status
18 | .\TraceMondo Cancel
19 | -Loop: Record only the last few minutes of activity (circular memory buffer).
20 | -CLR: Resolve call stacks for C# (Common Language Runtime).
21 | -JS: Resolve call stacks for JavaScript.
22 | -WPA: Launch the WPA viewer (Windows Performance Analyzer) with the collected trace.
23 | -Path: Optional path to a previously collected trace.
24 | -Verbose
25 |
26 | These scripts work with pre-Win10 versions of the Windows Performance Toolkit (WPT).
27 |
28 | .LINK
29 |
30 | https://learn.microsoft.com/en-us/windows-hardware/test/wpt/event-tracing-for-windows
31 | https://learn.microsoft.com/en-us/shows/defrag-tools/39-windows-performance-toolkit
32 | #>
33 |
34 | [CmdletBinding(DefaultParameterSetName = "Start")]
35 | Param(
36 | # "Start, Stop, Status, Cancel, View"
37 | [Parameter(Position=0)]
38 | [string]$Command,
39 |
40 | # Record only the last few minutes of activity (circular memory buffer).
41 | [Parameter(ParameterSetName="Start")]
42 | [switch]$Loop,
43 |
44 | # "Support Common Language Runtime / C#"
45 | [Parameter(ParameterSetName="Start")]
46 | [switch]$CLR,
47 |
48 | # "Support JavaScript"
49 | [Parameter(ParameterSetName="Start")]
50 | [switch]$JS,
51 |
52 | # "Launch WPA after collecting the trace"
53 | [Parameter(ParameterSetName="Stop")]
54 | [switch]$WPA,
55 |
56 | # "Optional path to a previously collected trace: MSO-Trace-Mondo.etl"
57 | [Parameter(ParameterSetName="View")]
58 | [string]$Path
59 |
60 | # [switch]$Verbose # implicit
61 | )
62 |
63 | if (!$Path) { $Path = $Null } # for PSv2
64 |
65 | # ===== CUSTOMIZE THIS =====
66 |
67 | $TraceParams =
68 | @{
69 | RecordingProfiles =
70 | @(
71 | ".\WPRP\CPU.wprp.Verbose"
72 | ".\WPRP\FileDiskIO.wprp.Light"
73 | ".\WPRP\OfficeProviders.wprp"
74 | ".\WPRP\Network.wprp.Verbose"
75 | ".\WPRP\ThreadPool.wprp"
76 | ".\WPRP\Defender.wprp.Light"
77 |
78 | <# ^^^ The first entry is the base recording profile for this script.
79 | vvv Additional recording profile string(s) follow. See ReadMe.txt
80 |
81 | "Registry" # Built-in
82 | ".\WPRP\FileDiskIO.wprp.Verbose"
83 | "c:\MyProfiles\MyRecordingProfile.wprp"
84 | #>
85 | )
86 |
87 | # This is the arbitrary name of the tracing session/instance:
88 | InstanceName = "MSO-Trace-Mondo"
89 | }
90 |
91 | $ViewerParams =
92 | @{
93 | # This configuration file organizes the data in the WPA viewer.
94 | # https://learn.microsoft.com/en-us/windows-hardware/test/wpt/view-profiles
95 | ViewerConfig = ".\WPAP\CPU-FileIO.wpaProfile"
96 |
97 | # The default trace file name is: .etl
98 | TraceName = $TraceParams.InstanceName
99 |
100 | # Optional alternate path to a previously collected ETL trace:
101 | TraceFilePath = $Path
102 | }
103 |
104 | # ===== END CUSTOMIZE ====
105 |
106 | if (!$script:PSScriptRoot) { $script:PSScriptRoot = Split-Path -Parent -Path $script:MyInvocation.MyCommand.Definition } # for PSv2
107 | $script:ScriptHomePath = $PSScriptRoot
108 | $script:ScriptRootPath = Resolve-Path "$PSScriptRoot\.."
109 | $script:PSScriptParams = $script:PSBoundParameters # volatile
110 |
111 | . "$ScriptRootPath\INCLUDE.ps1"
112 |
113 | # Main
114 | $Result = ProcessTraceCommand $Command @TraceParams -Loop:$Loop -CLR:$CLR -JS:$JS
115 | ValidateResult "ProcessTraceCommand" $Result
116 |
117 | switch ($Result)
118 | {
119 | Started
120 | {
121 | # Call stacks with symbols are available for File I/O in Windows 8.0 (v6.2) and above. Disk I/O traces do collect call stacks.
122 | if (!(CheckOSVersion '6.2.0')) { Write-Warn "Warning: Call stacks with symbols for File I/O traces are available starting with Windows 8.0`n" }
123 |
124 | Write-Msg "ETW tracing has begun.`nExercise the application, then run: $(GetScriptCommand) Stop [-WPA]`n"
125 | }
126 | Collected { WriteTraceCollected $TraceParams.InstanceName; if ($WPA) { LaunchViewer @ViewerParams } }
127 | View { LaunchViewer @ViewerParams }
128 | Error { exit 1 }
129 | }
130 |
131 | exit 0 # Success
132 |
--------------------------------------------------------------------------------
/src/PreWin10/TraceCPU.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .NOTES
3 |
4 | Copyright (c) Microsoft Corporation.
5 | Licensed under the MIT License.
6 |
7 | .SYNOPSIS
8 |
9 | Capture and View an ETW trace:
10 | CPU Samples, Thread Dispatch, Processes, Modules
11 |
12 | .DESCRIPTION
13 |
14 | .\TraceCPU Start [-Lean] [-Loop] [-CLR] [-JS]
15 | .\TraceCPU Stop [-WPA]
16 | .\TraceCPU View [-Path \MSO-Trace-CPU.etl]
17 | .\TraceCPU Status
18 | .\TraceCPU Cancel
19 | -Lean: Reduced data collection: no call stacks.
20 | -Loop: Record only the last few minutes of activity (circular memory buffer).
21 | -CLR: Resolve call stacks for C# (Common Language Runtime).
22 | -JS: Resolve call stacks for JavaScript.
23 | -WPA: Launch the WPA viewer (Windows Performance Analyzer) with the collected trace.
24 | -Path: Optional path to a previously collected trace.
25 | -Verbose
26 |
27 | These scripts work with pre-Win10 versions of the Windows Performance Toolkit (WPT).
28 |
29 | .LINK
30 |
31 | https://learn.microsoft.com/en-us/windows-hardware/test/wpt/event-tracing-for-windows
32 | https://learn.microsoft.com/en-us/shows/defrag-tools/39-windows-performance-toolkit
33 | #>
34 |
35 | [CmdletBinding(DefaultParameterSetName = "Start")]
36 | Param(
37 | # "Start, Stop, Status, Cancel, View"
38 | [Parameter(Position=0)]
39 | [string]$Command,
40 |
41 | # "Reduced data collection: no call stacks"
42 | [Parameter(ParameterSetName="Start")]
43 | [switch]$Lean,
44 |
45 | # Compatibility only
46 | [Parameter(ParameterSetName="Start")]
47 | [switch]$Lite,
48 |
49 | # Record only the last few minutes of activity (circular memory buffer).
50 | [Parameter(ParameterSetName="Start")]
51 | [switch]$Loop,
52 |
53 | # "Support Common Language Runtime / C#"
54 | [Parameter(ParameterSetName="Start")]
55 | [switch]$CLR,
56 |
57 | # "Support JavaScript"
58 | [Parameter(ParameterSetName="Start")]
59 | [switch]$JS,
60 |
61 | # "Launch WPA after collecting the trace"
62 | [Parameter(ParameterSetName="Stop")]
63 | [switch]$WPA,
64 |
65 | # "Optional path to a previously collected trace: MSO-Trace-CPU.etl"
66 | [Parameter(ParameterSetName="View")]
67 | [string]$Path
68 |
69 | # [switch]$Verbose # implicit
70 | )
71 |
72 | if (!$Path) { $Path = $Null } # for PSv2
73 |
74 | # ===== CUSTOMIZE THIS =====
75 |
76 | $TraceParams =
77 | @{
78 | RecordingProfiles =
79 | @(
80 | # Capture CPU Samples and Dispatcher Info with call stacks for all processes.
81 | ".\WPRP\CPU.wprp.Verbose"
82 | ".\WPRP\OfficeProviders.wprp.Light" # Code Markers
83 | <#
84 | ^^^ The first entry is the base recording profile for this script.
85 | vvv Additional recording profile string(s) follow. See ReadMe.txt
86 |
87 | "Registry" # Built-in
88 | ".\WPRP\FileDiskIO.wprp.Verbose"
89 | "c:\MyProfiles\MyRecordingProfile.wprp"
90 | #>
91 | )
92 |
93 | # This is the arbitrary name of the tracing session/instance:
94 | InstanceName = "MSO-Trace-CPU"
95 | }
96 |
97 | # Change the base recording profile:
98 | # Capture only "Lean" CPU Samples for all processes/modules.
99 | if ($Lean -or $Lite) { $TraceParams.RecordingProfiles = @( ".\WPRP\CPU.wprp.Light" ) } # Just this one recording profile.
100 |
101 | $ViewerParams =
102 | @{
103 | # This configuration file organizes the data in the WPA viewer.
104 | # https://learn.microsoft.com/en-us/windows-hardware/test/wpt/view-profiles
105 | ViewerConfig = ".\WPAP\CPU.wpaProfile"
106 |
107 | # The default trace file name is: .etl
108 | TraceName = $TraceParams.InstanceName
109 |
110 | # Optional alternate path to a previously collected ETL trace:
111 | TraceFilePath = $Path
112 | }
113 |
114 | # ===== END CUSTOMIZE ====
115 |
116 | if (!$script:PSScriptRoot) { $script:PSScriptRoot = Split-Path -Parent -Path $script:MyInvocation.MyCommand.Definition } # for PSv2
117 | $script:ScriptHomePath = $PSScriptRoot
118 | $script:ScriptRootPath = Resolve-Path "$PSScriptRoot\.."
119 | $script:PSScriptParams = $script:PSBoundParameters # volatile
120 |
121 | . "$ScriptRootPath\INCLUDE.ps1"
122 |
123 | # Main
124 |
125 | $Result = ProcessTraceCommand $Command @TraceParams -Loop:$Loop -CLR:$CLR -JS:$JS
126 | ValidateResult "ProcessTraceCommand" $Result
127 |
128 | switch ($Result)
129 | {
130 | Started { Write-Msg "ETW CPU tracing has begun.`nExercise the application, then run: $(GetScriptCommand) Stop [-WPA]`n" }
131 | Collected { WriteTraceCollected $TraceParams.InstanceName; if ($WPA) { LaunchViewer @ViewerParams } }
132 | View { LaunchViewer @ViewerParams }
133 | Error { exit 1 }
134 | }
135 |
136 | exit 0 # Success
137 |
--------------------------------------------------------------------------------
/src/PreWin10/TraceFileDiskIO.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .NOTES
3 |
4 | Copyright (c) Microsoft Corporation.
5 | Licensed under the MIT License.
6 |
7 | .SYNOPSIS
8 |
9 | Capture and View an ETW trace:
10 | File I/O, Disk I/O, Modules
11 |
12 | .DESCRIPTION
13 |
14 | .\TraceFileDiskIO Start [-Lean] [-Loop] [-CLR] [-JS]
15 | .\TraceFileDiskIO Stop [-WPA]
16 | .\TraceFileDiskIO View [-Path \MSO-Trace-FileDiskIO.etl]
17 | .\TraceFileDiskIO Status
18 | .\TraceFileDiskIO Cancel
19 | -Lean: Reduced data collection: no Disk I/O.
20 | -Loop: Record only the last few minutes of activity (circular memory buffer).
21 | -CLR: Resolve call stacks for C# (Common Language Runtime).
22 | -JS: Resolve call stacks for JavaScript.
23 | -WPA: Launch the WPA viewer (Windows Performance Analyzer) with the collected trace.
24 | -Path: Optional path to a previously collected trace.
25 | -Verbose
26 |
27 | These scripts work with pre-Win10 versions of the Windows Performance Toolkit (WPT).
28 |
29 | .LINK
30 |
31 | https://learn.microsoft.com/en-us/windows-hardware/test/wpt/event-tracing-for-windows
32 | https://learn.microsoft.com/en-us/shows/defrag-tools/39-windows-performance-toolkit
33 | #>
34 |
35 | [CmdletBinding(DefaultParameterSetName = "Start")]
36 | Param(
37 | # "Start, Stop, Status, Cancel, View"
38 | [Parameter(Position=0)]
39 | [string]$Command,
40 |
41 | # "Reduced data collection: no Disk I/O"
42 | [Parameter(ParameterSetName="Start")]
43 | [switch]$Lean,
44 |
45 | # Record only the last few minutes of activity (circular memory buffer).
46 | [Parameter(ParameterSetName="Start")]
47 | [switch]$Loop,
48 |
49 | # "Support Common Language Runtime / C#"
50 | [Parameter(ParameterSetName="Start")]
51 | [switch]$CLR,
52 |
53 | # "Support JavaScript"
54 | [Parameter(ParameterSetName="Start")]
55 | [switch]$JS,
56 |
57 | # "Launch WPA after collecting the trace"
58 | [Parameter(ParameterSetName="Stop")]
59 | [switch]$WPA,
60 |
61 | # "Optional path to a previously collected trace: MSO-Trace-FileDiskIO.etl"
62 | [Parameter(ParameterSetName="View")]
63 | [string]$Path
64 |
65 | # [switch]$Verbose # implicit
66 | )
67 |
68 | if (!$Path) { $Path = $Null } # for PSv2
69 |
70 | # ===== CUSTOMIZE THIS =====
71 |
72 | $TraceParams =
73 | @{
74 | RecordingProfiles =
75 | @(
76 | # Capture FileIO and DiskIO events with call stacks for all processes.
77 | ".\WPRP\FileDiskIO.wprp"
78 | ".\WPRP\OfficeProviders.wprp.Light" # Code Markers
79 | <#
80 | ^^^ The first entry is the base recording profile for this script.
81 | vvv Additional recording profile string(s) follow. See ReadMe.txt
82 |
83 | "Registry" # Built-in
84 | ".\WPRP\Handles.wprp.Verbose"
85 | "c:\MyProfiles\MyRecordingProfile.wprp"
86 | #>
87 | )
88 |
89 | # This is the arbitrary name of the tracing session/instance.
90 | InstanceName = "MSO-Trace-FileDiskIO"
91 | }
92 |
93 | if ($Lean) { $TraceParams.RecordingProfiles[0] = ".\WPRP\FileDiskIO.wprp.Light" }
94 |
95 | $ViewerParams =
96 | @{
97 | # This configuration file organizes the data in the WPA viewer.
98 | ViewerConfig = ".\WPAP\FileDiskIO.wpaProfile"
99 |
100 | # The trace file name is: .etl
101 | TraceName = $TraceParams.InstanceName
102 |
103 | # Optional alternate path to a previously collected ETL trace:
104 | TraceFilePath = $Path
105 | }
106 |
107 | # ===== END CUSTOMIZE ====
108 |
109 | if (!$script:PSScriptRoot) { $script:PSScriptRoot = Split-Path -Parent -Path $script:MyInvocation.MyCommand.Definition } # for PSv2
110 | $script:ScriptHomePath = $PSScriptRoot
111 | $script:ScriptRootPath = Resolve-Path "$PSScriptRoot\.."
112 | $script:PSScriptParams = $script:PSBoundParameters # volatile
113 |
114 | . "$ScriptRootPath\INCLUDE.ps1"
115 |
116 | # Main
117 |
118 | $Result = ProcessTraceCommand $Command @TraceParams -Loop:$Loop -CLR:$CLR -JS:$JS
119 | ValidateResult "ProcessTraceCommand" $Result
120 |
121 | switch ($Result)
122 | {
123 | Started
124 | {
125 | # Call stacks with symbols are available for File I/O in Windows 8.0 (v6.2) and above. Disk I/O traces do collect call stacks.
126 | if (!(CheckOSVersion '6.2.0')) { Write-Warn "Warning: Call stacks with symbols for File I/O traces are available starting with Windows 8.0`n" }
127 |
128 | Write-Msg "ETW File and Disk I/O tracing has begun.`nExercise the application, then run: $(GetScriptCommand) Stop [-WPA]`n"
129 | }
130 | Collected { WriteTraceCollected $TraceParams.InstanceName; if ($WPA) { LaunchViewer @ViewerParams } }
131 | View { LaunchViewer @ViewerParams }
132 | Error { exit 1 }
133 | }
134 |
135 | exit 0 # Success
136 |
--------------------------------------------------------------------------------
/src/PreWin10/TraceHandles.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .NOTES
3 |
4 | Copyright (c) Microsoft Corporation.
5 | Licensed under the MIT License.
6 |
7 | .SYNOPSIS
8 |
9 | Capture and View an ETW trace:
10 | Kernel Handles, Modules
11 |
12 | .DESCRIPTION
13 |
14 | .\TraceHandles Start [-Loop] [-CLR] [-JS]
15 | .\TraceHandles Stop [-WPA]
16 | .\TraceHandles View [-Path \MSO-Trace-Handles.etl]
17 | .\TraceHandles Status
18 | .\TraceHandles Cancel
19 | -Loop: Record only the last few minutes of activity (circular memory buffer).
20 | -CLR: Resolve call stacks for C# (Common Language Runtime).
21 | -JS: Resolve call stacks for JavaScript.
22 | -WPA: Launch the WPA viewer (Windows Performance Analyzer) with the collected trace.
23 | -Path: Optional path to a previously collected trace.
24 | -Verbose
25 |
26 | These scripts work with pre-Win10 versions of the Windows Performance Toolkit (WPT).
27 |
28 | .LINK
29 |
30 | https://learn.microsoft.com/en-us/windows-hardware/test/wpt/event-tracing-for-windows
31 | https://learn.microsoft.com/en-us/shows/defrag-tools/39-windows-performance-toolkit
32 | https://learn.microsoft.com/en-us/windows/desktop/SysInfo/object-categories
33 | #>
34 |
35 | [CmdletBinding(DefaultParameterSetName = "Start")]
36 | Param(
37 | # "Start, Stop, Status, Cancel, View"
38 | [Parameter(Position=0)]
39 | [string]$Command,
40 |
41 | # Record only the last few minutes of activity (circular memory buffer).
42 | [Parameter(ParameterSetName="Start")]
43 | [switch]$Loop,
44 |
45 | # "Support Common Language Runtime / C#"
46 | [Parameter(ParameterSetName="Start")]
47 | [switch]$CLR,
48 |
49 | # "Support JavaScript"
50 | [Parameter(ParameterSetName="Start")]
51 | [switch]$JS,
52 |
53 | # "Launch WPA after collecting the trace"
54 | [Parameter(ParameterSetName="Stop")]
55 | [switch]$WPA,
56 |
57 | # "Optional path to a previously collected trace: MSO-Trace-Handles.etl"
58 | [Parameter(ParameterSetName="View")]
59 | [string]$Path
60 |
61 | # [switch]$Verbose # implicit
62 | )
63 |
64 | if (!$Path) { $Path = $Null } # for PSv2
65 |
66 | # ===== CUSTOMIZE THIS =====
67 |
68 | $TraceParams =
69 | @{
70 | RecordingProfiles =
71 | @(
72 | # This XML file contains tracing parameters for Windows Kernel Object Handles.
73 | ".\WPRP\Handles.wprp.Light"
74 | ".\WPRP\OfficeProviders.wprp.Light" # Code Markers
75 | <#
76 | ^^^ The first entry is the base recording profile for this script.
77 | vvv Additional recording profile string(s) follow. See ReadMe.txt
78 |
79 | "Registry" # Built-in
80 | ".\WPRP\FileDiskIO.wprp"
81 | "c:\MyProfiles\MyRecordingProfile.wprp"
82 | #>
83 | )
84 |
85 | # This is the arbitrary name of the tracing session/instance.
86 | InstanceName = "MSO-Trace-Handles"
87 | }
88 |
89 | $ViewerParams =
90 | @{
91 | # This configuration file organizes the data in the WPA viewer.
92 | # https://learn.microsoft.com/en-us/windows-hardware/test/wpt/view-profiles
93 | ViewerConfig = ".\WPAP\Handles.wpaProfile"
94 |
95 | # The trace file name is: .etl
96 | TraceName = $TraceParams.InstanceName
97 |
98 | # Optional alternate path to a previously collected ETL trace:
99 | TraceFilePath = $Path
100 | }
101 |
102 | # ===== END CUSTOMIZE ====
103 |
104 | if (!$script:PSScriptRoot) { $script:PSScriptRoot = Split-Path -Parent -Path $script:MyInvocation.MyCommand.Definition } # for PSv2
105 | $script:ScriptHomePath = $PSScriptRoot
106 | $script:ScriptRootPath = Resolve-Path "$PSScriptRoot\.."
107 | $script:PSScriptParams = $script:PSBoundParameters # volatile
108 |
109 | . "$ScriptRootPath\INCLUDE.ps1"
110 |
111 | # Main
112 |
113 | # Tracing kernel handles is available in Windows 8.0 (v6.2) and above.
114 |
115 | if (!(CheckOSVersion '6.2.0'))
116 | {
117 | Write-Err "`nHandle tracing is available starting with Windows 8.0"
118 | exit 1
119 | }
120 |
121 | $Result = ProcessTraceCommand $Command @TraceParams -Loop:$Loop -CLR:$CLR -JS:$JS
122 | ValidateResult "ProcessTraceCommand" $Result
123 |
124 | switch ($Result)
125 | {
126 | Started
127 | {
128 | Write-Msg "ETW Handle tracing has begun.`nExercise the application, then run: $(GetScriptCommand) Stop [-WPA]`n"
129 |
130 | if (CheckOSVersion '10.0.18315') { break }
131 |
132 | Write-Warn "Tracing only Kernel Object Handles: Process, Thread, Registry Key, File, etc."
133 | Write-Warn "To trace GDI and User Handles, a more recent version of Windows is required (10.0.18315+)."
134 | Write-Warn "See: https://learn.microsoft.com/en-us/windows/desktop/SysInfo/object-categories"
135 | Write-Warn
136 | }
137 |
138 | Collected { WriteTraceCollected $TraceParams.InstanceName; if ($WPA) { LaunchViewer @ViewerParams } }
139 | View { LaunchViewer @ViewerParams }
140 | Error { exit 1 }
141 | }
142 |
143 | exit 0 # Success
144 |
--------------------------------------------------------------------------------
/src/PreWin10/WPRP/VirtualAlloc.wprp:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
13 |
14 |
15 |
16 |
17 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
84 |
85 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
106 |
107 |
108 |
109 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
--------------------------------------------------------------------------------
/src/PreWin10/TraceMemory.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .NOTES
3 |
4 | Copyright (c) Microsoft Corporation.
5 | Licensed under the MIT License.
6 |
7 | .SYNOPSIS
8 |
9 | Capture and View an ETW trace:
10 | RAM Usage (Reference Set), VirtualAlloc, Processes, Modules
11 |
12 | .DESCRIPTION
13 |
14 | .\TraceMemory Start [-Lean] [-Loop] [-CLR] [-JS]
15 | .\TraceMemory Stop [-WPA]
16 | .\TraceMemory View [-Path \MSO-Trace-Memory.etl]
17 | .\TraceMemory Status
18 | .\TraceMemory Cancel
19 | -Lean: Reduced data collection: memory snapshots every 0.5 sec.
20 | -Loop: Record only the last few minutes of activity (circular memory buffer).
21 | -CLR: Resolve call stacks for C# (Common Language Runtime).
22 | -JS: Resolve call stacks for JavaScript.
23 | -WPA: Launch the WPA viewer (Windows Performance Analyzer) with the collected trace.
24 | -Path: Optional path to a previously collected trace.
25 | -Verbose
26 |
27 | These scripts work with pre-Win10 versions of the Windows Performance Toolkit (WPT).
28 |
29 | .LINK
30 |
31 | https://learn.microsoft.com/en-us/windows-hardware/test/wpt/event-tracing-for-windows
32 | https://learn.microsoft.com/en-us/shows/defrag-tools/39-windows-performance-toolkit
33 | #>
34 |
35 | [CmdletBinding(DefaultParameterSetName = "Start")]
36 | Param(
37 | # "Start, Stop, Status, Cancel, View"
38 | [Parameter(Position=0)]
39 | [string]$Command,
40 |
41 | # "Reduced data collection: memory snapshots every 0.5 sec."
42 | [Parameter(ParameterSetName="Start")]
43 | [switch]$Lean,
44 |
45 | # "Same as 'Lean' (for compatiblity)"
46 | [Parameter(ParameterSetName="Start")]
47 | [switch]$Sample,
48 |
49 | # Record only the last few minutes of activity (circular memory buffer).
50 | [Parameter(ParameterSetName="Start")]
51 | [switch]$Loop,
52 |
53 | # "Support Common Language Runtime / C#"
54 | [Parameter(ParameterSetName="Start")]
55 | [switch]$CLR,
56 |
57 | # "Support JavaScript"
58 | [Parameter(ParameterSetName="Start")]
59 | [switch]$JS,
60 |
61 | # "Launch WPA after collecting the trace"
62 | [Parameter(ParameterSetName="Stop")]
63 | [switch]$WPA,
64 |
65 | # "Optional path to a previously collected trace: MSO-Trace-Memory.etl"
66 | [Parameter(ParameterSetName="View")]
67 | [string]$Path
68 |
69 | # [switch]$Verbose # implicit
70 | )
71 |
72 | if (!$Path) { $Path = $Null } # for PSv2
73 |
74 | # ===== CUSTOMIZE THIS =====
75 | $TraceParams =
76 | @{
77 | RecordingProfiles =
78 | @(
79 | # Capture Memory Info (Reference Set, etc.) with call stacks for all processes.
80 | # To see the available profiles, run: wpr -profiles .\WPRP\Memory.wprp
81 | ".\WPRP\Memory.wprp.Verbose"
82 | ".\WPRP\OfficeProviders.wprp.Light" # Code Markers
83 | <#
84 | ^^^ The first entry is the base recording profile for this script.
85 | vvv Additional recording profile string(s) follow. See ReadMe.txt
86 |
87 | "Registry" # Built-in
88 | ".\WPRP\FileDiskIO.wprp"
89 | "c:\MyProfiles\MyRecordingProfile.wprp.Light"
90 | #>
91 | )
92 |
93 | # This is the arbitrary name of the tracing session/instance.
94 | InstanceName = "MSO-Trace-Memory"
95 | }
96 |
97 | # Capture only snapshots per process every 1/2 second:
98 | if ($Lean -or $Sample) { $TraceParams.RecordingProfiles = @( ".\WPRP\Memory.wprp.Light" ) } # Just this one recording profile.
99 |
100 | $ViewerParams =
101 | @{
102 | # This configuration file organizes the data in the WPA viewer.
103 | ViewerConfig = ".\WPAP\Memory.wpaProfile"
104 |
105 | # The trace file name is: .etl
106 | TraceName = $TraceParams.InstanceName
107 |
108 | # Optional alternate path to a previously collected ETL trace:
109 | TraceFilePath = $Path
110 | }
111 | # ===== END CUSTOMIZE ====
112 |
113 | if (!$script:PSScriptRoot) { $script:PSScriptRoot = Split-Path -Parent -Path $script:MyInvocation.MyCommand.Definition } # for PSv2
114 | $script:ScriptHomePath = $PSScriptRoot
115 | $script:ScriptRootPath = Resolve-Path "$PSScriptRoot\.."
116 | $script:PSScriptParams = $script:PSBoundParameters # volatile
117 |
118 | . "$ScriptRootPath\INCLUDE.ps1"
119 |
120 | # Main
121 |
122 | # Memory tracing of this type is very limited before Win8.0 (v6.2).
123 | if ($Lean -or $Sample)
124 | {
125 | if (!(CheckOSVersion '6.2.0'))
126 | {
127 | Write-Err "`nThis type of memory sampling is available only in Windows 8.0 and later."
128 | exit 1
129 | }
130 | }
131 |
132 | $Result = ProcessTraceCommand $Command @TraceParams -Loop:$Loop -CLR:$CLR -JS:$JS
133 | ValidateResult "ProcessTraceCommand" $Result
134 |
135 | switch ($Result)
136 | {
137 | Started
138 | {
139 | if (!(CheckOSVersion '6.2.0')) { Write-Warn "Warning: Call stacks for this type of memory tracing are available in Windows 8.0 and later.`n" }
140 |
141 | Write-Msg "ETW Memory tracing has begun."
142 | Write-Msg "Exercise the application, then run: $(GetScriptCommand) Stop [-WPA]"
143 | Write-Msg "(Do not quit the application until tracing is stopped!)"
144 | Write-Msg
145 | }
146 | Collected { WriteTraceCollected $TraceParams.InstanceName; if ($WPA) { LaunchViewer @ViewerParams } }
147 | View { LaunchViewer @ViewerParams }
148 | Error { exit 1 }
149 | }
150 |
151 | exit 0 # Success
152 |
--------------------------------------------------------------------------------
/src/PreWin10/WPRP/Defender.wprp:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
13 |
14 |
15 |
16 |
17 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
70 |
71 |
72 |
73 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
90 |
91 |
92 |
93 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
111 |
112 |
113 |
114 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
--------------------------------------------------------------------------------
/src/SymbolScan.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .NOTES
3 |
4 | Copyright (c) Microsoft Corporation.
5 | Licensed under the MIT License.
6 |
7 | .SYNOPSIS
8 |
9 | SymbolScan [-Allow | -Prevent] [-Verbose]
10 | -Allow: Let Windows Defender scan symbol and trace files (default).
11 | -Prevent: Windows Defender should not scan symbol and trace files (for speed).
12 |
13 | .DESCRIPTION
14 |
15 | Virus scanners may slow down symbol resolution by scanning the potentially large symbol files downloaded/created by WPA: *.pdb, *.symcache
16 | (Windows Performance Analyzer [WPA] downloads *.pdb files as *.error, and *.symcache files as *.pending, then renames them once completed.)
17 |
18 | To increase performance, add the symbol file extensions to the Windows Defender Exclusion List: .pdb, .symcache, .pending, .error
19 | Also add the ETW log extensions: .etl, .wpapk
20 |
21 | .LINK
22 |
23 | https://learn.microsoft.com/en-us/powershell/module/defender/add-mppreference
24 | #>
25 |
26 | Param (
27 | # Windows Defender should scan trace/symbol files.
28 | #[Parameter(ParameterSetName="Scan")]
29 | [switch]$Allow,
30 |
31 | # Windows Defender should not scan trace/symbol files.
32 | [Parameter(ParameterSetName="NoScan")]
33 | [switch]$Prevent
34 | )
35 |
36 |
37 | function GetArgs { return $Args }
38 |
39 |
40 | [array]$SymbolFileExtensions = GetArgs .etl .wpapk .pdb .symcache .pending .error
41 |
42 |
43 | <#
44 | Determine whether this script has Administrator privileges.
45 | #>
46 | function CheckAdminPrivilege
47 | {
48 | $Principal = [Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()
49 | $Administrator = [Security.Principal.WindowsBuiltInRole]::Administrator
50 | return $Principal.IsInRole($Administrator)
51 | }
52 |
53 |
54 | <#
55 | Add the file extensions to the Windows Defender Exclusion List: .etl, .wpapk, .pdb, .symcache, .pending, .error
56 | The -Undo switch removes these file extensions from the Wndows Defender Exclusion List.
57 | #>
58 | function ExcludeSymbolExtensions
59 | {
60 | Param(
61 | [switch]$Undo
62 | )
63 | Write-Verbose "(Get-MpPreference).ExclusionExtension"
64 | [array]$ExclusionExtensions = (Get-MPPreference -ErrorAction:SilentlyContinue).ExclusionExtension
65 |
66 | # Get the intersection of the Symbol File Extensions with the current list of file extension exclusions.
67 |
68 | [array]$CommonExtensions = @()
69 | if ($ExclusionExtensions.length -ne 0)
70 | {
71 | Write-Verbose "$ExclusionExtensions"
72 |
73 | $CommonExtensions = Compare-Object -IncludeEqual -ExcludeDifferent -PassThru $SymbolFileExtensions $ExclusionExtensions
74 | }
75 |
76 | if ($Undo)
77 | {
78 | if ($CommonExtensions.length -eq 0) { return } # nothing to remove
79 |
80 | # Remove Symbol File Exclusions
81 |
82 | Write-Output "Allowing Windows Defender to scan the Symbol/Trace File Extensions:"
83 | Write-Output $CommonExtensions
84 | Write-Verbose "Remove-MpPreference -ExclusionExtension $CommonExtensions"
85 | Remove-MPPreference -ErrorAction:SilentlyContinue -ExclusionExtension $CommonExtensions >$Null
86 | }
87 | else
88 | {
89 | if ($CommonExtensions.length -eq $SymbolFileExtensions.length) { return } # nothing to add
90 |
91 | # Add Symbol File Exclusions
92 |
93 | Write-Verbose "Add-MpPreference -ExclusionExtension $SymbolFileExtensions"
94 | Add-MpPreference -ErrorAction:SilentlyContinue -ExclusionExtension $SymbolFileExtensions >$Null
95 | }
96 |
97 | # Double-check the result.
98 |
99 | Write-Verbose "(Get-MpPreference).ExclusionExtension"
100 | [array]$ExclusionExtensions = (Get-MPPreference -ErrorAction:SilentlyContinue).ExclusionExtension
101 |
102 | if ($ExclusionExtensions.length -eq 0) { return }
103 |
104 | Write-Verbose "$ExclusionExtensions"
105 |
106 | [array]$CommonExtensions = Compare-Object -IncludeEqual -ExcludeDifferent -PassThru $SymbolFileExtensions $ExclusionExtensions
107 |
108 | if ($CommonExtensions.length -eq 0) { return }
109 |
110 | if ($Undo)
111 | {
112 | Write-Output "Warning: These Symbol/Trace File Extensions remain on the Windows Defender Exclusion List:" $CommonExtensions
113 | }
114 | else
115 | {
116 | Write-Output "For speed, these Symbol/Trace File Extensions will not be scanned by Windows Defender:"
117 | Write-Output $CommonExtensions
118 | Write-Output $Null
119 | Write-Output "To undo this, run: $($script:MyInvocation.InvocationName -Replace ".ps1$") -Allow"
120 | }
121 | } # ExcludeSymbolExtensions
122 |
123 |
124 | function ListSymbolExtensions
125 | {
126 | Write-Verbose "(Get-MpPreference).ExclusionExtension"
127 | [array]$ExclusionExtensions = (Get-MPPreference -ErrorAction:SilentlyContinue).ExclusionExtension
128 |
129 | if ($ExclusionExtensions.length -ne 0)
130 | {
131 | Write-Verbose "$ExclusionExtensions"
132 |
133 | [array]$CommonExtensions = Compare-Object -IncludeEqual -ExcludeDifferent -PassThru $SymbolFileExtensions $ExclusionExtensions
134 |
135 | if ($CommonExtensions.length -ne 0)
136 | {
137 | Write-Output "These Symbol/Trace File Extensions will not be scanned by Windows Defender:"
138 | Write-Output $CommonExtensions
139 | return
140 | }
141 | }
142 |
143 | Write-Output "There are no Symbol/Trace File Extensions on the Windows Defender Exclusion List."
144 | }
145 |
146 |
147 | # Main
148 |
149 | if ([Environment]::OSVersion.Version.Major -lt 10)
150 | {
151 | Write-Output "Windows 10+ is required."
152 | return
153 | }
154 |
155 | if (!(CheckAdminPrivilege))
156 | {
157 | Write-Output "Administrator Privilege is required."
158 | return
159 | }
160 |
161 | if ($Prevent) { ExcludeSymbolExtensions }
162 | elseif ($Allow) { ExcludeSymbolExtensions -Undo }
163 | else { ListSymbolExtensions }
164 | Write-Output $Null
165 |
--------------------------------------------------------------------------------
/src/TraceRegistry.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .NOTES
3 |
4 | Copyright (c) Microsoft Corporation.
5 | Licensed under the MIT License.
6 |
7 | .SYNOPSIS
8 |
9 | Capture and View an ETW trace:
10 | Office Code Markers, Kernel Handles (including Registry Keys), Registry
11 |
12 | .DESCRIPTION
13 |
14 | Trace Registry activity.
15 | TraceRegistry Start [Start_Options]
16 | TraceRegistry Stop [-WPA [-FastSym]]
17 |
18 | Trace Windows Restart: Registry activity.
19 | TraceRegistry Start -Boot [Start_Options]
20 | TraceRegistry Stop -Boot [-WPA [-FastSym]]
21 |
22 | TraceRegistry View [-Path \MSO-Trace-Registry.etl|.wpapk] [-FastSym]
23 | TraceRegistry Status [-Boot]
24 | TraceRegistry Cancel [-Boot]
25 |
26 | -Boot: Trace Registry activity during the next Windows Restart.
27 | -WPA : Launch the WPA viewer (Windows Performance Analyzer) with the collected trace.
28 | -Path: Optional path to a previously collected trace.
29 | -FastSym: Load symbols only from cached/transcoded SymCache, not from slower PDB files.
30 | See: https://github.com/microsoft/MSO-Scripts/wiki/Advanced-Symbols#optimize
31 | -Verbose
32 |
33 | Start_Options
34 | -Loop: Record only the last few minutes of activity (circular memory buffer).
35 | -CLR : Resolve symbolic stackwalks for C# (Common Language Runtime).
36 | -JS : Resolve symbolic stackwalks for JavaScript.
37 |
38 | .LINK
39 |
40 | https://learn.microsoft.com/en-us/windows/win32/sysinfo/registry
41 | https://learn.microsoft.com/en-us/windows-hardware/test/wpt/event-tracing-for-windows
42 | https://learn.microsoft.com/en-us/shows/defrag-tools/39-windows-performance-toolkit
43 | #>
44 |
45 | [CmdletBinding(DefaultParameterSetName = "View")]
46 | Param(
47 | # "Start, Stop, Status, Cancel, View"
48 | [Parameter(Position=0)]
49 | [string]$Command,
50 |
51 | # Record only the last few minutes of activity (circular memory buffer).""
52 | [Parameter(ParameterSetName="Start")]
53 | [switch]$Loop,
54 |
55 | # "Trace Registry activity during the next Windows Restart."
56 | [switch]$Boot,
57 |
58 | # "Support Common Language Runtime / C#"
59 | [Parameter(ParameterSetName="Start")]
60 | [switch]$CLR,
61 |
62 | # "Support JavaScript"
63 | [Parameter(ParameterSetName="Start")]
64 | [switch]$JS,
65 |
66 | # "Launch WPA after collecting the trace"
67 | [Parameter(ParameterSetName="Stop")]
68 | [switch]$WPA,
69 |
70 | # "Optional path to a previously collected trace: MSO-Trace-Registry.etl"
71 | [Parameter(ParameterSetName="View")]
72 | [string]$Path = $Null,
73 |
74 | # "Faster symbol resolution by loading only from SymCache, not PDB"
75 | [Parameter(ParameterSetName="Stop")]
76 | [Parameter(ParameterSetName="View")]
77 | [switch]$FastSym
78 |
79 | # [switch]$Verbose # implicit
80 | )
81 |
82 | # ===== CUSTOMIZE THIS =====
83 |
84 | $TraceParams =
85 | @{
86 | RecordingProfiles =
87 | @(
88 | ".\WPRP\Registry.wprp!Registry" # Includes Office CodeMarkers
89 | ".\WPRP\Handles.wprp!KernelHandles"
90 | ".\WPRP\OfficeProviders.wprp!CodeMarkers" # Code Markers, HVAs, other light logging
91 |
92 | <# ^^^ The first entry is the base recording profile for this script.
93 | vvv Additional recording profile string(s) follow. See ReadMe.txt
94 |
95 | "Registry" # Built-in
96 | ".\WPRP\FileDiskIO.wprp!FileIO"
97 | "c:\MyProfiles\MyRecordingProfile.wprp!CustomProfile"
98 |
99 | Other recording profiles can be added via the WPT_WPRP environment variable.
100 | $Env:WPT_WPRP="c:\path\MyProfile.wprp!ProfileName;c:\path\MyProfile2.wprp!ProfileName2"
101 | set WPT_WPRP=c:\path\MyProfile.wprp!ProfileName;c:\path\MyProfile2.wprp!ProfileName2
102 |
103 | Other recording providers can be added via the WPT_XPERF environment variable (in "XPerf -ON" format).
104 | $Env:WPT_XPERF="GUIDorNAME1 + GUIDorNAME2:::Stack + GUIDorNAME3:KeywordFlags:Level + ..."
105 | set WPT_XPERF=GUIDorNAME1 + GUIDorNAME2:::Stack + GUIDorNAME3:KeywordFlags:Level + ...
106 |
107 | See: https://github.com/microsoft/MSO-Scripts/wiki/Customize-Tracing#envvar
108 | #>
109 | )
110 |
111 | ProviderManifests =
112 | @(
113 | # Optional: Register Office ETW Provider Manifests not registered by default.
114 | # See: .\OETW\ReadMe.txt
115 | ".\OETW\MsoEtwCM.man" # Office Code Markers
116 | )
117 |
118 | # This is the arbitrary name of the tracing session/instance:
119 | InstanceName = "MSO-Trace-Registry"
120 | }
121 |
122 | $ViewerParams =
123 | @{
124 | # The configuration files define the data tabs in the WPA viewer.
125 | # https://learn.microsoft.com/en-us/windows-hardware/test/wpt/view-profiles
126 | ViewerConfig = ".\WPAP\BasicInfo.wpaProfile", ".\WPAP\Registry.wpaProfile"
127 |
128 | # The default trace file name is: .etl
129 | TraceName = $TraceParams.InstanceName
130 |
131 | # Optional alternate path to a previously collected ETL trace:
132 | TraceFilePath = $Path
133 | }
134 |
135 | # ===== END CUSTOMIZE ====
136 |
137 | if (!$script:PSScriptRoot) { $script:PSScriptRoot = Split-Path -Parent -Path $script:MyInvocation.MyCommand.Definition } # for PSv2
138 | $script:ScriptHomePath = $PSScriptRoot
139 | $script:ScriptRootPath = $PSScriptRoot
140 | $script:PSScriptParams = $script:PSBoundParameters # volatile
141 |
142 | . "$ScriptRootPath\INCLUDE.ps1"
143 |
144 | # Main
145 |
146 | # Use Windows Performance Recorder. It's much simpler, but requires Admin privileges.
147 |
148 | $Result = ProcessTraceCommand $Command @TraceParams -Loop:$Loop -Boot:$Boot -CLR:$CLR -JS:$JS
149 |
150 | switch ($Result)
151 | {
152 | Started { Write-Msg "ETW tracing has begun.`nExercise the application, then run: $(GetScriptCommand) Stop [-WPA]`n" }
153 | Collected { WriteTraceCollected $TraceParams.InstanceName } # $WPA switch
154 | View { $WPA = $True }
155 | Success { $WPA = $False }
156 | Error { exit 1 }
157 | }
158 |
159 | if ($WPA) { LaunchViewer @ViewerParams -FastSym:$FastSym }
160 |
161 | exit 0 # Success
162 |
--------------------------------------------------------------------------------
/src/PreWin10/WPRP/Handles.wprp:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
13 |
14 |
15 |
16 |
17 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
95 |
96 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
118 |
119 |
120 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
133 |
134 |
135 |
136 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
--------------------------------------------------------------------------------
/src/NetBlame/Auxiliary/Extensions.cs:
--------------------------------------------------------------------------------
1 | // Copyright(c) Microsoft Corporation.
2 | // Licensed under the MIT License.
3 |
4 | using System;
5 | using System.Collections.Generic;
6 | using System.Diagnostics;
7 | using System.Net;
8 |
9 | using Microsoft.Windows.EventTracing.Events; // IGenericEvent
10 | using Microsoft.Windows.EventTracing.Symbols; // IStackSnapshot
11 |
12 | using TimestampETW = Microsoft.Windows.EventTracing.TraceTimestamp;
13 | using TimestampUI = Microsoft.Performance.SDK.Timestamp;
14 |
15 | using AddressETW = Microsoft.Windows.EventTracing.Address;
16 | using AddrVal = System.UInt64;
17 |
18 | namespace NetBlameCustomDataSource
19 | {
20 | [System.Diagnostics.DebuggerStepThrough()]
21 | public static class Extensions
22 | {
23 | public static bool IsNA(this string str) => System.String.IsNullOrWhiteSpace(str) || str == Util.strNA; // "N/A"
24 |
25 | public static bool HasValue(this in TimestampUI time) => (time.ToNanoseconds != 0); // zero-initialized struct
26 |
27 | public static bool HasMaxValue(this in TimestampUI time) => (time == TimestampUI.MaxValue);
28 |
29 | public static void SetMaxValue(this ref TimestampUI time) { time = TimestampUI.MaxValue; }
30 |
31 | public static bool Between(this in TimestampUI tRef, in TimestampUI tFirst, in TimestampUI tLast) => tRef >= tFirst && tRef <= tLast;
32 |
33 | public static TimestampUI ToGraphable(this in TimestampETW time) => new TimestampUI(time.RelativeTimestamp.Nanoseconds);
34 |
35 | public static TimestampETW Zero(this in TimestampETW time) => new TimestampETW(time.Context, time.Context.ReferenceValue);
36 |
37 | public static AddrVal ToValue(this in AddressETW addr) => (AddrVal)addr.Value;
38 |
39 | public static bool Empty(this IPAddress ipAddr) => ipAddr == null || ipAddr.Equals(IPAddress.Any/*0.0.0.0*/) || ipAddr.AddressFamily == System.Net.Sockets.AddressFamily.Unspecified;
40 |
41 | public static bool Empty(this IPEndPoint ipep) => ipep == null || (ipep.Port == 0 && ipep.Address.Empty());
42 |
43 | public static string ToGraphable(this IPAddress ipAddr) => ipAddr?.ToString() ?? String.Empty;
44 |
45 | public static string ToGraphable(this IPEndPoint ipEndPoint) => !ipEndPoint.Empty() ? ipEndPoint.ToString() : String.Empty;
46 | public static string AddrGraphable(this IPEndPoint ipEndPoint) => !ipEndPoint.Empty() ? ipEndPoint.Address.ToString() : String.Empty;
47 | public static uint PortGraphable(this IPEndPoint ipEndPoint) => (uint?)ipEndPoint?.Port ?? 0;
48 |
49 | public static bool Empty(this SocketAddress socket) => (socket == null || socket[0]/*family*/ == 0);
50 |
51 | // SocketAddress.Equals may give false negatives when the socket contains random padding bytes!
52 | public static bool SafeEquals(this SocketAddress socket, SocketAddress comparand)
53 | {
54 | if (socket == null || comparand == null)
55 | return false;
56 |
57 | if (socket.Family != comparand.Family)
58 | return false;
59 |
60 | if (socket.Port() != comparand.Port())
61 | return false;
62 |
63 | if (socket.Equals(comparand))
64 | return true;
65 |
66 | // Expensive!
67 | return Util.NewEndPoint(socket).Equals(Util.NewEndPoint(comparand));
68 | }
69 |
70 | public static bool IsAddrZero(this SocketAddress socket)
71 | {
72 | #if DEBUG
73 | if (socket.Empty()) return true;
74 |
75 | switch (socket.Family)
76 | {
77 | case System.Net.Sockets.AddressFamily.InterNetwork: // IPv4
78 | return Util.NewEndPoint(socket).Address.Equals(IPAddress.Any);
79 | case System.Net.Sockets.AddressFamily.InterNetworkV6: // IPv6
80 | return Util.NewEndPoint(socket).Address.Equals(IPAddress.IPv6Any);
81 | }
82 | return false;
83 | #else
84 | throw new NotImplementedException("IsAddrZero: Not intended for release.");
85 | #endif // DEBUG
86 | }
87 |
88 | public static ushort Port(this SocketAddress socket) => (ushort)((socket[2] << 8) + socket[3]);
89 |
90 | public static UInt16 GetUInt16(this IGenericEvent evt, string strField) => evt.Fields[strField].AsUInt16;
91 |
92 | public static UInt32 GetUInt32(this IGenericEvent evt, string strField) => evt.Fields[strField].AsUInt32;
93 |
94 | public static UInt64 GetUInt64(this IGenericEvent evt, string strField) => evt.Fields[strField].AsUInt64;
95 |
96 | public static UInt64 TryGetUInt64(this IGenericEvent evt, string strField) => evt.Fields.TryGetValue(strField, out IGenericEventField field) ? field.AsUInt64 : 0;
97 |
98 | public static IReadOnlyList GetBinary(this IGenericEvent evt, string strField) => evt.Fields[strField].AsBinary;
99 |
100 | public static UInt64 GetAddrValue(this IGenericEvent evt, string strField) => evt.Fields[strField].AsAddress.ToValue();
101 |
102 | public static UInt64 TryGetAddrValue(this IGenericEvent evt, string strField) => evt.Fields.TryGetValue(strField, out IGenericEventField field) ? field.AsAddress.ToValue() : 0;
103 |
104 | public static string GetString(this IGenericEvent evt, string strField) => evt.Fields[strField].AsString;
105 |
106 | public static string GetAddressString(this IGenericEvent evt) => (evt.GetUInt32("AddressLength") > 1) ? evt.GetString("Address") : null; // AddressLength includes 0
107 |
108 | public static SocketAddress GetSocketAddress(this IGenericEvent evt, string strField = "Address") => evt.Fields[strField].AsSocketAddress;
109 |
110 | public static SocketAddress GetLocalAddress(this IGenericEvent evt) => (evt.GetUInt32("LocalAddressLength") != 0) ? evt.GetSocketAddress("LocalAddress") : null;
111 |
112 | public static SocketAddress GetRemoteAddress(this IGenericEvent evt) => (evt.GetUInt32("RemoteAddressLength") != 0) ? evt.GetSocketAddress("RemoteAddress") : null;
113 |
114 | // Simple hash of all addresses in the stack. Returns 0 if none.
115 | public static int Hash(this IStackSnapshot ss)
116 | {
117 | if (ss?.Frames == null) return 0;
118 |
119 | int hash = 0;
120 | foreach (var frame in ss.Frames)
121 | hash ^= frame.Address.GetHashCode();
122 |
123 | return hash;
124 | }
125 | }
126 |
127 | } // NetBlameCustomDataSource.Events
128 |
--------------------------------------------------------------------------------
/src/NetBlame/Providers/Thread.Classic.cs:
--------------------------------------------------------------------------------
1 | // Copyright(c) Microsoft Corporation.
2 | // Licensed under the MIT License.
3 |
4 | using System;
5 | using System.Collections.Generic;
6 | using System.Runtime.InteropServices; // StructLayout
7 |
8 | using Microsoft.Windows.EventTracing; // ClassicEvent
9 |
10 | using static NetBlameCustomDataSource.Util;
11 |
12 | using TimestampETW = Microsoft.Windows.EventTracing.TraceTimestamp;
13 |
14 | using DWId = System.Int32; // Process/ThreadID (ideally UInt32)
15 |
16 | using Addr32 = System.UInt32;
17 | using Addr64 = System.UInt64;
18 |
19 |
20 | namespace NetBlameCustomDataSource.Thread.Classic
21 | {
22 | #pragma warning disable 649 // StructFromBytes initializes the fields.
23 |
24 | [StructLayout(LayoutKind.Sequential, Pack = 4)]
25 | public class ThreadClassicEvent
26 | {
27 | public readonly TimestampETW timeStamp;
28 | public readonly DWId pidInitiator;
29 | public DWId tidInitiator;
30 | public readonly byte opEvent;
31 |
32 | /*
33 | Initialize a sequential struct from payload bytes.
34 | */
35 | public static void StructFromBytes(in ReadOnlySpan data, out T payload) where T : struct
36 | {
37 | bool fSuccess = MemoryMarshal.TryRead(data, out payload);
38 | AssertCritical(fSuccess);
39 | }
40 |
41 | public ThreadClassicEvent(in ClassicEvent evt)
42 | {
43 | this.pidInitiator = (DWId)evt.ProcessId;
44 | this.tidInitiator = (DWId)evt.ThreadId;
45 | this.opEvent = (byte)evt.Id;
46 |
47 | this.timeStamp = evt.Timestamp;
48 |
49 | if ((TEID)evt.Id != TEID.Rundown) return;
50 |
51 | // This is apparently what WPA does for rundown events: sets the (struct) timestamp to 0.
52 | this.timeStamp = evt.Timestamp.Zero();
53 |
54 | AssertCritical(this.timeStamp.TotalMicroseconds == 0);
55 | }
56 | } // ThreadClassicEvent
57 |
58 | [StructLayout(LayoutKind.Sequential, Pack = 4)]
59 | public readonly struct ThreadEventPayload
60 | {
61 | public readonly DWId ProcessId;
62 | public readonly DWId ThreadId;
63 | }
64 |
65 | public class THREAD_EVENT : ThreadClassicEvent
66 | {
67 | public readonly ThreadEventPayload ThreadEvt;
68 | public readonly Addr64 ThreadProc;
69 |
70 | const DWId tidUnknown = -1;
71 |
72 | private Addr32 GetThreadProc32(in ClassicEvent evt)
73 | {
74 | if (evt.Data.Length < 2*sizeof(UInt32) + 6*sizeof(UInt32))
75 | return 0;
76 |
77 | // Layout (wmicore.mof): PID (DW), TID (DW), (PTR)[5], ThreadProc (PTR)
78 | StructFromBytes(evt.Data.Slice(2*sizeof(UInt32) + 5*sizeof(UInt32), sizeof(UInt32)), out UInt32 threadProc);
79 | return threadProc;
80 | }
81 |
82 | private Addr64 GetThreadProc64(in ClassicEvent evt)
83 | {
84 | if (evt.Data.Length < 2*sizeof(UInt32) + 6*sizeof(UInt64))
85 | return 0;
86 |
87 | // Layout (wmicore.mof): PID (DW), TID (DW), (PTR)[5], ThreadProc (PTR)
88 | StructFromBytes(evt.Data.Slice(2*sizeof(UInt32) + 5*sizeof(UInt64), sizeof(UInt64)), out UInt64 threadProc);
89 | return threadProc;
90 | }
91 |
92 | public THREAD_EVENT(in ClassicEvent evt) : base(in evt)
93 | {
94 | // There are multiple versions of this event class.
95 | // In any case, just get the first two DWORDs.
96 | StructFromBytes(evt.Data.Slice(0, 2*sizeof(UInt32)), out this.ThreadEvt);
97 |
98 | // If the thread "created itself" then the creator/initiator is unknown.
99 | if (this.tidInitiator == this.ThreadEvt.ThreadId && (TEID)evt.Id != TEID.Exit)
100 | this.tidInitiator = tidUnknown;
101 |
102 | // Get the ThreadProc address if available. (See wmicore.mof: "Thread Create/Exit Event")
103 | if (evt.Version > 0)
104 | {
105 | if (evt.Is32Bit)
106 | this.ThreadProc = GetThreadProc32(evt);
107 | else
108 | this.ThreadProc = GetThreadProc64(evt);
109 | }
110 | }
111 | } // THREAD_EVENT
112 |
113 |
114 | // Thread Event ID
115 | // cf. wmicore.mof
116 | enum TEID : byte
117 | {
118 | Create = 1, // EVENT_TRACE_TYPE_START
119 | Exit = 2, // EVENT_TRACE_TYPE_END
120 | Rundown = 3,// EVENT_TRACE_TYPE_DC_START
121 | }
122 |
123 |
124 | /*
125 | Parse classic events as they are pre-processed via: traceProcessor.Process()
126 | */
127 | class ThreadEventConsumer
128 | {
129 | public Queue threadEventQueue;
130 | public Queue threadRundownQueue;
131 | #if DEBUG
132 | public bool FHaveRundown { get; set; }
133 | #else
134 | public bool FHaveRundown { get => true; set {} }
135 | #endif // DEBUG
136 |
137 | public ThreadEventConsumer()
138 | {
139 | const int capacity = 2048; // TODO: Intelligent initial capacity?
140 | threadEventQueue = new Queue(capacity);
141 | threadRundownQueue = new Queue(capacity/2);
142 | }
143 |
144 |
145 | /*
146 | By separating the rundown events (time=0) from the others (time>0),
147 | we join them together here, and thus the events are sorted by time.
148 | */
149 | public void Complete()
150 | {
151 | this.FHaveRundown = this.threadRundownQueue.Count > 0;
152 |
153 | while (this.threadEventQueue.Count > 0)
154 | this.threadRundownQueue.Enqueue(this.threadEventQueue.Dequeue());
155 |
156 | this.threadEventQueue = this.threadRundownQueue;
157 | this.threadRundownQueue = null;
158 | }
159 |
160 |
161 | public void Process(in ClassicEvent evt)
162 | {
163 | THREAD_EVENT te;
164 |
165 | AssertCritical(evt.ProviderId == ThreadTable.guid);
166 |
167 | switch ((TEID)evt.Id)
168 | {
169 | case TEID.Create:
170 | case TEID.Exit:
171 | te = new THREAD_EVENT(evt);
172 |
173 | if (te.ThreadEvt.ThreadId != 0 && te.ThreadEvt.ProcessId > TcpIp.TcbRecord.pidSystem/*4*/)
174 | threadEventQueue.Enqueue(te);
175 |
176 | break;
177 |
178 | case TEID.Rundown:
179 | te = new THREAD_EVENT(evt);
180 |
181 | if (te.ThreadEvt.ThreadId != 0 && te.ThreadEvt.ProcessId > TcpIp.TcbRecord.pidSystem/*4*/)
182 | threadRundownQueue.Enqueue(te);
183 |
184 | break;
185 | }
186 | } // Process
187 | } // ThreadEventConsumer
188 | } // namespace NetBlameCustomDataSource.Thread.Classic
--------------------------------------------------------------------------------
/src/BETA/WPAP/Network.wpaProfile:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 | 0
53 |
54 |
55 |
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/src/WPAP/Threads.wpaProfile:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 | 0
75 |
76 |
77 |
78 |
79 |
80 |
81 |
--------------------------------------------------------------------------------
/src/NetBlame/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.suo
8 | *.user
9 | *.userosscache
10 | *.sln.docstates
11 |
12 | # User-specific files (MonoDevelop/Xamarin Studio)
13 | *.userprefs
14 |
15 | # Build results
16 | [Dd]ebug/
17 | [Dd]ebugPublic/
18 | [Rr]elease/
19 | [Rr]eleases/
20 | x64/
21 | x86/
22 | bld/
23 | [Bb]in/
24 | [Oo]bj/
25 | [Ll]og/
26 |
27 | # Visual Studio 2015 cache/options directory
28 | .vs/
29 | # Uncomment if you have tasks that create the project's static files in wwwroot
30 | #wwwroot/
31 |
32 | # MSTest test Results
33 | [Tt]est[Rr]esult*/
34 | [Bb]uild[Ll]og.*
35 |
36 | # NUNIT
37 | *.VisualState.xml
38 | TestResult.xml
39 |
40 | # Build Results of an ATL Project
41 | [Dd]ebugPS/
42 | [Rr]eleasePS/
43 | dlldata.c
44 |
45 | # .NET Core
46 | project.lock.json
47 | project.fragment.lock.json
48 | artifacts/
49 | **/Properties/launchSettings.json
50 |
51 | *_i.c
52 | *_p.c
53 | *_i.h
54 | *.ilk
55 | *.meta
56 | *.obj
57 | *.pch
58 | *.pdb
59 | *.pgc
60 | *.pgd
61 | *.rsp
62 | *.sbr
63 | *.tlb
64 | *.tli
65 | *.tlh
66 | *.tmp
67 | *.tmp_proj
68 | *.log
69 | *.vspscc
70 | *.vssscc
71 | .builds
72 | *.pidb
73 | *.svclog
74 | *.scc
75 |
76 | # Chutzpah Test files
77 | _Chutzpah*
78 |
79 | # Visual C++ cache files
80 | ipch/
81 | *.aps
82 | *.ncb
83 | *.opendb
84 | *.opensdf
85 | *.sdf
86 | *.cachefile
87 | *.VC.db
88 | *.VC.VC.opendb
89 |
90 | # Visual Studio profiler
91 | *.psess
92 | *.vsp
93 | *.vspx
94 | *.sap
95 |
96 | # TFS 2012 Local Workspace
97 | $tf/
98 |
99 | # Guidance Automation Toolkit
100 | *.gpState
101 |
102 | # ReSharper is a .NET coding add-in
103 | _ReSharper*/
104 | *.[Rr]e[Ss]harper
105 | *.DotSettings.user
106 |
107 | # JustCode is a .NET coding add-in
108 | .JustCode
109 |
110 | # TeamCity is a build add-in
111 | _TeamCity*
112 |
113 | # DotCover is a Code Coverage Tool
114 | *.dotCover
115 |
116 | # Visual Studio code coverage results
117 | *.coverage
118 | *.coveragexml
119 |
120 | # NCrunch
121 | _NCrunch_*
122 | .*crunch*.local.xml
123 | nCrunchTemp_*
124 |
125 | # MightyMoose
126 | *.mm.*
127 | AutoTest.Net/
128 |
129 | # Web workbench (sass)
130 | .sass-cache/
131 |
132 | # Installshield output folder
133 | [Ee]xpress/
134 |
135 | # DocProject is a documentation generator add-in
136 | DocProject/buildhelp/
137 | DocProject/Help/*.HxT
138 | DocProject/Help/*.HxC
139 | DocProject/Help/*.hhc
140 | DocProject/Help/*.hhk
141 | DocProject/Help/*.hhp
142 | DocProject/Help/Html2
143 | DocProject/Help/html
144 |
145 | # Click-Once directory
146 | publish/
147 |
148 | # Publish Web Output
149 | *.[Pp]ublish.xml
150 | *.azurePubxml
151 | # TODO: Comment the next line if you want to checkin your web deploy settings
152 | # but database connection strings (with potential passwords) will be unencrypted
153 | *.pubxml
154 | *.publishproj
155 |
156 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
157 | # checkin your Azure Web App publish settings, but sensitive information contained
158 | # in these scripts will be unencrypted
159 | PublishScripts/
160 |
161 | # NuGet Packages
162 | *.nupkg
163 | # The packages folder can be ignored because of Package Restore
164 | **/packages/*
165 | # except build/, which is used as an MSBuild target.
166 | !**/packages/build/
167 | # Uncomment if necessary however generally it will be regenerated when needed
168 | #!**/packages/repositories.config
169 | # NuGet v3's project.json files produces more ignorable files
170 | *.nuget.props
171 | *.nuget.targets
172 |
173 | # Microsoft Azure Build Output
174 | csx/
175 | *.build.csdef
176 |
177 | # Microsoft Azure Emulator
178 | ecf/
179 | rcf/
180 |
181 | # Windows Store app package directories and files
182 | AppPackages/
183 | BundleArtifacts/
184 | Package.StoreAssociation.xml
185 | _pkginfo.txt
186 |
187 | # Visual Studio cache files
188 | # files ending in .cache can be ignored
189 | *.[Cc]ache
190 | # but keep track of directories ending in .cache
191 | !*.[Cc]ache/
192 |
193 | # Others
194 | ClientBin/
195 | ~$*
196 | *~
197 | *.dbmdl
198 | *.dbproj.schemaview
199 | *.jfm
200 | *.pfx
201 | *.publishsettings
202 | orleans.codegen.cs
203 |
204 | # Since there are multiple workflows, uncomment next line to ignore bower_components
205 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
206 | #bower_components/
207 |
208 | # RIA/Silverlight projects
209 | Generated_Code/
210 |
211 | # Backup & report files from converting an old project file
212 | # to a newer Visual Studio version. Backup files are not needed,
213 | # because we have git ;-)
214 | _UpgradeReport_Files/
215 | Backup*/
216 | UpgradeLog*.XML
217 | UpgradeLog*.htm
218 |
219 | # SQL Server files
220 | *.mdf
221 | *.ldf
222 |
223 | # Business Intelligence projects
224 | *.rdl.data
225 | *.bim.layout
226 | *.bim_*.settings
227 |
228 | # Microsoft Fakes
229 | FakesAssemblies/
230 |
231 | # GhostDoc plugin setting file
232 | *.GhostDoc.xml
233 |
234 | # Node.js Tools for Visual Studio
235 | .ntvs_analysis.dat
236 | node_modules/
237 |
238 | # Typescript v1 declaration files
239 | typings/
240 |
241 | # Visual Studio 6 build log
242 | *.plg
243 |
244 | # Visual Studio 6 workspace options file
245 | *.opt
246 |
247 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
248 | *.vbw
249 |
250 | # Visual Studio LightSwitch build output
251 | **/*.HTMLClient/GeneratedArtifacts
252 | **/*.DesktopClient/GeneratedArtifacts
253 | **/*.DesktopClient/ModelManifest.xml
254 | **/*.Server/GeneratedArtifacts
255 | **/*.Server/ModelManifest.xml
256 | _Pvt_Extensions
257 |
258 | # Paket dependency manager
259 | .paket/paket.exe
260 | paket-files/
261 |
262 | # FAKE - F# Make
263 | .fake/
264 |
265 | # JetBrains Rider
266 | .idea/
267 | *.sln.iml
268 |
269 | # CodeRush
270 | .cr/
271 |
272 | # Python Tools for Visual Studio (PTVS)
273 | __pycache__/
274 | *.pyc
275 |
276 | # Cake - Uncomment if you are using it
277 | # tools/**
278 | # !tools/packages.config
279 |
280 | # vim temp (~) files
281 | *~
282 |
--------------------------------------------------------------------------------
/src/BETA/TraceEdgeChrome.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .NOTES
3 |
4 | Copyright (c) Microsoft Corporation.
5 | Licensed under the MIT License.
6 |
7 | .SYNOPSIS
8 |
9 | Capture and View an ETW trace:
10 | CPU Samples, Thread Dispatch, File I/O, Office Logging Providers, ThreadPool, Processes, Modules
11 |
12 | .DESCRIPTION
13 |
14 | .\TraceEdgeChrome Start [-Loop] [-CLR]
15 | .\TraceEdgeChrome Stop [-WPA [-FastSym]]
16 | .\TraceEdgeChrome View [-Path \MSO-Trace-EdgeChrome.etl|.wpapk] [-FastSym]
17 | .\TraceEdgeChrome Status
18 | .\TraceEdgeChrome Cancel
19 | -Loop: Record only the last few minutes of activity (circular memory buffer).
20 | -CLR: Resolve call stacks for C# (Common Language Runtime).
21 | -WPA: Launch the WPA viewer (Windows Performance Analyzer) with the collected trace.
22 | -Path: Optional path to a previously collected trace.
23 | -FastSym: Load symbols only from cached/transcoded SymCache, not from slower PDB files.
24 | See: https://github.com/microsoft/MSO-Scripts/wiki/Advanced-Symbols#optimize
25 | -Verbose
26 |
27 | .LINK
28 |
29 | https://learn.microsoft.com/en-us/windows-hardware/test/wpt/event-tracing-for-windows
30 | https://learn.microsoft.com/en-us/shows/defrag-tools/39-windows-performance-toolkit
31 | #>
32 |
33 | [CmdletBinding(DefaultParameterSetName = "View")]
34 | Param(
35 | # "Start, Stop, Status, Cancel, View"
36 | [Parameter(Position=0)]
37 | [string]$Command,
38 |
39 | # Record only the last few minutes of activity (circular memory buffer).
40 | [Parameter(ParameterSetName="Start")]
41 | [switch]$Loop,
42 |
43 | # "Support Common Language Runtime / C#"
44 | [Parameter(ParameterSetName="Start")]
45 | [switch]$CLR,
46 |
47 | # "Launch WPA after collecting the trace"
48 | [Parameter(ParameterSetName="Stop")]
49 | [switch]$WPA,
50 |
51 | # "Optional path to a previously collected trace: MSO-Trace-EdgeChrome.etl"
52 | [Parameter(ParameterSetName="View")]
53 | [string]$Path = $Null,
54 |
55 | # "Faster symbol resolution by loading only from SymCache, not PDB"
56 | [Parameter(ParameterSetName="Stop")]
57 | [Parameter(ParameterSetName="View")]
58 | [switch]$FastSym
59 |
60 | # [switch]$Verbose # implicit
61 | )
62 |
63 | # ===== CUSTOMIZE THIS =====
64 |
65 | $TraceParams =
66 | @{
67 | RecordingProfiles =
68 | @(
69 | ".\WPRP\MSEdge.wprp!MSEdge_Filtered" # Includes Chrome
70 | "..\WPRP\JS.wprp!JS"
71 | # "..\WPRP\CPU.wprp!CPU-Dispatch"
72 | # "..\WPRP\FileDiskIO.wprp!FileAndDiskIO"
73 | # "..\WPRP\OfficeProviders.wprp!OfficeLogging"
74 | # "..\WPRP\Handles.wprp!AllHandles"
75 | # "..\WPRP\Defender.wprp!DefenderFull"
76 |
77 | <# ^^^ The first entry is the base recording profile for this script.
78 | vvv Additional recording profile string(s) follow. See ..\ReadMe.txt
79 |
80 | "Registry" # Built-in
81 | "..\WPRP\FileDiskIO.wprp!FileIO"
82 | "c:\MyProfiles\MyRecordingProfile.wprp!CustomProfile"
83 |
84 | Other recording profiles can be added via the WPT_WPRP environment variable.
85 | $Env:WPT_WPRP="c:\path\MyProfile.wprp!ProfileName;c:\path\MyProfile2.wprp!ProfileName2"
86 | set WPT_WPRP=c:\path\MyProfile.wprp!ProfileName;c:\path\MyProfile2.wprp!ProfileName2
87 |
88 | Other recording providers can be added via the WPT_XPERF environment variable (in "XPerf -ON" format).
89 | $Env:WPT_XPERF="GUIDorNAME1 + GUIDorNAME2:::Stack + GUIDorNAME3:KeywordFlags:Level + ..."
90 | set WPT_XPERF=GUIDorNAME1 + GUIDorNAME2:::Stack + GUIDorNAME3:KeywordFlags:Level + ...
91 |
92 | See: https://github.com/microsoft/MSO-Scripts/wiki/Customize-Tracing#envvar
93 | #>
94 | )
95 |
96 | ProviderManifests =
97 | @(
98 | # Optional: Register ETW Provider Manifests not registered by default.
99 | # See: .\OETW\ReadMe.txt
100 | ".\OETW\EdgeETW.man"
101 | ".\OETW\ChromeETW.man"
102 | )
103 |
104 | # This is the arbitrary name of the tracing session/instance:
105 | InstanceName = "MSO-Trace-EdgeChrome"
106 | }
107 |
108 | $ViewerParams =
109 | @{
110 | # The configuration files define the data tabs in the WPA viewer.
111 | # https://learn.microsoft.com/en-us/windows-hardware/test/wpt/view-profiles
112 | ViewerConfig = ".\WPAP\MSEdge.wpaProfile"
113 |
114 | # The default trace file name is: .etl
115 | TraceName = $TraceParams.InstanceName
116 |
117 | # Optional alternate path to a previously collected ETL trace:
118 | TraceFilePath = $Path
119 | }
120 |
121 | # ===== END CUSTOMIZE ====
122 |
123 | if (!$script:PSScriptRoot) { $script:PSScriptRoot = Split-Path -Parent -Path $script:MyInvocation.MyCommand.Definition } # for PSv2
124 | $script:ScriptHomePath = $PSScriptRoot
125 | $script:ScriptRootPath = "$PSScriptRoot\.."
126 | $script:PSScriptParams = $script:PSBoundParameters # volatile
127 |
128 | . "$ScriptRootPath\INCLUDE.ps1"
129 |
130 | # Main
131 |
132 | if ($Command -ne "View")
133 | {
134 | $Win10VerMin = '10.0.15002' # Min version for both Windows and WPR for
135 | $Win10VerCur = [Environment]::OSVersion.Version
136 |
137 | if ($Win10VerCur -lt $Win10VerMin)
138 | {
139 | Write-Err "This trace requires Windows 10 v$Win10VerMin. Current version is: v$Win10VerCur"
140 | exit 1
141 | }
142 |
143 | CheckPrerequisites # Sets script:WPR_Win10Ver
144 |
145 | if (!(!$script:WPR_PreWin10 -and ($script:WPR_Win10Ver -ge $Win10VerMin)))
146 | {
147 | Write-Err "This trace requires WPR.exe v$Win10VerMin. Current version is: v$script:WPR_Win10Ver"
148 | Write-Err $script:WPR_Path
149 | exit 1
150 | }
151 | }
152 |
153 | $Result = ProcessTraceCommand $Command @TraceParams -Loop:$Loop -CLR:$CLR
154 |
155 | switch ($Result)
156 | {
157 | Started { Write-Msg "ETW tracing has begun.`nExercise the application, then run: $(GetScriptCommand) Stop [-WPA]`n" }
158 | Collected { WriteTraceCollected $TraceParams.InstanceName } # $WPA switch
159 | View { $WPA = $True }
160 | Success { $WPA = $False }
161 | Error { exit 1 }
162 | }
163 |
164 | if ($WPA)
165 | {
166 | LaunchViewer @ViewerParams -FastSym:$FastSym
167 |
168 | Write-Warn "`nPlease be patient, as it may take several minutes for WPA to organize the thousands of events."
169 | Write-Status "This is mainly due to the Regions of Interest (Timelines View)."
170 | }
171 |
172 | exit 0 # Success
173 |
--------------------------------------------------------------------------------
/src/WPRP/ThreadPool.wprp:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
13 |
14 |
15 |
16 |
17 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
64 |
65 |
66 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
96 |
97 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
115 |
116 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
129 |
130 |
131 |
132 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
--------------------------------------------------------------------------------
/src/PreWin10/WPRP/CPU.wprp:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
13 |
14 |
15 |
16 |
17 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
102 |
103 |
107 |
108 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
121 |
122 |
123 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
146 |
147 |
148 |
149 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
--------------------------------------------------------------------------------