【问题标题】:Custom Powershell Cmdlet - Create hidden accessible variable自定义 Powershell Cmdlet - 创建隐藏的可访问变量
【发布时间】:2013-08-22 22:46:47
【问题描述】:

我正在开发用于访问 REST Web 服务的自定义 Powershell Cmdlet。
Web 服务要求我进行身份验证,当我进行身份验证时,它会返回一个身份验证令牌,之后我必须将其包含在每个请求中。

我面临的问题是我无法以所需的方式存储令牌,因此我可以在身份验证后在命令中轻松使用它。

我希望它能以与 Connect-MSOLService 相同的方式工作。
对于那些不熟悉 Office 365 cmdlet 的人,我将给出一些示例。

Office 365 Cmdlet

$Credentials = 获取凭据
Connect-MSOLService -Credential $Credentials
获取-MSOLUser

在此示例中,Get-MSOLUser 将返回每个 Office 365 用户,因为之前已经调用了 Connect-MSOLService。

我的 Cmdlet

$Credentials = 获取凭据
$token = Connect-WebService -Credential $Credentials
获取服务器 -token $token
Get-Client -token $token

如您所见,我必须返回令牌并将其存储在一个变量中,并在身份验证后的每次调用中使用它。

所以这引出了我的问题,我如何才能将令牌“注入”到 Powershell 会话中,然后在我的 cmdlet/模块中的每个命令上“在后台”使用它?

感谢您的宝贵时间。

【问题讨论】:

    标签: c# powershell cmdlet


    【解决方案1】:

    我不知道微软是怎么做到的,但我认为一种方法是这样的:

    function Connect-WebService {
       param($credential)
    
       #Do all of the connection here
    
    
       #Set the global variable so it will be available outside of this function
       $script:token = ...
    }
    
    function Get-Server {
       param(
          $token = $script:token # By default use the globally set $token variable
      )
    }
    

    如果您在 PowerShell 模块中执行所有操作,这种方式将有效。

    【讨论】:

    • 我忘记提及的一件事是我正在用 C# 编写 Cmdlet。我将检查是否可以将变量注入 C# 代码中的全局变量。
    • 经过一番思考,即使我能够将token inn获取到全局变量中,我仍然需要执行Get-Service -token $token之类的命令,但感谢您的建议。
    • 我只记得 PowerShell 也有可以工作的脚本范围变量。我只是不知道这将如何在 C# Cmdlet 中工作,因为我从未编写过。您使用 C# 而不是 PowerShell 编写它是否有特定原因?
    • 你不能在你的 Cmdlet 中创建一个类成员变量。您的 Connect-WebService 设置它,如果它不为空,您的 Get-Server 将使用它。
    • 我会检查的。原因是 web 服务要求我通过 REST 请求数据,然后它以 Json 的形式返回,我需要将其序列化为我可以使用的类。在 C# 中完成所有“肮脏的工作”会更干净、更容易
    【解决方案2】:

    您必须小心将令牌存储在进程范围的变量中,因为可能有多个 PowerShell 运行空间在同一个进程中运行。但是,您可以做的是创建对 Dictionary 的静态引用,该 Dictionary 为运行 cmdlet 的运行空间存储令牌。您可以像这样获取运行空间 ID:

    Guid runspaceId = Guid.Empty;
    using (var ps = PowerShell.Create(RunspaceMode.CurrentRunspace))
    {
        runspaceId = ps.Runspace.InstanceId;
    }
    

    然后创建一个带有静态只读字段的静态类,如下所示:

    public static class TokenUtil {
        public static readonly Dictionary<Guid,PSObject> Tokens = new Dictionary<Guid,PSObject>();
    }
    

    检查此运行空间的现有令牌,如下所示:

    PSObject token = null;
    if (TokenUtil.Tokens.ContainsKey(runspaceId))
    {
        token = TokenUtil.Tokens[runspaceId];
    }
    

    【讨论】:

      【解决方案3】:

      如果使用 PowerShell 5.0 程序集,您可以从 PSCmdlet 继承并使用 SessionState 来存储变量。

      private string const variableName = "MyVar";
      private Token token = new Token("your token");
      SessionState.PSVariable.Set(new PSVariable(variableName, token, ScopedItemOptions.Private));
      

      然后您使用GetValue() 来检索它。

      Token storedToken = (Token)SessionState.PSVariable.GetValue(variableName);
      

      此变量可用于 PowerShell 会话,但会在 cmdlet 调用之间持续存在。我使用它在第一个查询中存储 API 令牌,并在它过期或会话关闭之前重复使用它。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-01-26
        • 2013-04-26
        • 1970-01-01
        • 2020-06-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多