Skip to content

Instantly share code, notes, and snippets.

@Qazeer
Created July 6, 2023 22:41
Show Gist options
  • Save Qazeer/6c655627962f034aa2b6e92594770ee2 to your computer and use it in GitHub Desktop.
Save Qazeer/6c655627962f034aa2b6e92594770ee2 to your computer and use it in GitHub Desktop.
Convert .NET Usage Log files (created by the .NET CLR upon assembly execution) from the specified Source Directory into a single CSV file.
<#
.SYNOPSIS
Consolidate the Usage Log files (created by the .NET CLR upon assembly execution) from the specified Source Directory into a single CSV file.
Script inspired by the Move-KAPEConsoleHost_history.ps1 script from Andrew Rathbun and Matt Arbaugh: https://github.com/AndrewRathbun/DFIRPowerShellScripts/blob/main/Move-KAPEConsoleHost_history.ps1
.PARAMETER InputDir
Specify the folder which contains the Usage Log file(s). Ideally, the C:\ or C:\Users|Utilisateurs|Usuarios|Benutzer directory in order to grab the file(s) from all users.
.PARAMETER Destination
Specify the folder where the NetAssembly_UsageLogs.csv file will be placed.
.PARAMETER outputFile
Specify the output file name (by default NetAssembly_UsageLogs.csv).
#>
[CmdletBinding()]
param
(
[Parameter(Mandatory = $true,
Position = 1,
HelpMessage = 'Specify the folder which contains the Usage Log file(s). Ideally, the C:\ or C:\Users|Utilisateurs|Usuarios|Benutzer directory in order to grab the file(s) from all users.')]
[String]$InputDir,
[Parameter(Mandatory = $true,
Position = 2,
HelpMessage = 'Specify the folder where the NetAssembly_UsageLogs.csv file will be placed.')]
[String]$Destination,
[Parameter(Mandatory = $false,
HelpMessage = 'Specify the output file name (by default NetAssembly_UsageLogs.csv).')]
[String]$outputFile = "NetAssembly_UsageLogs.csv"
)
try {
# Check if $InputDir exists
if (-not (Test-Path -Path $InputDir -PathType Container)) {
throw "The directory $InputDir does not exist."
}
# Create the $Destination path if it does not exist
if (-not (Test-Path -Path $Destination -PathType Container)) {
# Create the directory, but do not prompt for confirmation (-Confirm:$false)
[void] (New-Item -ItemType Directory -Path $Destination -Confirm:$false)
}
# Regex pattern to extract username from file path
$usernameRegex = "\\(Users|Utilisateurs|Usuarios|Benutzer)\\(.+?)\\AppData\\"
# Look for Usage Log file(s) in $InputDir
$files = Get-ChildItem -Recurse -ErrorAction Stop -File -Path "$InputDir" -Include "*.log" | Where-Object { $_.FullName -match ".*\\AppData\\Local\\Microsoft\\CLR_.*\\UsageLogs\\.*" } | ForEach-Object{ $_.FullName }
# Check if files were found
if ($null -eq $files -or $files.Count -eq 0) {
Write-Host "No UsageLogs file(s) were found in $InputDir"
}
else {
Write-Host "Found $($files.Count) Usage Log file(s) in $InputDir"
}
$assembliesOutput = New-Object System.Collections.ArrayList
foreach ($file in $files) {
$fileItem = Get-Item $file
# Extract username from file path
$file -match $usernameRegex | Out-Null
$username = $matches[2]
Write-Host "Located $($file.BaseName) for $username"
$null = $assembliesOutput.Add([PSCustomObject]@{
User = $username
AssemblyName = $fileItem.BaseName
FirstExecutionTimestamp = $fileItem.CreationTimeUtc.ToString("yyyy-MM-ddTHH:mm:ssK")
LastExecutionTimestamp = $fileItem.LastWriteTimeUtc.ToString("yyyy-MM-ddTHH:mm:ssK")
File = $file
})
}
$assembliesOutput | Export-Csv -NoTypeInformation "$Destination\\$outputFile"
}
catch [System.Exception] {
# If an error occurred, print error details
Write-Error "An error occurred while running this script"
Write-Error "Exception type: $($_.Exception.GetType().FullName)"
Write-Error "Exception message: $($_.Exception.Message)"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment