PowerShell中C#嵌套Struct引用及New-Object使用实践问询
问题解答
1. 嵌套结构体(MyClass内部的MyRECT)的正确引用方式
当结构体嵌套在类内部时,PowerShell中不能用[MyClass]::MyRECT作为New-Object的参数,因为New-Object需要的是类型的完全限定名称或者System.Type对象。对于.NET嵌套类型,其完全限定名称的格式是外层类型名+内层类型名(用+连接,而非.)。
正确的两种引用方式:
- 使用类型名称字符串:
$Rectangle = New-Object -TypeName MyClass+MyRECT - 先获取
Type对象再实例化:$rectType = [MyClass+MyRECT] $Rectangle = New-Object $rectType
2. Struct是否必须与Class同级?
不需要。Struct完全可以嵌套在Class内部,这是.NET允许的类型组织方式,嵌套结构体可以访问外层类的私有成员(如果业务需要),也能起到封装作用,只是引用时要遵循嵌套类型的命名规则。
3. 调用GetWindowRect的两种实践建议
实践一:自定义RECT结构体 + 显式声明P/Invoke方法
这种方式灵活性高,适合需要直接操作RECT字段的场景:
Add-Type @" using System; using System.Runtime.InteropServices; public class WindowApiHelper { // 嵌套结构体 public struct MyRECT { public int Left; public int Top; public int Right; public int Bottom; } [DllImport("user32.dll")] public static extern bool GetWindowRect(IntPtr hWnd, ref MyRECT lpRect); } "@ # 获取窗口句柄(示例:记事本窗口) $notepadHandle = (Get-Process notepad).MainWindowHandle # 实例化嵌套结构体 $rect = New-Object WindowApiHelper+MyRECT # 调用API [WindowApiHelper]::GetWindowRect($notepadHandle, [ref]$rect) # 输出结果 Write-Host "窗口位置:Left=$($rect.Left), Top=$($rect.Top), Right=$($rect.Right), Bottom=$($rect.Bottom)"
实践二:利用.NET内置类型 + 内存分配读取
这种方式无需自定义结构体,直接用Marshal类分配非托管内存并读取数据,适合临时调用的场景:
Add-Type @" using System; using System.Runtime.InteropServices; public class WindowApiHelper { [DllImport("user32.dll")] public static extern bool GetWindowRect(IntPtr hWnd, IntPtr lpRect); } "@ # 获取窗口句柄 $notepadHandle = (Get-Process notepad).MainWindowHandle # 分配非托管内存(RECT结构体大小为16字节:4个int,每个4字节) $rectPtr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal(16) try { # 调用API if ([WindowApiHelper]::GetWindowRect($notepadHandle, $rectPtr)) { # 读取每个字段的值 $left = [System.Runtime.InteropServices.Marshal]::ReadInt32($rectPtr, 0) $top = [System.Runtime.InteropServices.Marshal]::ReadInt32($rectPtr, 4) $right = [System.Runtime.InteropServices.Marshal]::ReadInt32($rectPtr, 8) $bottom = [System.Runtime.InteropServices.Marshal]::ReadInt32($rectPtr, 12) Write-Host "窗口位置:Left=$left, Top=$top, Right=$right, Bottom=$bottom" } } finally { # 释放非托管内存 [System.Runtime.InteropServices.Marshal]::FreeHGlobal($rectPtr) }
内容的提问来源于stack exchange,提问作者LiquidMetal
相关产品推荐
相关产品推荐

