so I have some code that uses the parameter -secondsremaining in write-progress to estimate time remaining in a loop.
However, I hate writing all of this out every foreach loop - and shouldn't have to, makes the code look convoluted, etc. So i'm trying to put all of the UX friendly code into it's own function. Obviously the scoping gets weird, so I have to call out everything as global, and then reset everything once the loop ends so the variables are clean for the next loop I use the function for.
Behold - the function.
function set-progressparams {
[cmdletbinding()]
PARAM (
[parameter(Mandatory=$true,
Position=0,
ValueFromPipeline=$true)]
$iterationVariable,
[parameter(Mandatory=$true,
Position=1,
ValueFromPipeline=$true)]
[array]$pp_arr
)
if (! $global:secondsRemaining) {
[nullable[double]]$global:secondsRemaining = $null
}
if (! $global:start) {
$global:start = get-date;
}
else {
continue
}
if (! $global:Pi) {
$global:Pi = 1
}
else {
$global:Pi++
}
$global:progressParameters = @{
Activity = "Processing"
Status = 'Processing'
CurrentOperation = "Doing something with $iterationVariable"
PercentComplete = (($global:Pi / $pp_arr.count) *100)
}
if ($global:secondsRemaining) {
$global:progressParameters.SecondsRemaining = $global:secondsRemaining
}
if ($global:secondsElapsed) {
$global:progressParameters.activity = "[$($global:pi)/$($pp_arr.Count)] $($global:secondsElapsed.ToString('hh\:mm\:ss'))"
}
$global:secondsElapsed = (Get-Date) – $global:start
$global:secondsRemaining = ($global:secondsElapsed.TotalSeconds / $global:pi) * ($pp_arr.Count – $global:pi)
# END OF LOOP - RESET ALL VARIABLES #
if ($global:pi -eq $global:pp_arr.Count) {
$global:pi = $null;
$pp_arr = $null;
$iterationVariable = $null;
$global:secondsRemaining = $null;
$global:start = $null;
$global:progressParameters = $null;
$global:secondsElapsed = $null;
}
}
so the parameters are PP_arr: (progressparam array i'm iterating through in the foreach) & Iterationvariable (the iteration variable created in the foreach loop. )
the foreach loop looks VERY clean now - but uhh... this doesn't work. when I call this in the loop - it breaks the loop. No error given. No information. Just stops it cold.
Behold - the loop
$z_arr = @()
foreach ($item in $zvms) {
$vmname = $item.vmname;
$vmid = $item.vmidentifier;
$vpgid = $item.vpgidentifier;
$vpgname = $item.vpgname;
set-progressparams $item $zvms;
write-progress @progressparameters;
$vol_arr = $zvol | ?{$_.protectedvm.identifier -eq $vmid} | select @{n='datastore';e={$_.datastore.name}},@{n='VMDK';e={$_.path.filename}}, @{n='VolumeIdentifier';e={$_.volumeidentifier}}
$row = '' | select VMname, VMid, VPGname, VPGid, Volume
$row.VMname = $vmname;
$row.VMid = $vmid;
$row.VPGname = $vpgname;
$row.VPGid = $vpgid;
$row.Volume = $vol_arr;
$z_arr += $row
}
I'm not emotionally attached to using this function - so if anyone has a working function that just populates the write-progress parameters with useful info including -secondsremaining, i'll take it. Otherwise - anyone have any idea why this function breaks the loop. (if i take it out of the loop, loop runs fine)