Powershell 脚本开关参数

Powershell Script Switch parameters

我正在尝试创建一个脚本,使用对象 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

如果有人能检查我的工作并提供反馈and/or建议,将不胜感激!谢谢!

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

简单的解决方案是将 returned/found 对象分配给一个变量,然后测试该变量是否已填充以设置 $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,然后根据它的对象类型 returns 输出不同的内容。这将完全消除对开关参数的需要。也许您可以使用 Azure Active Directory PowerShell module 中的 Get-AzureADObjectById 来采用类似的策略