Passing a PowerShell variable as a cmdlet parameter
我正在学习PowerShell为我的团队编写工具。我今天很忙,但是可以通过删除ForEach循环中的IF语句来简化它,因为命令之间的唯一区别是参数-replace或-remove。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | 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 =" replace"}排列:
1 2 3 4 5 | Switch($action) { R {'remove'} U {'replace'} } |
我还在ForEach循环中尝试了Invoke-Expression:
1 2 | $CMD="Set-ADObject -identity $userToBeFixed -$action @{`"msDS-SyncServerUrl`" = $TargetSSU}" Invoke-Expression -Command $CMD |
Set-ADObject cmdlet总是会失败,通常会抱怨Set-ADObject无法找到接受参数的位置参数,如" -remove"," System.Object []"或" System.Collections.Hashtable" 。
我将问题隔离到Set-ADObject,而不喜欢$ action变量用作参数。如果我将-$ action替换为-replace或-remove,则它将起作用(如上述代码段所示)。
我意识到这是一个小问题,但是似乎没有理由让我拥有这样的冗余代码感到困扰。我很想学习如何解决此问题。
另外,无关的,我还没有真正找到一种更好的方法来做到这一点:
1 | Until (($Action -eq"R") -or ($Action -eq"U")) |
我已经搜索并尝试了其他解决方案,例如:
1 | Until ($Action -eq @{"R" -or"U"}) |
但似乎无法合并对多个条件的评估。这使我感到困扰,但没有我在这里遇到的主要问题那么严重。
请对我放松。我对这件事一无所知。如果有人看到其他问题,我可以改善,请告诉我。我想学习这个。
谢谢。
您可以通过喷溅解决此问题。
例如:
1 2 3 | $action = 'Recurse' $params = @{ $action = $true } Get-ChildItem @params |
该示例在功能上等同于
Persistent13的有用答案显示了如何使用散列通过哈希表动态传递参数。
至:
Also, unrelated, I haven't really found a better way to do this:
1 Until (($Action -eq"R") -or ($Action -eq"U"))
PowerShell提供了数组包含运算符:
1 2 3 4 5 | # PSv3+ $Action -in 'R', 'U' # Equivalent, PSv1+ 'R', 'U' -contains $Action |
两种形式都将标量操作数与数组操作数的每个元素进行比较(使用
另一种选择是将
1 | $Action -match '^(R|U)$' |
Persistent13对如何使用散列需要哈希表的参数的解释就可以解决问题。
mklement0的简化比较解决方案有助于清除那部分代码。
我喜欢将所有不涉及脚本逻辑(即函数)的内容移至与主PowerShell脚本不同的文件中。我的大多数脚本都遵循以下结构:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | #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"} } |
在您的特定示例中,我会将提示设置等的所有逻辑带入一个函数,该函数根据传递给它的参数来选择执行路径。你可以做
1 2 3 4 5 6 7 8 9 10 | 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 #> } } |