Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing arguments to Start-Job scriptblock?

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!

like image 264
Drism Avatar asked Feb 02 '13 17:02

Drism


People also ask

How do I start a PowerShell job?

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.

What can you use to start a job in PowerShell other than the start-job command?

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 .

How do I run a process in the background in Windows PowerShell?

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.

How do I view background jobs in PowerShell?

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.


2 Answers

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" }
like image 125
Loïc MICHEL Avatar answered Oct 31 '22 13:10

Loïc MICHEL


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 the ScriptBlock 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.

like image 25
Bender the Greatest Avatar answered Oct 31 '22 15:10

Bender the Greatest