Skip to content

Instantly share code, notes, and snippets.

@jborean93
Last active August 19, 2024 19:40
Show Gist options
  • Save jborean93/e1cdae68b3c9728dd95a4f800ad8da61 to your computer and use it in GitHub Desktop.
Save jborean93/e1cdae68b3c9728dd95a4f800ad8da61 to your computer and use it in GitHub Desktop.
Splits the input string using the Win32 argument splitter
# Copyright: (c) 2024, Jordan Borean (@jborean93) <[email protected]>
# MIT License (see LICENSE or https://opensource.org/licenses/MIT)
#Requires -Module Ctypes
Function Split-ExeArgument {
[OutputType([string])]
[CmdletBinding()]
param (
[Parameter(Mandatory, ValueFromPipeline)]
[string[]]
$InputObject
)
begin {
$s32 = New-CtypesLib Shell32.dll
$s32.CharSet('Unicode').SetLastError().Returns([IntPtr]).CommandLineToArgvW = [Ordered]@{
lpCmdLine = [string]
pNumArgs = [ref][int]
}
}
process {
foreach ($cmdArg in $InputObject) {
$numArgs = 0
$res = $s32.CommandLineToArgvW($cmdArg, [ref]$numArgs)
if ($res -eq [IntPtr]::Zero) {
$exc = [System.ComponentModel.Win32Exception]::new($s32.LastError)
$err = [System.Management.Automation.ErrorRecord]::new(
$exc,
"FailedToConvert",
"NotSpecified",
$cmdArg)
$err.ErrorDetails = 'Failed to split argument ''{0}'' 0x{1:X8}: {2}' -f @($cmdArg, $exc.NativeErrorCode, $exc.Message)
$PSCmdlet.WriteError($err)
continue
}
try {
$argPtrs = [IntPtr[]]::new($numArgs)
[System.Runtime.InteropServices.Marshal]::copy($res, $argPtrs, 0, $numArgs)
foreach ($ptr in $argPtrs) {
[System.Runtime.InteropServices.Marshal]::PtrToStringUni($ptr)
}
}
finally {
[System.Runtime.InteropServices.Marshal]::FreeHGlobal($res)
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment