If/else 在 Foreach 中.. 否则将被忽略

If/else inside Foreach.. Else is ignored

所以我的脚本中有一对 Foreach 循环。这些功能包含必要的

[Parameter(Mandatory=$false)]
    [Switch]$Logonly 

件,但我认为我的循环使用错误的语法来捕获该开关值..

Foreach ($i in $is) {
    if (-not $Logonly){
        $time = (Get-Date).ToString('T')
        New-func1
        Get-func2
        Set-func3
        Log-Write -LogPath $sLogFile -LineValue "========================[ $time ]==============================="
} else {
    #Foreach ($Manager in $Managers){
        New-func1_logonly
        Get-func2
        Set-func3_logonly
        Log-Write -LogPath $sLogFile -LineValue "========================[ LogOnly ]==============================="
    }
  }
#}


Foreach ($Report in $ReportsTo) {
    If (-not $Logonly){
    Remove-func4
    write-host "first remove hit"
} else {
    #ForEach ($Report in $ReportsTo) {
    Remove-func5_logonly
    write-host "Second remove hit"
    }
   }
#}

所以我的理解是,因为我的 3 个函数有前面提到的 [Parameter 行,所以我可以用 -Logonly 调用我的脚本,这应该足以被 else 捕获循环的一部分。我这里做错了什么?

当前完整代码:

#---------------------------------------------------------[Initializations]-------------------------------------------------------- 
 
#  Dot Source required Function Libraries
#. "\server\e$\scripts\Logging_Functions.ps1" 
. "c:\users\documents\powershell\Functions\Logging_Functions.ps1"

#  Error Action
$ErrorActionPreference = 'silentlycontinue'
#  Debug preference
$global:DebugPreference = "continue"
#  WhatIf Preference, uncomment to run script in a logging only function
#$WhatIfPreference = $true

#----------------------------------------------------------[Declarations]----------------------------------------------------------
  
#  Script Version
$sScriptVersion = "1.0"

Import-Module ActiveDirectory


#  Log File Info
$sLogPath = "C:\Users\Documents\powershell\Logs"
#$sLogPath = "\server\e$\Logs"
$sLogName = "Set-LitmosGroups_$(get-date -f yyyy-MM-dd_HH-mm-ss).log"
$LogOnlyName = "C:\Users\Documents\powershell\Logs\Set-LitmosGroups (Log Only).log"
$sLogFile = Join-Path -Path $sLogPath -ChildPath $sLogName
$LogLine = $null 

#$logonly = $null

#  Variable Initializations
#  Org Unit where the target groups reside (Litmos)
$OU = "ou=test_litmos, ou=test accounts, dc=domain, dc=net"
#  Org unt containing the All Managers security group
$OU2 = "CN=All Managers,OU=Organizational,OU=Groups,DC=domain,DC=net"

#  Get member of the 'ALL Managers' security group
$Managers = Get-ADGroupMember -identity $OU2 | Select-Object -expandproperty samaccountname

#  Get AD groups with Report to in the name in $ou
$ReportsTo = Get-adgroup -searchbase $ou -filter "Name -like 'Report to *'" |  
Select-Object -expandproperty name

$samecount = 0
$addcount = 0

Param (
[Parameter(Mandatory=$false)]
[Switch]$LogOnly
)

#----------------------------------------------------------[Functions]-------------------------------------------------------------


Function Get-DirectReport {
    [CmdletBinding()]
    param(
        [Parameter(
            Mandatory = $false,
            ValueFromPipeline = $true,
            ValueFromPipelineByPropertyName = $true
        )]
 
        [string]  $SamAccountName,
 
        [switch]  $NoRecurse
    )
 
    BEGIN {}
 
    PROCESS {
        $UserAccount = Get-ADUser $SamAccountName -Properties DirectReports, DisplayName
        $UserAccount | select -ExpandProperty DirectReports | ForEach-Object {
            $User = Get-ADUser $_ -Properties DirectReports, DisplayName, Title, EmployeeID
            if ($null -ne $User.EmployeeID) {
                if (-not $NoRecurse) {
                    Get-DirectReport $User.SamAccountName
                }
                [PSCustomObject]@{
                    SamAccountName    = $User.SamAccountName
                    UserPrincipalName = $User.UserPrincipalName
                    DisplayName       = $User.DisplayName
                    Manager           = $UserAccount.DisplayName
                }
            }
        }
    }
 
    END {}
 
}

Function New-bhReportToGroup {
    [CmdletBinding(SupportsShouldProcess)] 
    $Log1 = "New group for " + $manager + " has been created."
    $Log2 = "Group for " + $manager + " already exists."
    #From on when you see the below line $script:<variable> that sets the scope for that variable to the entire script which means other functions can use the value
    $script:ReportsTo = $ReportsTo -replace ("Report to ", "")

    if ($manager -notin $ReportsTo) { 
        new-adgroup -name "Report to $manager" -groupscope global -path $ou
        $script:addcount = $addcount +1
        $LogLine = $Log1
        Log-Write -LogPath $sLogFile -LineValue $LogLine 
    }
    else {
        $script:samecount = $samecount + 1
        $LogLine = $Log2
        Log-Write -LogPath $sLogFile -LineValue $LogLine 
    }
}

Function New-bhReportToGroup_logonly {
    #[CmdletBinding(SupportsShouldProcess)]
    $Log1 = "New group for " + $manager + " would have been created in $OU."
    $Log2 = "Group for " + $manager + " already exists in $OU."
    $script:ReportsTo = $ReportsTo -replace ("Report to ", "")

    if ($manager -notin $ReportsTo) { 
        $Script:addcount = $addcount +1
        $LogLine = $Log1
        Log-Write -LogPath $LogOnlyName -LineValue $LogLine 
    }


    else {
        $Script:samecount = $samecount + 1
        $LogLine = $Log2
        Log-Write -LogPath $LogOnlyName -LineValue $LogLine 
    }
}

Function Get-bhDReports {
    [CmdletBinding(SupportsShouldProcess)] 
    $script:directreports = Get-Directreport $manager -norecurse  | Select-Object samAccountName
    if ($null -ne $directreports) {        
        $LogLine = "Gathering direct reports for " + $manager
        Log-Write -LogPath $sLogFile -LineValue $LogLine 
    }
    else {
        $LogLine = $manager + " has no reports."
        Log-Write -LogPath $sLogFile -LineValue $LogLine 
    }   
}

Function Set-bhRTGmembers {
    [CmdletBinding(SupportsShouldProcess)] 
    #  Get manager's 'report to <manager>' group again to update members
    $managerReportToGroup = Get-ADGroup -SearchBase $OU -Filter "Name -like 'Report to $Manager'"
    if ($managerReportToGroup) {
        Add-ADGroupMember -identity $managerReportToGroup.Name -members $DirectReports
        Add-ADGroupMember -identity $managerReportToGroup.name -members $Manager
        $LogLine = "Report to " + $Manager + " updated."
        Log-Write -LogPath $sLogFile -LineValue $LogLine 
    }
    else {
        $LogLine = "Could not find group for " + $Manager
        Log-Write -LogPath $sLogFile -LineValue $LogLine 
    }
}

Function Set-bhRTGmembers_logonly {
    #[CmdletBinding(SupportsShouldProcess)] 
    #  Get manager's 'report to <manager>' group again to update members
    $managerReportToGroup = Get-ADGroup -SearchBase $OU -Filter "Name -like 'Report to $Manager'"
    if ($managerReportToGroup) {
        $LogLine = "Report to " + $Manager + " would be updated with $DirectReports."
        Log-Write -LogPath $LogOnlyName -LineValue $LogLine 
    }
    else {
        $LogLine = "Could not find group for " + $Manager
        Log-Write -LogPath $LogOnlyName -LineValue $LogLine 
    }
}

Function Remove-bhOOSGroups {
    [CmdletBinding(SupportsShouldProcess)] 
    $report = $report -replace ("Report to ", "")
    if ($Report -notin $managers) {
        Remove-ADGroup -Identity "Report to $Report" -confirm:$false
        $LogLine = $report + " user has fell out of scope, Report group removed."
        Log-Write -LogPath $sLogFile -LineValue $LogLine
    }
    else {
       Continue
    }
}

Function Remove-bhOOSGroups_logonly {
    #[CmdletBinding(SupportsShouldProcess)] 
    $report = $report -replace ("Report to ", "")
    if ($Report -notin $managers) {
        $LogLine = $report + " user has fell out of scope, Report group would be removed."
        Log-Write -LogPath $sLogFile -LineValue $LogLine
    }
    else {
       Continue
    }
}

#----------------------------------------------[ Execution ]------------------------------------------------



Foreach ($Manager in $Managers) {
    if (-not $LogOnly) {
    $time = (Get-Date).ToString('T')
        write-host $Logonly
        New-bhReportToGroup
        Get-bhDReports
        Set-bhRTGmembers
        Log-Write -LogPath $sLogFile -LineValue "========================[ $time ]==============================="
 } else {
      write-host $logonly
        New-bhReportToGroup_logonly
        Get-bhDReports
        Set-bhRTGmembers_logonly
        Log-Write -LogPath $LogOnlyName -LineValue "========================[ LogOnly ]==============================="  
    }
  }
Foreach ($Report in $ReportsTo) {
    If (-not $LogOnly){
    Remove-bhOOSGroups
} else {
    #ForEach ($Report in $ReportsTo) {
    Remove-bhOOSGroups_logonly
        }
   }
#}

您需要将 $LogOnly 声明为 脚本的参数 - 这样您就可以 forward it 您定义的函数 当你执行它们时:

param(
  [Parameter(Mandatory=$false)]
  [switch]$LogOnly
)

function New-Thing {
  param(
    [Parameter(Mandatory=$false)]
    [switch]$LogOnly
  )

  if(-not $LogOnly) {
    return "Thing"
  }
  else {
    Write-Host "Here I would have returned thing!"
  }
}

# Splatting $PSBoundParameters 
New-Thing @PSBoundParameters

如您所见,不再需要 if/else 语句 - 我们只需将传递给脚本的任何参数参数传递给函数。


如果展开 $PSBoundParameters 是不可取的(如果您有不同的参数转发给不同的函数可能会出现这种情况),您也可以 use $PSDefaultParameterValues 让您的函数接受参数参数,像这样:

param(
  [Parameter(Mandatory=$false)]
  [switch]$LogOnly,

  [Parameter(Mandatory=$false)]
  [string]$AnotherParameter
)

# Set default param values for your custom functions
$PSDefaultParameterValues['New-Thing:LogOnly'] = $LogOnly
$PSDefaultParameterValues['Get-AnotherThing:UnrelatedParameter'] = $AnotherParameter

function New-Thing {
  param(
    [Parameter(Mandatory=$false)]
    [switch]$LogOnly
  )

  # ...
}

function Get-AnotherThing {
  param(
    [Parameter(Mandatory=$false)]
    [switch]$UnrelatedParameter
  )

  # ...
}

# No need to explicitly pass arguments to the functions anymore
# PowerShell will do it for us
New-Thing
Get-AnotherThing

如果硬要维护两套功能,就这么简单:

param(
  [Parameter(Mandatory=$false)]
  [switch]$LogOnly
)

foreach($Round in 1..5){
  if(-not $LogOnly){
    Write-Host "Round $Round!"
    # Call Function1 here

  }
  else{
    Write-Host "Round $Round, LogOnly!"
    # Call Function1_LogOnly here
  }
}

在 PS 中检查 [switch] 是否用作参数(此示例使用 [switch]$LogOnly):

if($LogOnly.IsPresent)
{
   #Do Something
}
else
{
   #Do Something else
}

编辑:不确定你做错了什么,可能是你调用脚本的方式,也可能是因为你使用 ISE 时没有在 运行 脚本之前清除参数变量。 Switch 本身在函数中或函数外的参数块中工作正常:

PS C:\> cat $home\documents\test.ps1
param(
    [string]$Test,
    [switch]$TestSwitch
)

if($TestSwitch.IsPresent)
{
    return "Hello $Test, switch is present."
}
else
{
    return "Hello $Test, switch is not present."
}
PS C:\> . $home\documents\test.ps1 -Test World -TestSwitch
Hello World, switch is present.
PS C:\> . $home\documents\test.ps1 -Test World
Hello World, switch is not present.
PS C:\>