clockres.psm1
using namespace System.Linq using namespace System.Reflection using namespace System.ComponentModel using namespace System.Linq.Expressions using namespace System.Runtime.InteropServices $keys, $types = ($x = [PSObject].Assembly.GetType( 'System.Management.Automation.TypeAccelerators' ))::Get.Keys, @{ uint_ = [UInt32].MakeByRefType() } $types.Keys.ForEach{ if ($_ -notin $keys) { $x::Add($_, $types.$_) } } function New-Delegate { [CmdletBinding()] param( [Parameter(Mandatory, Position=0)] [ValidateNotNullOrEmpty()] [String]$Module, [Parameter(Mandatory, Position=1)] [ValidateScript({![String]::IsNullOrEmpty($_)})] [ScriptBlock]$Signature ) begin { $kernel32 = @{} [Array]::Find(( Add-Type -AssemblyName Microsoft.Win32.SystemEvents -PassThru ), [Predicate[Type]]{$args[0].Name -eq 'kernel32'} ).GetMethods([BindingFlags]'NonPublic, Static, Public').Where{ $_.Name -cmatch '\AGet(P|M)' }.ForEach{ $kernel32[$_.Name] = $_ } if (( $mod = $kernel32.GetModuleHandle.Invoke($null, @($Module)) ) -eq [IntPtr]::Zero) { throw [DllNotFoundException]::new("Can not find $Module library.") } } process {} end { $funcs = @{} for ($i, $m, $fn, $p = 0, ([Expression].Assembly.GetType( 'System.Linq.Expressions.Compiler.DelegateHelpers' ).GetMethod('MakeNewCustomDelegate', [BindingFlags]'NonPublic, Static') ), [Marshal].GetMethod('GetDelegateForFunctionPointer', ([IntPtr])), $Signature.Ast.FindAll({$args[0].CommandElements}, $true).ToArray(); $i -lt $p.Length; $i++ ) { $fnret, $fname = ($def = $p[$i].CommandElements).Value if (( $fnsig = $kernel32.GetProcAddress.Invoke($null, @($mod, $fname)) ) -eq [IntPtr]::Zero) { throw [InvalidOperationException]::new("Can not find $fname signature.") } $fnargs = $def.Pipeline.Extent.Text [Object[]]$fnargs = (( ($fnargs -replace '\[|\]' -split ',\s+?') + $fnret ), $fnret)[[String]::IsNullOrEmpty($fnargs)] $funcs[$fname] = $fn.MakeGenericMethod( [Delegate]::CreateDelegate([Func[[Type[]], Type]], $m).Invoke($fnargs) ).Invoke([Marshal], $fnsig) } Set-Variable $Module -Value $funcs -Scope Script -Force } } Set-Alias -Name clockres -Value Get-ClockRes function Get-ClockRes { [CmdletBinding()]param() process { New-Delegate ntdll { int NtQueryTimerResolution([uint_, uint_, uint_]) int RtlNtStatusToDosError([int]) } $max, $min, $cur = [UInt32[]](,0 * 3) if (($nts = $ntdll.NtQueryTimerResolution.Invoke([ref]$max, [ref]$min, [ref]$cur)) -ne 0) { throw "$([Win32Exception]::new($ntdll.RtlNtStatusToDosError.Invoke($nts)).Message)" } ($zip = [Enumerable]::Zip( [String[]]('Maximum', 'Minimum', 'Current'), [String[]]($max, $min, $cur).ForEach{' timer resolution: {0:f3} ms' -f ($_ / 10000)}, [Func[String, String, String]]{$args[0] + $args[1]} )) $zip.Dispose() } } Export-ModuleMember -Alias clockres -Function Get-ClockRes |