We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
How about something like this?
$LARGE_INTEGER = New-Struct LARGE_INTEGER { Int64 'QuadPart 0' Int32 'LowPart 0' UInt32 'HighPart 4' } -Explicit $FILE_DIRECTORY_INFORMATION = New-Struct FILE_DIRECTORY_INFORMATION { UInt32 'NextEntryOffset' UInt32 'FileIndex' LARGE_INTEGER 'CreationTime' LARGE_INTEGER 'LastAccessTime' LARGE_INTEGER 'LastWriteTime' LARGE_INTEGER 'ChangeTime' LARGE_INTEGER 'EndOfFile' LARGE_INTEGER 'AllocationSize' UInt32 'FileAttributes' UInt32 'FileNameLength' Byte[] 'FileName ByValArray 2' } -CharSet Unicode
It can be implemented with next (just an example because it can be done more pretty):
using namespace System.Reflection using namespace System.Reflection.Emit using namespace System.Management.Automation using namespace System.Runtime.InteropServices function Get-PSModuleBuilder { process { if (!($pmb = $ExecutionContext.SessionState.PSVariable.Get( 'PSModuleBuilder' # shouldn't be visible ).Value)) { Set-Variable -Name PSModuleBuilder -Value ($pmb = ([AssemblyBuilder]::DefineDynamicAssembly( ([AssemblyName]::new('PSModuleBuilder')), 'Run' )).DefineDynamicModule('PSModuleBuilder', $false) ) -Option Constant -Scope Global -Visibility Private $pmb } else { $pmb } } } function New-Struct { [CmdletBinding()] [OutputType([Type])] param( [Parameter(Mandatory, Position=0)] [ValidateNotNullOrEmpty()] [String]$Name, [Parameter(Mandatory, Position=1)] [ValidateScript({![String]::IsNullOrEmpty($_.ToString())})] [ScriptBlock]$Definition, [Parameter()] [PackingSize]$PackingSize = 'Unspecified', [Parameter()] [ValidateSet('Ansi', 'Auto', 'Unicode')] [CharSet]$CharSet = 'Ansi', [Parameter()] [Switch]$Explicit ) process { [TypeAttributes]$attr = 'BeforeFieldInit, Class, Public, Sealed' $type = switch ($Explicit) { $true {'Explicit'} $false {'Sequential'} } $attr = $attr -bor [TypeAttributes]::"$($type)Layout" $attr = $attr -bor [TypeAttributes]::"$($CharSet)Class" if (!($struct = ($pmb = Get-PSModuleBuilder).GetType($Name))) { $type = $pmb.DefineType($Name, $attr, [ValueType], $PackingSize) $ctor = [MarshalAsAttribute].GetConstructor( [BindingFlags]'Instance, Public', $null, [Type[]]@([UnmanagedType]), $null ) $sc = @([MarshalAsAttribute].GetField('SizeConst')) [PSParser]::Tokenize($Definition, [ref]$null).Where{ $_.Type -cmatch '\A(Command|String)\Z' }.ForEach{ if ($_.Type -eq 'Command') { $token = $_.Content # data type $ft = switch (($def = $pmb.GetType($token)) -eq $null) { $true { [Type]$token } $false { $def } # perhaps type is defined in assembly } } else { $token = @($_.Content.Trim() -split '\s+') # field name with additional data switch ($token.Length) { 1 { [void]$type.DefineField($token[0], $ft, 'Public') } 2 { switch ($Explicit) { $true { [void]$type.DefineField($token[0], $ft, 'Public').SetOffset([Int32]$token[1]) } $false { $unm = [UnmanagedType]$token[1] [void]$type.DefineField($token[0], $ft, 'Public, HasFieldMarshal').SetCustomAttribute( [CustomAttributeBuilder]::new($ctor, [Object]@($unm)) ) } }} 3 { $unm = [UnmanagedType]$token[1] [void]$type.DefineField($token[0], $ft, 'Public, HasFieldMarshal').SetCustomAttribute( [CustomAttributeBuilder]::new($ctor, $unm, $sc, @([Int32]$token[2])) ) } } } } # foreach $GetSize = $type.DefineMethod('GetSize', 'Public, Static', [Int32], [Type[]]@()) $il = $GetSize.GetILGenerator() $il.Emit([OpCodes]::ldtoken, $type) $il.Emit([OpCodes]::call, [Type].GetMethod('GetTypeFromHandle')) $il.Emit([OpCodes]::call, [Marshal].GetMethod('SizeOf', [Type[]]@([Type]))) $il.Emit([OpCodes]::ret) $Implicit = $type.DefineMethod( 'op_Implicit', 'PrivateScope, Public, Static, HideBySig, SpecialName', $type, [Type[]]@([IntPtr]) ) $il = $Implicit.GetILGenerator() $il.Emit([OpCodes]::ldarg_0) $il.Emit([OpCodes]::ldtoken, $type) $il.Emit([OpCodes]::call, [Type].GetMethod('GetTypeFromHandle')) $il.Emit([OpCodes]::call, [Marshal].GetMethod('PtrToStructure', [Type[]]@([IntPtr], [Type]))) $il.Emit([OpCodes]::unbox_any, $type) $il.Emit([OpCodes]::ret) $type.CreateType() } else { $struct } } }
The text was updated successfully, but these errors were encountered:
No branches or pull requests
How about something like this?
It can be implemented with next (just an example because it can be done more pretty):
The text was updated successfully, but these errors were encountered: