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!
The Start-Job cmdlet starts a PowerShell background job on the local computer. A PowerShell background job runs a command without interacting with the current session. When you start a background job, a job object returns immediately, even if the job takes an extended time to finish.
Invoke-Command - The AsJob parameter creates a background job on a remote computer. You can use Invoke-Command to run any job command remotely, including Start-Job .
To run commands in the background in the PowerShell, you need to use Background job cmdlets. Background job means running commands/job in the background without occupying the console.
The Get-Job cmdlet gets objects that represent the background jobs that were started in the current session. You can use Get-Job to get jobs that were started by using the Start-Job cmdlet, or by using the AsJob parameter of any cmdlet. Without parameters, a Get-Job command gets all jobs in the current session.
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" }
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With