You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PowerShell调用非托管代码:枚举类型处理问题排查

问题描述

我正在使用PowerShell调用userenv.dll中的组策略更新API(RefreshPolicy和RefreshPolicyEx)。以下调用RefreshPolicy的代码可正常运行:

$sig =@'
[DllImport("userenv.dll", SetLastError = true, ExactSpelling = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool RefreshPolicy([MarshalAs(UnmanagedType.Bool)] bool bMachine);
'@
$mytype = add-type -memberdefinition $sig -Name "Win32RefreshGP" -Namespace Win32Functions -PassThru
$mytype::RefreshPolicy($false) # 刷新用户策略

但尝试导入包含枚举的RefreshPolicyEx定义时出现问题:

$sigEx =@'
public enum RefreshPolicyOption:uint
{ 
    RP_FORCE = 1,
    RP_SYNC = 2 
}

[DllImport("userenv.dll", SetLastError = true, ExactSpelling = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool RefreshPolicyEx([MarshalAs(UnmanagedType.Bool)] bool bMachine, RefreshPolicyOption dwOptions = 0);
'@
$mytypeEx = add-type -memberdefinition $sigEx -Name "Win32RefreshGP" -Namespace Win32Functions -PassThru
$mytypeEx::RefreshPolicyEx($false) # 刷新用户策略

调用时抛出错误:

Method invocation failed because [System.Object[]] does not contain a method named 'RefreshPolicyEx'.
At line:1 char:1

  • $mytypeEx::RefreshPolicyEx($false) # Refresh the user policy
  • + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
      + FullyQualifiedErrorId : MethodNotFound
    

怀疑是类型定义中使用枚举导致的问题,已尝试切换单/双引号,预期能像C#中正常工作,求解决思路。

解决思路

问题核心是Add-Type的-PassThru参数特性:当你在同一个-MemberDefinition中定义多个类型(此处为枚举RefreshPolicyOption和包含方法的类),-PassThru会返回一个包含所有生成类型的数组,而非单个类型对象。直接用$mytypeEx::RefreshPolicyEx调用时,实际是在数组对象上查找方法,自然会失败。

修复方案1:从返回数组中提取目标类

Add-Type返回的数组中,第一个元素是枚举,第二个是包含RefreshPolicyEx方法的类,通过索引提取即可:

$mytypeEx = Add-Type -MemberDefinition $sigEx -Name "Win32RefreshGP" -Namespace Win32Functions -PassThru
$gpClass = $mytypeEx[1] # 提取包含方法的类
$gpClass::RefreshPolicyEx($false)

修复方案2:将枚举和类分开定义

先单独创建枚举类型,再定义包含方法的类,此时-PassThru会返回单个类型对象:

# 先定义枚举
$enumSig = @'
public enum RefreshPolicyOption:uint
{ 
    RP_FORCE = 1,
    RP_SYNC = 2 
}
'@
Add-Type -MemberDefinition $enumSig -Name "RefreshPolicyOption" -Namespace Win32Functions

# 再定义RefreshPolicyEx方法
$methodSig = @'
[DllImport("userenv.dll", SetLastError = true, ExactSpelling = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool RefreshPolicyEx([MarshalAs(UnmanagedType.Bool)] bool bMachine, Win32Functions.RefreshPolicyOption dwOptions = 0);
'@
$mytypeEx = Add-Type -MemberDefinition $methodSig -Name "Win32RefreshGP" -Namespace Win32Functions -PassThru
$mytypeEx::RefreshPolicyEx($false)

修复方案3:不使用-PassThru,直接通过命名空间调用

如果不需要返回类型对象,可去掉-PassThru,直接用完整命名空间+类名调用方法:

Add-Type -MemberDefinition $sigEx -Name "Win32RefreshGP" -Namespace Win32Functions
[Win32Functions.Win32RefreshGP]::RefreshPolicyEx($false)
# 也可使用枚举值实现强制刷新:
[Win32Functions.Win32RefreshGP]::RefreshPolicyEx($false, [Win32Functions.RefreshPolicyOption]::RP_FORCE)

内容的提问来源于stack exchange,提问作者shocko

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 06:37:15