I want to backup some data over my script. All data shall be zipped in a separate thread. But two things go wrong:
- The function testFct is never called - indication: no "inside: ...".
- The parameter ZipSource is missing - see output.
Calling the script results in:
> .\Backup.ps1
outside: -What: Data A -ZipSource -ZipDest C:\Users\xyz\AppData\Local\Temp -Timestamp "20220517-002854
outside: -What: Data B -ZipSource -ZipDest C:\Users\xyz\AppData\Local\Temp -Timestamp "20220517-002854
>
Here is my Script:
class BackupContentData
{
[ValidateNotNullOrEmpty()][string]$What
[ValidateNotNullOrEmpty()][string]$ZipSource
}
$bcd = @(
[BackupContentData]@{ What="Data A"; ZipSource="$env:USERPROFILE\Documents\a_file.txt";}
[BackupContentData]@{ What="Data B"; ZipSource="$env:USERPROFILE\Documents\b_file.txt";}
)
function testFct {
param([string]$What, [string]$ZipSource, [string]$ZipDest, [string]$Timestamp)
Write-Host "inside: -What: "$What" -ZipSource "$ZipSource" -ZipDest "$ZipDest" -Timestamp "$Timestamp
}
$timestamp="$(get-date -f yyyyMMdd-HHmmss)"
foreach ($e in $bcd) {
$job = Start-ThreadJob -Name $e.What -InputObject $e -ScriptBlock {
Invoke-Expression "function getTest {$using:testFct}"
Write-Host "outside: -What: "$input.What" -ZipSource "$input.ZipSource" -ZipDest "$env:Temp" -Timestamp ""$(get-date -f yyyyMMdd-HHmmss)"
getTest -What "$input.What" -ZipSource "$input.ZipSource" -ZipDest "$env:Temp" -Timestamp "$(get-date -f yyyyMMdd-HHmmss)"
}
Receive-Job $job -AutoRemoveJob -Wait
}
What is wrong with the script?
Since
testFct
doesn't exist in the scope of your ThreadJob, you need to first store the function's definition and then pass it to the runspace scope and define the function there as demonstrated in this answer.The other issue is trying to reference the same
$input
more than one time. Due to the nature of the automatic variable$input
, you can only reference this variable once in your script block:As a workaround you could wrap the variable in the Array subexpression operator
@( )
or the Subexpression operator$( )
to store the enumerated output in a new variable.Here is a simple example of what's explained above:
Lastly, your script is not actually multi-threading, this is because you're storing the job inside your loop and then waiting for it sequentially instead of starting all jobs at once and then waiting for all of them.
The output you can expect from this: