【问题标题】:Pass entire hashtable to Invoke-Expression将整个哈希表传递给 Invoke-Expression
【发布时间】:2019-03-16 15:43:15
【问题描述】:

我想问你一个关于将哈希表传递给 Invoke-Expression 的问题。

我正在编写简单的 E2E 监控,并提到哈希表用作包含 HTTP 表单凭据的主体以记录 jira。 它对我来说很好,但出于特定原因,我想根据收到的参数动态创建这个 Invoke-Webrequest。 这就是我的收获。

因此,我不知道如何将哈希表(其他数据类型也可以,如字符串或 int)传递给 Invoke Expression。 它总是像System.Collections.Hashtable

$uri = 'https://exdom.com/login.jsp?saml_sso=false'
$method = "POST"
$postParams = @{
    os_username = "username";
    os_password = "password";
    login = "true"
}

$scriptBlock = {
    param(
        [Parameter(Mandatory=$true,Position=1)][string]$uri,
        [Parameter(Mandatory=$false,Position=2)][string]$method,
        [Parameter(Mandatory=$true,Position=3)][hashtable]$postParams
    )
    $commandFragments = @()
    $commandFragments += "Invoke-WebRequest"
    if ( $PSBoundParameters.ContainsKey('uri')){
        $commandFragments += " -Uri $uri"
    }
    if ( $PSBoundParameters.ContainsKey('method')){
        $commandFragments += " -Method $method"
    }
    if ( $PSBoundParameters.ContainsKey('postParams')){
        $commandFragments += " -Body $postParams"
    }
    $commandFromFragments = $commandFragments -join ''
    (Invoke-Expression -Command $commandFromFragments).Content | Out-File 'c:\tmp\response3.html'
    (Invoke-Expression -Command "Invoke-WebRequest -Uri https://exdom.com/login.jsp?saml_sso=false -Method POST -Body @(@{'os_username' = 'username@mydomain.com'; 'os_password' = 'mypassword'; 'login' = 'true'})").Content | Out-File 'c:\tmp\response4.html'
    (Invoke-WebRequest -Method $method -Uri $uri -Body $postParams).Content | Out-File 'c:\tmp\response5.html'
}

Invoke-Command -ScriptBlock $scriptBlock -ArgumentList ($uri, $method, $postParams)

我想我缺少一些基本的东西。 可以请教一下吗?

谢谢,马塞尔

【问题讨论】:

  • 使用喷溅。 Invoke-Expression 这里不需要。
  • $commandFragments += " -Body $postParams" splatting and the & operator instead

标签: powershell hashtable


【解决方案1】:

让我们谈谈有什么问题。

$commandFragments += " -Body $postParams"

您正在将 HashTable 转换为字符串。这是不可能的。所以我们能做的就是把它转化成某种东西。现在我们应该转换成什么? Invoke-WebRequest -body

这可以通过 Json 来完成。所以你可以使用 " -Body $($postParams | convertto-json)"

但这只是将 json 保存到一个仍然不起作用的字符串中,因为 Json 需要位于命令 Invoke-WebRequest 内的字符串中。所以解决方法是用单引号将 JSON 括起来。 " -Body '$($postParams | ConvertTo-Json)'"

我们还可以进行一些小的修复以提高效率。就像 if 语句看起来

$PSBoundParameters.GetEnumerator() | %{
    switch($_.Key){
        "uri" { $commandFragments += " -Uri $uri" }
        "method" { $commandFragments += " -Method $method" }
        "postParams" { $commandFragments += " -Body '$($postParams | ConvertTo-Json)'" }
    }
}

最终产品是

$uri = 'https://exdom.com/login.jsp?saml_sso=false'
$method = "POST"
$postParams = @{
    "os_username" = "username";
    "os_password" = "password";
    "login" = "true"
}

$scriptBlock = {
    param(
        [Parameter(Mandatory=$true,Position=1)][string]$uri,
        [Parameter(Mandatory=$false,Position=2)][string]$method,
        [Parameter(Mandatory=$true,Position=3)][hashtable]$postParams
    )

    $commandFragments = $("Invoke-WebRequest")
    $PSBoundParameters.GetEnumerator() | %{
        switch($_.Key){
            "uri" { $commandFragments += " -Uri $uri" }
            "method" { $commandFragments += " -Method $method" }
            "postParams" { $commandFragments += " -Body '$($postParams | ConvertTo-Json)'" }
        }
    }
    (Invoke-Expression -Command $($commandFragments -join '')).Content | Out-File 'c:\tmp\response3.html'
    (Invoke-Expression -Command "Invoke-WebRequest -Uri https://exdom.com/login.jsp?saml_sso=false -Method POST -Body @(@{'os_username' = 'username@mydomain.com'; 'os_password' = 'mypassword'; 'login' = 'true'})").Content | Out-File 'c:\tmp\response4.html'
    (Invoke-WebRequest -Method $method -Uri $uri -Body $postParams|ConvertTo-Json).Content
}

Invoke-Command -ScriptBlock $scriptBlock -ArgumentList ($uri, $method, $postParams)

【讨论】:

    猜你喜欢
    • 2020-09-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-22
    • 2020-06-14
    相关资源
    最近更新 更多