将整个哈希表传递给Invoke-Expression

时间:2018-10-11 14:03:57

标签: powershell hashtable

我想问您一个有关将哈希表传递给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)

我想我缺少一些基本知识。 我可以问你个建议吗?

谢谢,马塞尔(Marcel)

1 个答案:

答案 0 :(得分:-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)