首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将PowerShell变量作为cmdlet参数传递

将PowerShell变量作为cmdlet参数传递
EN

Stack Overflow用户
提问于 2017-09-08 17:41:33
回答 4查看 5K关注 0票数 6

我正在学习PowerShell为我的团队编写工具。我今天处于紧要关头,并且完成了这项工作,但是我想通过删除ForEach循环中的IF语句来简化它,因为命令之间的唯一区别是参数-replace-remove

代码语言:javascript
复制
Write-Host "This script removes or replaces en masse users' msds-SyncServerURL property"

DO {
    $TargetSSU=Read-Host "`nWhat msds-SyncServerURL do you want to replace or remove?"
    $UsersToBeFixed=Get-ADUser -Filter {msds-SyncServerURL -like $TargetSSU} -Properties ('name','samaccountname','msDS-SyncServerURL')
    IF ($UsersToBeFixed -eq $null) {
        Write-Host "`nNo users appear to have $TargetSSU as their msds-SyncServerURL value. Please try again."
    }
} UNTIL ($UsersToBeFixed -ne $null)

Write-Host "`n`nThe following users have $TargetSSU as their msds-SyncServerURL value:"
$UsersToBeFixed |select name,samaccountname,msds-syncserverurl|ft

DO {
    $Action=Read-Host "Do you want to [R]emove or [U]pdate $TargetSSU?"
} Until (($Action -eq "R") -or ($Action -eq "U"))    
    IF ($Action -eq "U") {
        DO {
            $NewSyncServer=Read-Host "`nEnter the new Sync Server's hostname (not the URL)"
            Write-Host "`nChecking to see if $NewSyncServer has a userfile share..."
            $VerifySyncServer=Test-Path \\$NewSyncServer\userfiles
            IF ($VerifySyncServer -eq $false) {
                Write-host "`n$NewSyncServer does not appear to be a valid Sync Server hostname. Please try again."
            }
        } UNTIL ($VerifySyncServer -eq $true)
        $TargetSSU="https://$NewSyncServer.ourdomain.com"
    }

ForEach ($userToBeFixed in $UsersToBeFixed) {
    Write-Host "`nFixing" ($usertobefixed).name
    IF ($Action -eq "R") {
        Set-ADObject -identity $userToBeFixed -remove @{"msDS-SyncServerUrl" = $TargetSSU}
    }
    IF ($Action -eq "U") {
        Set-ADObject -identity $userToBeFixed -replace @{"msDS-SyncServerUrl" = $TargetSSU}
    }
}

Write-Host "`nHere is the result of the operation:"
foreach ($userToBeFixed in $UsersToBeFixed) {
    Get-ADUser -Identity $userToBeFixed -Properties ('name','samaccountname','msDS-SyncServerURL')|select name,samaccountname,msds-syncserverurl
}

我最初使用了以下开关,尝试各种引号排列,甚至{$action=“替换”}:

代码语言:javascript
复制
Switch($action)
{
    R {'remove'}
    U {'replace'}
}

我还在ForEach循环中尝试了调用-表达式:

代码语言:javascript
复制
$CMD="Set-ADObject -identity $userToBeFixed -$action @{`"msDS-SyncServerUrl`" = $TargetSSU}"
Invoke-Expression -Command $CMD

通常情况下, Set-ADObject cmdlet会失败,通常抱怨System.Object[]无法找到接受'-remove‘、'System.Object[]’或‘System.’这样的位置参数。

我将问题隔离到Set-ADObject,不喜欢将$action变量用作参数。如果我将-$action替换为-replace-remove,它就会正常工作(正如上面的代码片段所示)。

我意识到这是一个小问题,但似乎毫无理由地拥有这样的冗余代码让我感到困扰。我很乐意学习如何解决这个问题。

而且,与此无关的是,我还没有找到更好的方法来做到这一点:

代码语言:javascript
复制
Until (($Action -eq "R") -or ($Action -eq "U"))

我已经搜索并尝试了其他解决方案,例如:

代码语言:javascript
复制
Until ($Action -eq @{"R" -or "U"})

但似乎无法巩固对多种条件的评价。这让我很困扰,但没有我在这里的主要问题那么多。

手下留情。我对这件事不熟悉。如果有人看到任何我能改进的地方,请告诉我。我想学这个。

谢谢。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2017-09-08 18:28:41

您可以使用溅溅解决这个问题。

例如:

代码语言:javascript
复制
$action = 'Recurse'
$params = @{ $action = $true }
Get-ChildItem @params

该示例在功能上等价于Get-ChildItem -Recurse

票数 4
EN

Stack Overflow用户

发布于 2017-09-09 04:22:19

坚持13的有用答案向您展示了如何通过散列表动态地传递参数。

至于:

而且,与此无关的是,我还没有找到更好的方法来做到这一点: ($Action -eq "R") -or ($Action -eq "U"))

PowerShell提供数组包含操作符:-contains (PSv1+,LHS上的数组)和-in (PSv3+,RHS上的数组):

代码语言:javascript
复制
# PSv3+
$Action -in 'R', 'U'

# Equivalent, PSv1+
'R', 'U' -contains $Action

这两种表单都将标量操作数与数组操作数的每个元素进行比较(使用-eq逻辑),并在找到第一个匹配项(如果有的话)后立即返回$True

另一个选项是使用带有正则表达式的-match运算符:

代码语言:javascript
复制
$Action -match '^(R|U)$'
票数 2
EN

Stack Overflow用户

发布于 2017-09-08 19:25:04

我喜欢将不涉及脚本逻辑(即函数)的所有内容移到与主PowerShell脚本不同的文件中。我的大多数脚本都遵循这样的结构:

Edit-SyncServerUrl.ps1

代码语言:javascript
复制
#requires -Version 5.1

<#
    Company header
#>

<#
.SYNOPSIS
Comment-based help
#>
[CmdletBinding(SupportsShouldProcess)]
Param([String]$Option)

. "$PSScriptRoot\scriptfunctions.ps1"

<# .. variables .. #>

Switch -Regex ($Option)
{
    '^rem' {Edit-SyncServerURL -Remove}
    '^rep' {Edit-SyncServerURL -Replace}
    Default {Write-Host "Invalid option passed: $Option"}
}

在您的具体示例中,我会将提示设置等的所有逻辑转化为一个函数,该函数根据传递给它的参数选择执行路径。你可以

代码语言:javascript
复制
Param(
    [ValidateScript({$_ -match '^(u|r)'})]
    [String]$Option=(Read-Host -Prompt 'Would you like to (r)emove or (u)pdate a target msds-SyncServerUrl?'
)

Switch -Regex ($Option)
{
    '^r' { <# Logic #> }
    '^u' { <# Logic #> }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46121939

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档