【问题标题】:Powershell Script Switch parametersPowershell 脚本切换参数
【发布时间】:2021-11-06 11:28:44
【问题描述】:

我正在尝试创建一个脚本,该脚本使用对象 ID 和应用程序 ID(用于应用程序和服务主体)来定位用户、组、应用程序或服务主体。我希望脚本能够在有或没有开关参数的情况下运行。我希望它能够搜索全部或特定搜索位置。例如:

搜索全部:./test.ps1 -ObjectId "xxxx-xxxx-xxxx-xxxxxx"

仅限用户和组:./test.ps1 -ObjectId "xxxx-xxxx-xxxx-xxxxxx" -User -Group

仅限应用程序:./test.ps1 -ObjectId "xxxx-xxxx-xxxx-xxxxxx" -App

如果有人可以检查我的工作并提供反馈和/或建议,我们将不胜感激!谢谢!

[CmdletBinding(DefaultParameterSetName='SearchAll')]
param(
    [Parameter(Mandatory=$true)]
    [ValidatePattern("^[a-z_0-9]{8}[-][a-z_0-9]{4}[-][a-z_0-9]{4}[-][a-z_0-9]{4}[-][a-z_0-9]{12}")]
    $objectID,
    
    [Parameter(ParameterSetName = 'Switches')]
    [switch]$User,
    [Parameter(ParameterSetName = 'Switches')]
    [switch]$Group,
    [Parameter(ParameterSetName = 'Switches')]
    [switch]$sp,
    [Parameter(ParameterSetName = 'Switches')]
    [switch]$App
)

if($PSCmdlet.ParameterSetName -eq 'Switches')
{
    if ($user.IsPresent) {
        Get-AzADUser -ObjectId $objectID | Select-Object Mail, DisplayName
        $found = $true }
    
    if ($group.IsPresent) {
        Get-AzADGroup -ObjectId $objectID | Select-Object DisplayName, Description, Id
        $found = $true }
   
    if ($app.IsPresent) { 
        Get-AzADApplication -ObjectId $objectID | Select-Object ObjectType, DisplayName, Id, Type, ApplicationId
        Get-AzADApplication -ApplicationId $objectID | Select-Object ObjectType, DisplayName, Id, Type, ApplicationId
        $found = $true }
   
    if ($sp.IsPresent) { 
        Get-AzADServicePrincipal -ObjectId $objectID | Select-Object ObjectType, DisplayName, Id, Type, ApplicationId
        Get-AzADServicePrincipal -ApplicationId $objectID | Select-Object ObjectType, DisplayName, Id, Type, ApplicationId
        $found = $true }
    if (-not $found) { Write-Warning "Not found." }
}

else{
    $user = Get-AzADUser -ObjectId $objectID
    if ($user)
    {
        $user | Format-List Mail, DisplayName
    }
    else
    {
        $group = Get-AzADGroup -ObjectId $objectID
        if ($group)
        {
            $group | Format-List DisplayName, Description, Id
        }
        else
        {
            $appO = Get-AzADApplication -ObjectId $objectID
            if ($appO)
            {
                Write-Host "ObjectID"
                $appO | Format-List ObjectType, DisplayName, Id, Type, ApplicationId
            }
            else
            {
                $appA = Get-AzADApplication -ApplicationId $objectID
                if ($appA)
                {
                    Write-Host "Application ID"
                    $appA | Format-List ObjectType, DisplayName, Id, Type, ApplicationId
                }
                else
                {
                    $spO = Get-AzADServicePrincipal -ObjectId $objectID
                    if ($spO)
                    {
                        $spO | Format-List ObjectType, DisplayName, Id, Type, ApplicationId
                    }
                    else
                    {
                        $spA = Get-AzADServicePrincipal -ApplicationId $objectID
                        if ($spA)
                        {
                            $spA | Format-List ObjectType, DisplayName, Id, Type, ApplicationId
                        }
                        else
                        {
                            Write-Warning "Object does not exist."
                        }
                    }
                }
            }
        }
    }
}

还有,

if (-not $found) { Write-Warning "Not found." }

行似乎不起作用。有什么建议吗?

【问题讨论】:

  • 我提出了回复$found。我为您的问题的代码审查留下了一些指示。但我认为还有另一个代码审查论坛。让我知道,因为我想从答案中剔除一些绒毛。
  • @Steven 在发布到 CR 之前,OP 需要让代码正常工作(即包括似乎不起作用的行)——否则它不会是 on-topic
  • @SᴀᴍOnᴇᴌᴀ 谢谢。我们会看看这是怎么回事。我只是想确保答案最终得到清理。假设它是值得的。

标签: azure powershell scripting powershell-core


【解决方案1】:

看起来你将$found设置为$true,不管结果如何 Get-AzADUser 或任何其他命令。由于您在每个 if/else 脚本块中都这样做,因此像 -not $found 这样的表达式将始终返回 false,因此永远不会写入警告。

简单的解决方案是将返回/找到的对象分配给一个变量,然后测试是否填充了该变量以设置$found。然后像以前一样输出变量:

if ( $user ) {
    $AzADUser = Get-AzADUser -ObjectId $objectID
    If( $AzADUser ) { $found = $true }
    $AzADUser | Select-Object Mail, DisplayName
}

if ( $group ) {
    $AzADGroup = Get-AzADGroup -ObjectId $objectID    
    If( $AzADGroup ) { $found = $true }
    $AzADGroup | Select-Object DisplayName, Description, Id
}

if ( $app ) { 
    $AzADApplication =  @(Get-AzADApplication -ObjectId $objectID)
    $AzADApplication += Get-AzADApplication -ApplicationId $objectID
    If( $AzADApplication ) { $found = $true }
    $AzADApplication| Select-Object ObjectType, DisplayName, Id, Type, ApplicationId    
}

if ( $sp ) { 
    $AzADServicePrincipal =  @(Get-AzADServicePrincipal -ObjectId $objectID)
    $AzADServicePrincipal += Get-AzADServicePrincipal -ApplicationId $objectID
    If( $AzADServicePrincipal ) { $found = $true }
    $AzADServicePrincipal | Select-Object ObjectType, DisplayName, Id, Type, ApplicationId
}

if (-not $found) { Write-Warning "Not found." }

注意:您不需要引用.IsPresent

显然,您可以对不同的开关参数重复此操作。

但是,这有点罗嗦,因为您使用同一个变量来表示可能返回的几种不同类型的对象。此外,您将根据对象类型返回不同的属性。

您可以使用 Switch 语句来改善这一点:

Switch ([Boolean]$true) {
    $user {
        Get-AzADUser -ObjectId $objectID | Select-Object Mail, DisplayName
    }
    $group {
        Get-AzADGroup -ObjectId $objectID | Select-Object DisplayName, Description, Id        
    }
    $app {
        Get-AzADApplication -ObjectId $objectID | Select-Object ObjectType, DisplayName, Id, Type, ApplicationId
        Get-AzADApplication -ApplicationId $objectID | Select-Object ObjectType, DisplayName, Id, Type, ApplicationId
    }
    $sp {
        Get-AzADServicePrincipal -ObjectId $objectID | Select-Object ObjectType, DisplayName, Id, Type, ApplicationId
        Get-AzADServicePrincipal -ApplicationId $objectID | Select-Object ObjectType, DisplayName, Id, Type, ApplicationId
    }
    Default {
        Write-Warning "Not found."
    }
}

一个优点是任何匹配的脚本块都会执行,除了默认的,只有在没有其他块执行时才会运行。在这种情况下,您不需要重复的 If 语句或 $found

即使使用Switch 的更简洁的版本,代码仍然相当重复。我认为有一种更通用的方法可以查询您最初可能不知道的类型的对象。如果这是一个本地 AD 实现,我将使用 Get-ADObject 然后根据它返回的对象类型以不同的方式输出。这将完全消除对开关参数的需求。也许您可以使用Azure Active Directory PowerShell module 中的Get-AzureADObjectById 来采用类似的策略

【讨论】:

  • 谢谢你,史蒂文!如果我使用您提供的内容,是每个参数的 if 语句分开,还是嵌套 if 语句?
  • 您可以像以前一样安排单独的 If 块来查找每个开关参数。我更新了示例以包含所有 If 语句。但是,我还添加了一个基于 switch 的示例并改进了替代方法建议。无论如何,如果您对解决方案感到满意,请考虑接受答案。这样做将有助于其他人找到并参考我们的工作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-08-20
  • 1970-01-01
  • 2021-05-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多