Reputation: 309
I'd like to setup a cmdlet to start and stop mysql, and I'm trying to do so with Start-Job. the I've got the following in my Powershell profile:
$mysqlpath = "C:\Program Files\MySQL\MySQL Server 5.5\bin"
Function Start-Mysql
{
Start-Job -ScriptBlock { & "$mysqlpath\mysqld.exe" }
}
The variable doesn't seem to be expanding in the job command however? I must be missing some sort of scoping rule. Could someone please advise? Thanks!
Upvotes: 8
Views: 11456
Reputation: 21418
Loïc MICHEL's answer is correct, but if you find it becomes difficult to deal with remembering which positional argument is which within the ScriptBlock
, I'd like to offer a trick using the param
keyword. Within the ScriptBlock
, begin the body with param
like you would for an advanced function, and put your code after also as if it were a function:
Note: The
ScriptBlock
param
name does not need to be the same in theScriptBlock
and current session, it can be the same or something totally different. The important thing is you match the correct argument positionally in the-ArgumentList
.
Start-Job { param( $mysqlpath ) & "$mysqlpath\mysqld.exe" } -ArgumentList $mysqlpath
This works because a ScriptBlock
is just an unnamed function, so you can define parameters in mostly the same way you can when defining a proper function. The arguments in -ArgumentList
are passed to the ScriptBlock
as positional arguments in the order provided, so by default the order the arguments are passed is the same order they will be bound to named parameters in.
While the $using:
scope is syntactically easier to work with, this method gets you the best of all worlds here, as the $using:
scope cannot be used within the current session. This is incredibly useful you have a ScriptBlock
that needs to be able to execute in any context and it's complicated enough that referencing the arguments by index becomes difficult to manage. This approach allows you to name your parameters and works with any ScriptBlock
in all execution contexts, whether it's Start-Job
, Invoke-Command
, powershell.exe
, or executing a ScriptBlock
with the call operator &
.
This is one of (if not the) most portable solution if you want to use named variables instead of referencing $args[i]
for every variable.
Upvotes: 2
Reputation: 26120
you have to use the -argumentlist
parameter see get-help start-job :
start-job -ScriptBlock { & $args[0] } -ArgumentList @($mysqlpath )
note that in V3 you just have to use the prefix using:
before your varname ex:
Start-Job -ScriptBlock { & "$using:mysqlpath\mysqld.exe" }
Upvotes: 12