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

如何处理PowerShell 6+中不再存在的System程序集问题?

解决方案:适配Impersonation模块到PowerShell 7+

针对你遇到的Joel Bennett的Impersonation模块在PowerShell 7+中因System.Collections.Generic.Stack[System.Security.Principal.WindowsImpersonationContext]类型缺失无法运行的问题,除了调用Windows PowerShell 5.1会话外,还有以下几种更优方案:

1. 重写模块核心逻辑适配.NET Core/.NET 5+

PowerShell 7基于.NET Core/.NET 5+,WindowsImpersonationContext依然存在,但模块原代码依赖的.NET Framework程序集加载逻辑在PS7中不兼容。你可以修改模块的核心实现:

  • 显式加载所需程序集:在模块开头添加代码确保加载正确的程序集
    Add-Type -AssemblyName System.Security.Principal.Windows
    
  • 替换栈类型声明:将原代码中的泛型栈声明替换为兼容PS7的写法
    # 修改后(PS7+兼容)
    $impersonationStack = [System.Collections.Generic.Stack[System.Security.Principal.WindowsImpersonationContext]]::new()
    
  • 关键说明:.NET Core中WindowsImpersonationContext的生命周期管理逻辑与.NET Framework一致,但需通过显式加载程序集避免隐式加载失败的问题。

2. 使用已适配PS7的第三方Impersonation模块

PowerShell Gallery中有多个已兼容PS7的凭据切换模块,可直接替代旧模块:

  • 安装PSImpersonation模块:
    Install-Module -Name PSImpersonation -Scope CurrentUser -Force
    
  • 该模块提供Invoke-Impersonated等命令,直接支持在PS7中切换凭据访问远程共享,无需依赖旧模块的.NET Framework逻辑。

3. 手动实现Win32 API调用(替代.NET API)

如果不想依赖.NET API的差异,可以直接调用Windows原生API实现 impersonation,核心是通过P/Invoke调用LogonUser、ImpersonateLoggedOnUser和RevertToSelf等函数:

Add-Type @"
using System;
using System.Runtime.InteropServices;
using System.Security.Principal;

public class ImpersonationHelper {
    [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
    public static extern bool LogonUser(
        string lpszUsername,
        string lpszDomain,
        string lpszPassword,
        int dwLogonType,
        int dwLogonProvider,
        out IntPtr phToken);

    [DllImport("advapi32.dll", SetLastError = true)]
    public static extern bool ImpersonateLoggedOnUser(IntPtr hToken);

    [DllImport("advapi32.dll", SetLastError = true)]
    public static extern bool RevertToSelf();

    [DllImport("kernel32.dll", SetLastError = true)]
    public static extern bool CloseHandle(IntPtr hObject);

    public static WindowsImpersonationContext Impersonate(string username, string domain, string password) {
        IntPtr token = IntPtr.Zero;
        try {
            if (!LogonUser(username, domain, password, 9, 0, out token)) {
                throw new System.ComponentModel.Win32Exception();
            }
            if (!ImpersonateLoggedOnUser(token)) {
                throw new System.ComponentModel.Win32Exception();
            }
            return WindowsIdentity.Impersonate(token);
        } finally {
            if (token != IntPtr.Zero) {
                CloseHandle(token);
            }
        }
    }
}
"@

# 使用示例
$context = [ImpersonationHelper]::Impersonate("RemoteUser", "Domain", "Password")
try {
    # 执行需要 impersonation 的操作,比如访问远程共享
    Get-ChildItem "\\RemoteMachine\Share"
} finally {
    $context.Undo()
    $context.Dispose()
}

这种方式完全绕过.NET版本差异,直接与Windows系统交互,兼容性更强。

4. 简化Windows PowerShell会话调用

如果坚持使用旧模块,可简化原会话调用代码,无需手动管理会话生命周期:

Invoke-Command -UseWindowsPowerShell {
    # 加载旧模块并执行命令
    Import-Module Impersonation
    My-LegacyCmdlet -Credential $Using:cred -Action { Get-ChildItem "\\RemoteMachine\Share" }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 14:52:57