Since I find myself coming to different conclusions than Don Jones, I’m guessing I have just misunderstood something or have missed something completely and I’m not testing what I should be testing. If someone sees an error in how I’m using Remote Variables or something else amiss in the tests, please correct me. However, from my naive, simple tests, it seems as though PowerShell does parse the scriptblock correctly, but using Remote Variables does not work with Register-ScheduledJob.
Invalid Remote Variable Name - Fails parsing and thus never invokes the command on the “remote” machine.
I get an error message if I use an invalid variable name like the following script (it’s probably unnecessarily large since I’ve been reusing the same test-method, just altered it a little for the other two tests):
1. function Test-ScheduledJobWithInvalidRemoteVariableName
2. {
3. PARAM (
4. $MyParam
5. )
6.
7. Invoke-Command -ComputerName localhost -ScriptBlock {
8. # First just plainly remove the job if it exists
9. Get-ScheduledJob -Name "Test-ScheduledJobWithInvalidRemoteVariableName" -EA SilentlyContinue | Unregister-ScheduledJob
10.
11. $arguments = @{
12. Name = "Test-ScheduledJobWithInvalidRemoteVariableName";
13. ScheduledJobOption = @{ RunElevated = $true };
14. RunNow = $True;
15. ScriptBlock = { $Using:NonExistingRemoteVariableName | Out-File C:\InvalidRemoteVariableValue.txt };
16. }
17.
18. Register-ScheduledJob @arguments
19. }
20. }
21.
22. Test-ScheduledJobWithInvalidRemoteVariableName -MyParam "The invalid remote param value"
On line 15 we can see $Using:NonExistingRemoteVariableName which, of course, does not exist in the local scope. Running this code gives the following exception, making it seem as though PowerShell parses the scriptblock.
Invoke-Command : The value of the using variable '$using:NonExistingRemoteVariableName' can
not be retrieved because it has not been set in the local session.
At line:7 char:5
+ Invoke-Command -ComputerName localhost -ScriptBlock {
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [Invoke-Command], RuntimeException
+ FullyQualifiedErrorId : UsingVariableIsUndefined,Microsoft.PowerShell.Commands.Invok
eCommandCommand
Also, it does not run any of the code inside the scriptblock passed to Invoke-Command, since it states that the script is using an invalid remote variable (error id: UsingVariableIsUndefined).
Scheduled Job with Remote Variable - Registers the job but the Remote Variable does not have any value
I don’t get any error message if, on the other hand, I use a correctly named local variable, the MyParam variable, as in the following code:
1. function Test-ScheduledJobWithRemoteVariable
2. {
3. PARAM (
4. $MyParam
5. )
6.
7. Invoke-Command -ComputerName localhost -ScriptBlock {
8. # First just plainly remove the job if it exists
9. Get-ScheduledJob -Name "Test-ScheduledJobWithArgumentList" -EA SilentlyContinue | Unregister-ScheduledJob
10.
11. $arguments = @{
12. Name = "Test-ScheduledJobWithArgumentList";
13. ScheduledJobOption = @{ RunElevated = $true };
14. RunNow = $True;
15. ScriptBlock = { $Using:MyParam | Out-File C:\RemoteVariableValue.txt };
16. }
17.
18. Register-ScheduledJob @arguments
19. }
20. }
21.
22. Test-ScheduledJobWithRemoteVariable -MyParam "The remote param value"
(The only difference from the last code is the function name, the job name and the variable name used on line 15.)
Since the $Using:MyParam exists in the local scope, PowerShell accepts this script as valid. However, the C:\RemoteVariableValue.txt which was created will be an empty file.
Scheduled Job with ArgumentList - Correctly passes the expected parameter value to the Scheduled Job.
The third case, using -ArgumentList to pass the value of the variable to the scheduled job seems to work fine.
1. function Test-ScheduledJobWithArgumentList
2. {
3. PARAM (
4. $MyParam
5. )
6.
7. Invoke-Command -ComputerName localhost -ScriptBlock {
8. # First just plainly remove the job if it exists
9. Get-ScheduledJob -Name "ScheduledJobWithArgumentList" -EA SilentlyContinue | Unregister-ScheduledJob
10.
11. $arguments = @{
12. Name = "ScheduledJobWithArgumentList";
13. ScheduledJobOption = @{ RunElevated = $true };
14. RunNow = $True;
15. ArgumentList = $Using:MyParam;
16. ScriptBlock = { PARAM ($ArgumentPassed) $ArgumentPassed | Out-File C:\ArgumentListValue.txt }
17. }
18.
19. Register-ScheduledJob @arguments
20. }
21. }
22.
23. Test-ScheduledJobWithArgumentList -MyParam "The ArgumentList param value"
(The only difference from the last code is the function name, the job name, the scriptblock on line 16 and the argument ArgumentList was added on line 15.)
The C:\ArgumentListValue.txt file will have the correct “The ArgumentList param value” text as content.
Conclusion/Summary
The only way I get to work is using -ArgumentList to pass the value. So I’m probably doing something wrong when I try to use the $Using scope to use the parameter in the scheduled job, or using Remote Variables doesn’t work with ScheduledJobs. If someone finds an error in the above tests or reasoning, could you please point me to the error of my reasoning or perhaps a resource which explains Remote Variables, and how they are implemented, in detail?