Skeer
Skeer

Reputation: 173

If/else inside Foreach.. Else is ignored

So I've got a pair of Foreach loops in my script. The functions contain the requisite

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

pieces but I think my loops are using the wrong syntax to catch that switch value..

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"
    }
   }
#}

So the way I understand it is since 3 of my functions have the aforementioned [Parameter line then I can call my script with a -Logonly and that should be enough to be caught by the else parts of the loops. What did I do wrong here?

Current code in it's entirety:

#---------------------------------------------------------[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
        }
   }
#}

Upvotes: 0

Views: 412

Answers (2)

Santiago Squarzon
Santiago Squarzon

Reputation: 60518

In PS to check if [switch] was used as parameter (using [switch]$LogOnly for this example):

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

Edit: Not sure what you're doing wrong, maybe the way you're calling your script or maybe because you're using ISE without clearing the param variables before running the script. Switch itself works fine in a param block in or out a function:

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:\>

Upvotes: 1

Mathias R. Jessen
Mathias R. Jessen

Reputation: 174690

You'll want to declare $LogOnly as a parameter of the script - so that you can forward it to the functions you define when you execute them:

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

As you can see, the if/else statements are no longer required - we just pass whatever parameter arguments was passed to the script along to the function.


If splatting $PSBoundParameters is undesirable (this might be the case if you have different parameters to forward to different functions), you can also use $PSDefaultParameterValues to make your functions take on the parameter arguments, like this:

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

If you insist on maintaining two sets of functions, it's as simple as:

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
  }
}

Upvotes: 2

Related Questions