Script For NetBackup, Global Variable Problems

Hello all ^^,

I’m scripting something for change the scedule of a NetBackup Policy.

I’m using a windows 2016 server with Netbackup v 8.1.1

My problem is than 2 Global Variable seems to loose the value when the script change of function.

The variables is $Global:PolicyName and $Global:StopTime.

They take teir value in the GetInfoSched Function, and when i leave this function the variable is $null.

#Déclaration des path utilisés
$PathConfig = "C:\Admin\ConfigPolicies"
$PathNBUcmd = "C:\Program Files\Veritas\NetBackup\bin"
$PathNBUadmincmd = "C:\Program Files\Veritas\NetBackup\bin\admincmd"
$PathResult = "c:\Admin\Result"

#Déclaration des Variables Globales
$Global:Startime = $null
$Global:StopTime = $null
$Global:ChoixMenu = $null
$Global:Boucle = $null
$Global:ScheduleLabel = $null
$Global:ChoixSched = $null
$Global:PolicyName 
$Global:Jour = $null

Set-Location $PathNBUadmincmd
#Faire un Backup de la configuration des schedules de ttes les policies
#Menu des Opérations disponibles



Function Menu(){
    Write-Host "Opération disponible :"
    Write-Host "1. Changer le jour et heure d'un Schedule d'une Policy"
    Write-Host "2. Remettre les schedules a l'origine"
    $Global:ChoixMenu = Read-Host "Selectioner l'operation souhaité"
}

$Var = "PolicyName"
Function GetInfosSch(){
    T("Entrer GetInfoSch", "PolicyName", $PolicyName)
    $CritereSelection = Read-Host "Donner votre critere de sélection"
    $ListPN = .\bppllist.exe -allpolicies -U | Find /I "Policy Name"
    ForEach($Policy in $ListPN){
        $PolicyName = ($Policy.split(":")[1]).replace(" ","") | Where{$_ -like "*$CritereSelection*"} 
    }
    #$Start = Read-Host "Date et Heure de début de sauvegarde, ex: mm/jj/YYYY 10:30"
    #$Stop = Read-Host "Date et Heure de fin, ex: mm/jj/YYYY 11:30"
    $Start = "02/04/2020 16:00"
    $Stop = "02/04/2020 16:30"
    $Jour = (Get-Date -Date $Start.split(" ")[0] -UFormat "%A").Replace(" ","")
    $StartTime = New-TimeSpan -Start ($Start.Split(" ")[0]) -End $Start 
    $StartTime = $StartTime.TotalSeconds
    $tdiff = New-TimeSpan -Start $Start -End $Stop
    $StopTime = $tdiff.TotalSeconds

    #Recuperation des informations des schedules de la Policy
    $Schedules = .\bpplsched.exe RGS_MGMT_P -U | Where{$_ -like "*Schedule*"}

    #Choix et Récuperation des PolicyName et ScheduleLabel 
    $Sched1 = ($Schedules[0].split(":")[1]).replace(" ","")
    $Sched2 = ($Schedules[1].split(":")[1]).replace(" ","")
    Write-Host "1. $Sched1"
    Write-Host "2. $Sched2"
    $ChoixSched = Read-Host "Sélectionner le schedule a modifier" 
    Switch($ChoixSched){
        1{$Global:ScheduleLabel = $Sched1}
        2{$Global:ScheduleLabel = $Sched2}
    }
    Write-Host "#============================================================================# "
    Write-Host "Récapitulations des informations avant modifications des Schedules:" 
    Write-Host "Critere de sélection: $CritereSelection"
    Write-Host "PolicyName: $PolicyName"
    Write-Host "Schedule Label: $ScheduleLabel"
    Write-Host "Jour: $Jour"
    Write-Host "Date et Heure start backup: $Start"
    Write-Host "Date et Heure stop backup: $Stop"
    Write-Host "StartTime en seconde: $StartTime"
    Write-Host "StopTime en seconde: $StopTime"
    $Global:Boucle = Read-Host "Si tout est ok, Yes ou Non"
    T("Sortie GetInfoSch","PolicyName",$PolicyName)
}

#A revoir !
Function BackupSched(){
    T("Entrée Backup","PolicyName",$PolicyName)
    Set-Location $PathNBUadmincmd
    Write-Host "Passe dans la fonction BackupSched"
    $ListPN = .\bppllist.exe -allpolicies -U | Find /I "Policy Name" 
    Write-Host "$ListPN"
    $Date = Get-Date -UFormat "-%d-%m-%Y"
    $TP = Test-Path -Path "$PathConfig\AllPolicies.txt"
    If($TP -eq "*True*"){Remove-Item "$PathConfig\AllPolicies.txt"}
    ForEach($Policy in $ListPN){
        $Policy = ($Policy.split(":")[1]).replace(" ","") 
        Write-Host "Policy: $policy"
        $PolicyList = $Policy | Out-File "$PathConfig\AllPolicies.txt" -Append
        .\bpplsched.exe $Policy -l | Out-File "$PathConfig\Config-$Policy$Date.txt"
    }
    Write-Host "Policy: $Policy"
    Write-Host "Fin de la fonction Backup"
    T("Sortie Backup","PolicyName",$PolicyName)
}


# A Verifier !!!
Function ModificationSched(){
    T("Entrée ModifSched","PolicyName",$PolicyName)
    Write-Host "Début de la fonction Modification"
    Write-Host "PolicyName: $Global:PolicyName"
    Write-Host "ScheduleLabel: $ScheduleLabel"
    Write-Host "StartTime: $StartTime"
    Write-Host "StopTime: $StopTime"
    Switch($Jour){
        Dimanche{.\bpplschedwin $PolicyName $Global:SheduleLabel -0 $StartTime $StopTime -1 0 0 -2 0 0 -3 0 0 -4 0 0 -5 0 0 -6 0 0}
        Lundi{.\bpplschedwin $PolicyName $Global:SheduleLabel -0 0 0 -1 $StartTime $StopTime -2 0 0 -3 0 0 -4 0 0 -5 0 0 -6 0 0}
        Mardi{.\bpplschedwin $PolicyName $Global:SheduleLabel -0 0 0 -1 0 0 -2 $StartTime $StopTime -3 0 0 -4 0 0 -5 0 0 -6 0 0}
        Mercredi{.\bpplschedwin $PolicyName $Global:SheduleLabel -0 0 0 -1 0 0 -2 0 0 -3 $StartTime $StopTime -4 0 0 -5 0 0 -6 0 0}
        Jeudi{.\bpplschedwin $PolicyName $Global:SheduleLabel -0 0 0 -1 0 0 -2 0 0 -3 0 0 -4 $StartTime $StopTime -5 0 0 -6 0 0}
        Vendredi{.\bpplschedwin $PolicyName $Global:SheduleLabel -0 0 0 -1 0 0 -2 0 0 -3 0 0 -4 0 0 -5 $StartTime $StopTime -6 0 0}
        Samedi{.\bpplschedwin $PolicyName $Global:SheduleLabel -0 0 0 -1 0 0 -2 0 0 -3 0 0 -4 0 0 -5 0 0 -6 $StartTime $StopTime}
    }
    Write-Host "Modification éffectué"
    T("Sortie ModifSched","PolicyName",$PolicyName)
}


Function RollBack(){
    $PolicyList = Get-Content "$PathConfig\AllPolicies.txt"
    ForEach($Policy in $PolicyList){
        $ConfigRef = Get-Content "$PathConfig\Config-$Policy*.txt"
        $ConfigDiff = .\bpplsched.exe $Policy -l
        $PolicyName = $Policy
        If(Compare-Object -ReferenceObject $ConfigRef -DifferenceObject $ConfigDiff){
            Write-Host "Les fichiers sont Differents"
            $Diff = Compare-Object -ReferenceObject $ConfigRef -DifferenceObject $ConfigDiff   
            $DiffCsv = $Diff | Export-Csv "$PathConfig\config.csv" -Delimiter ","
            $Diff = Import-Csv "$PathConfig\config.csv" -Delimiter ","
            $Conf =  $Diff[1].InputObject 
            $i=0
            $TabVal = @()
            $TabPos = @()
            While($i -le 14){
                If($Diff.split(" ")[$i] -notlike "0"){
                    $Val = $Diff.split(" ")[$i]
                    $TabVal += $Val
                    $TabPos += $i
                }
                $i++
            }
            #Rechercher le schedule Label qui a été modifié
        Switch($TabPos[1]){
            1{.\bpplschedwin $PolicyName $Global:SheduleLabel -0 $StartTime $StopTime -1 0 0 -2 0 0 -3 0 0 -4 0 0 -5 0 0 -6 0 0}
            3{.\bpplschedwin $PolicyName $Global:SheduleLabel -0 0 0 -1 $StartTime $StopTime -2 0 0 -3 0 0 -4 0 0 -5 0 0 -6 0 0}
            5{.\bpplschedwin $PolicyName $Global:SheduleLabel -0 0 0 -1 0 0 -2 $StartTime $StopTime -3 0 0 -4 0 0 -5 0 0 -6 0 0}
            7{.\bpplschedwin $PolicyName $Global:SheduleLabel -0 0 0 -1 0 0 -2 0 0 -3 $StartTime $StopTime -4 0 0 -5 0 0 -6 0 0}
            9{.\bpplschedwin $PolicyName $Global:SheduleLabel -0 0 0 -1 0 0 -2 0 0 -3 0 0 -4 $StartTime $StopTime -5 0 0 -6 0 0}
           11{.\bpplschedwin $PolicyName $Global:SheduleLabel -0 0 0 -1 0 0 -2 0 0 -3 0 0 -4 0 0 -5 $StartTime $StopTime -6 0 0}
           13{.\bpplschedwin $PolicyName $Global:SheduleLabel -0 0 0 -1 0 0 -2 0 0 -3 0 0 -4 0 0 -5 0 0 -6 $StartTime $StopTime}
        }

        }
        Else{
            Write-Host "Les fichiers sont identiques"
        }
    }
}



Function T([string]$orig, [string]$var, [string]$val){
    Write-Host "#####################################################"
    Write-Host "Oigine: $Orig"
    Write-Host "Entrer dans la fonction T"
    Write-Host "$var : $val"
    Write-Host "PolicyName: $Global:PolicyName"
    Write-Host "ScheduleLabel: $ScheduleLabel"
    Write-Host "StartTime: $StartTime"
    Write-Host "StopTime: $StopTime"
    Write-Host "#####################################################"
}


###############Deroulement du Script##################
do{
    Menu
    GetInfosSch
}
Until($Global:Boucle -like "*Yes*")
if ($Global:ChoixMenu -eq 1){
    BackupSched
    ModificationSched
}
Else {
    RollBack
}


Set-Location "C:\Admin"

Thx for help.

First, using Global Variables is almost always a bad practice. Powershell is designed to pass data in a pipeline, but you should be passing data to the function and producing a object as output (if necessary). Look at the example below how a function passes data to a function, no global variables in the function. Even if I create a global variable (e.g. Color), it is passed to the function, not a global variable:

Function Menu {
    [CmdletBinding()]
    param (
        $Color='Green'
    )
    Write-Host "Opération disponible :" -ForegroundColor $Color
    Write-Host "1. Changer le jour et heure d'un Schedule d'une Policy" -ForegroundColor $Color
    Write-Host "2. Remettre les schedules a l'origine" -ForegroundColor $Color
    $Choix = Read-Host "Selectioner l'operation souhaité"
    switch -Regex ($Choix) {
        "1|2" {
            [pscustomobject]@{
                ChoixMenu = $Choix
            }
        }
        default {
            Throw 'Must be a 1 or 2'
        }
    }
}

Function GetInfosSch {
    [CmdletBinding()]
    param (
        [Parameter(
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true
        )]
        [int]$ChoixMenu
    )

    Write-Verbose -Message ('User chose {0}' -f $ChoixMenu)

    $stopTime = switch ($ChoixMenu) {
        1 {(Get-Date).AddDays(1)}
        2 {(Get-Date).AddDays(2)}
    }

    [pscustomobject]@{
        StartTime = Get-Date
        StopTime  = $stopTime
    }

}


Function ModificationSched {
    [CmdletBinding()]
    param (
        [Parameter(
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true
        )]
        [datetime]$StartTime,
        [Parameter(
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true
        )]
        [datetime]$StopTime
    )  
   
    Write-Verbose -Message ("Setting schedule with start {0} and stop {1}" -f $StartTime, $StopTime)
}


$Color = 'Cyan'
Menu -Color $Color | GetInfosSch -Verbose | ModificationSched -Verbose

Output:

Opération disponible :
1. Changer le jour et heure d'un Schedule d'une Policy
2. Remettre les schedules a l'origine
Selectioner l'operation souhaité: 1
VERBOSE: User chose 1
VERBOSE: Setting schedule with start 4/2/2020 6:11:54 PM and stop 4/3/2020 6:11:54 PM

Opération disponible :
1. Changer le jour et heure d'un Schedule d'une Policy
2. Remettre les schedules a l'origine
Selectioner l'operation souhaité: 2
VERBOSE: User chose 2
VERBOSE: Setting schedule with start 4/2/2020 6:12:22 PM and stop 4/4/2020 6:12:22 PM

Opération disponible :
1. Changer le jour et heure d'un Schedule d'une Policy
2. Remettre les schedules a l'origine
Selectioner l'operation souhaité: 3
Must be a 1 or 2
At line:15 char:13
+             Throw 'Must be a 1 or 2'
+             ~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : OperationStopped: (Must be a 1 or 2:String) [], RuntimeException
    + FullyQualifiedErrorId : Must be a 1 or 2

Now, to answer your question about scope, creating the variable $Global:StartTime doesn’t persist if you use a variable $StartTime in your function, you have to create it as $Global:StartTime in the function or the scope is function only.

Hello Rob,

 

Thx to for your reply ^^

First i will try to understand what you explain to me and come back to you :wink:

 

I do’t understand really what you want to tell me about Create the $Global:Variable in the function or the scope is the function only …

Could you explain to me ?

 

Ok it’s good, i understand what you have said to me.

I just have to call always, my variable “$Global:PolicyName”, and not on time “$Global:PolicyName” and other “$PolicyName”.

I think remember in my course of Powershell, that when we create a Global Variable, we could call it With ou without $Global.

Ok Thx Rob :wink:

 

A function has it’s own private scope. When you are setting a variable in a function like this:

$myVar = '123'

This is setting a variable in the function scope which takes precedence over global. In your scenario, using global variables (which again is bad), you should GET and SET using the $Global container:

$Global:myvar = '123'

https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_scopes?view=powershell-7
https://adamtheautomator.com/powershell-global-variable/

Hello Robs,

 

I’m come back to you ,

I’have some problems with the Global Variable, so i have two solution do without Function or with finction but without Global Variable !

But How to pass a Variable to another fonction ? i really don’t understand…

 

Thx for help.

As parameter of the function. :wink:

You said that using the Global Variable is bad, so how to pass variable to another function without using $Global:Variable ?

As parameter of the function. :wink:

I’ve Understand how to pass a variable to the fonction where the variable is come from.

But how pass a variable of the fonction One to the function Two ?

 

I’ve try this , like Rob said :

 

Function One(){
    $ChoixMenu = 1
    [pscustomobject]@{
        ChoixMenu = $ChoixMenu
        }
    Write-Output "ChoixMenu-One: $ChoixMenu"
}

Function Two(){
    [CmdletBinding()]
    param (
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [int]$ChoixMenu
    )
    Write-Output "ChoixMenu-Two: $ChoixMenu"
}

One
Two $ChoixMenu 

But the result is not good for me :

 

PS C:\Users\Administrateur.WIN-VLGC27MQG0C> C:\Admin\TRy.ps1

ChoixMenu

    1

ChoixMenu-One: 1
ChoixMenu-Two: 0

You might stop using the same variable names to reduce the confusion. :wink:

Function One{
    $PramOne = 1
    $PramOne
}

Function Two {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)]
        [int]$ParamTwo
    )
   "ReturnValue function Two: $ParamTwo"
}

Two -ParamTwo (One)

You could also save the output of function one in a variable and pass this to function two like this:

$outputOfFunctionOne = One
Two -ParamTwo $outputOfFunctionOne 

Ah the function overwrite…Ok.
New try, i think i will be crazy soon !

Function One(){
    $ChoixMenuOne = 1
}

Function Two(){
    [CmdletBinding()]
    param (
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [int]$ChoixMenuTwo
    )
    Write-Output "ChoixMenuTwo: $ChoixMenuTwo"
}

Two -ChoixMenuTwo (One)

0, perhaps The number of my skill in powershell …

Ok, even if my try works…a day !

 

I don’t think it’s usefull for my script, i’m wrong ?

You assigned a value to the variable in your function one bit you did not output it. :wink:

So instead of

Function One(){
$ChoixMenuOne = 1
}

use this

Function One(){
    $ChoixMenuOne = 1
    $ChoixMenuOne
}

We need do output it…Hmm Ok it’s work…but i don’t really understand, my skill certainly ^^

 

Ok ok.

 

Now how can i use this method for my script…i will look that.

 

Thx again Olaf and Robs :wink:

Have a nice days, has you can :wink: