i want create thread that run script code in powershell using CreateThread WinApi. i use this code but error occured:
function local:Get-ProcAddress {
Param (
[OutputType([IntPtr])]
[Parameter( Position = 0, Mandatory = $True )]
[String]
$Module,
[Parameter( Position = 1, Mandatory = $True )]
[String]
$Procedure
)
# Get a reference to System.dll in the GAC
$SystemAssembly = [AppDomain]::CurrentDomain.GetAssemblies() |
Where-Object { $_.GlobalAssemblyCache -And $_.Location.Split('\\')[-1].Equals('System.dll') }
$UnsafeNativeMethods = $SystemAssembly.GetType('Microsoft.Win32.UnsafeNativeMethods')
# Get a reference to the GetModuleHandle and GetProcAddress methods
$GetModuleHandle = $UnsafeNativeMethods.GetMethod('GetModuleHandle')
$GetProcAddress = $UnsafeNativeMethods.GetMethod('GetProcAddress')
# Get a handle to the module specified
$Kern32Handle = $GetModuleHandle.Invoke($null, @($Module))
$tmpPtr = New-Object IntPtr
$HandleRef = New-Object System.Runtime.InteropServices.HandleRef($tmpPtr, $Kern32Handle)
# Return the address of the function
$GetProcAddress.Invoke($null, @([Runtime.InteropServices.HandleRef]$HandleRef, $Procedure))
}
function local:Get-DelegateType {
Param (
[OutputType([Type])]
[Parameter( Position = 0)]
[Type[]]
$Parameters = (New-Object Type[](0)),
[Parameter( Position = 1 )]
[Type]
$ReturnType = [Void]
)
$Domain = [AppDomain]::CurrentDomain
$DynAssembly = New-Object Reflection.AssemblyName('ReflectedDelegate')
$AssemblyBuilder = $Domain.DefineDynamicAssembly($DynAssembly, [System.Reflection.Emit.AssemblyBuilderAccess]::Run)
$ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('InMemoryModule', $false)
$TypeBuilder = $ModuleBuilder.DefineType('MyDelegateType', 'Class, Public, Sealed, AnsiClass, AutoClass', [System.MulticastDelegate])
$ConstructorBuilder = $TypeBuilder.DefineConstructor('RTSpecialName, HideBySig, Public', [System.Reflection.CallingConventions]::Standard, $Parameters)
$ConstructorBuilder.SetImplementationFlags('Runtime, Managed')
$MethodBuilder = $TypeBuilder.DefineMethod('Invoke', 'Public, HideBySig, NewSlot, Virtual', $ReturnType, $Parameters)
$MethodBuilder.SetImplementationFlags('Runtime, Managed')
$TypeBuilder.CreateType()
}
and define createthread winapi:
# CreateThread
$CreateThreadAddr = Get-ProcAddress kernel32.dll CreateThread
$CreateThreadDelegate = Get-DelegateType @([IntPtr], [UInt32], [IntPtr], [IntPtr], [UInt32], [IntPtr]) ([IntPtr])
$CreateThread = [Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($CreateThreadAddr, $CreateThreadDelegate)
i call createthread winapi in this way:
$ThreadProcScript = {
Param (
[Parameter()]
[IntPtr]$lpParameter
)
calc.exe
return [Int32]0
}
$Delegate = Get-DelegateType @([IntPtr]) ([int32])
$Callback = $ThreadProcScript -as $Delegate
$CreateThread.Invoke(0,0,$Callback ,0,0,0)
but error occured: Cannot convert the "MyDelegateType" value of type "MyDelegateType" to type "System.IntPtr" how can i Fix this error? and is there another way to using create thread winapi in powershell?
Converting an managed object to IntPtr is possible by "pinning" the object, but this is very tricky business because it is only allowed in "unsafe" code. You can do it in C# using the 'fixed' statement. The GCHandle.AddrOfPinnedObject() method is an alternative that might be called directly from PowerShell, but I can't recommend it to you.
I'll warn you however that full generality "winapi" programming (or even using the unmanaged CreateThread) turns out to have of awful complexity if you try to do it in PowerShell. You would need to understand advanced .NET interop and PowerShell's restrictions on threads, both of which are only partially documented. Using .NET's System.Thread class instead of the windows API help with a part of this without the requirement for "unsafe" code, but even that approach is something I'd recommend you not do in PowerShell without a higher-level explanation than just "wanting" winapi programming in PowerShell.
For a up-to-date Powershell module that helps to abstract what's needed for lightweight (thread) based jobs for general purposes see PoshRSJob on GitHub. It will probably save you a lot of time debugging over trying to call the WINAPI functions yourself. Introductory article at https://learn-powershell.net/2015/03/31/introducing-poshrsjob-as-an-alternative-to-powershell-jobs/