Trying to run simple http server in separate process using powershell. But can't figure out how to pass parameters to it. Tried several approaches and constantly getting exception. Could you advice?
$port = 9700
$prefix = 'http://+:{0}/' -f $port;
$ScriptBlock = {
$http = [System.Net.HttpListener]::new()
$http.Prefixes.Add($args[0]);
$http.Start();
$Error.Clear(); }
Start-Process pwsh -ArgumentList '-NoProfile', '-NoExit', "-Command" $ScriptBlock $prefix -NoNewWindow -Wait
In result of example above it: A positional parameter cannot be found that accepts argument ' $http = [System.Net.HttpListener]::new() | $http.Prefixes.Add($args[0]); $http.Start(); $Error.Clear(); '.
All pass-through arguments passed to
Start-Processmust be the elements of a single array passed to-ArgumentList.$ScriptBlockand$prefixin your call aren't part of the-ArgumentListarray and therefore constitute additional, positional arguments fromStart-Process's perspective, which it doesn't recognize - that caused the error you saw.Fundamentally, all pass-through arguments are invariably strings, so you cannot pass a script block as such (it would be turned into its verbatim source code, not including the enclosing
{and})However, since are looking for synchronous invocation (
-Wait) in the same window (-NoNewWindow), there's no need forStart-Processat all, and you can simply callpwshdirectly, which - from inside a PowerShell session ony - does allow you to use a script block:See the docs for PowerShell (Core)'s CLI,
pwsh.If you do want to use
Start-Process- which is only necessary if you want to run the code in a new window or with elevation (as admin) or with a different user identity - use the following:For readability and ease of embedding quotes, the solution uses an expandable here-string (
@"<newline>...<newline>@").It takes advantage of the fact that script blocks serialize as their verbatim source code, excluding
{and}, so you make the target PowerShell instance invoke it by enclosing it in& { ... }in the command string.& { $ScriptBlock }would work in your particular case, to make the technique robust, any embedded"characters must be escaped as\"-escaped in order to ensure that the CLI's initial command-line parsing doesn't remove them.This is what the
-replace '(?<!\\)(\\*)"', '$1$1\"'operation below does.Note:
All pass-through arguments for
pwshare encoded in a single string passed to the (positionally implied)-ArgumentListparameter.While you could alternatively make use of the
-EncodedCommandand (currently undocumented)-EncodedArgumentsCLI parameters, doing is even more cumbersome, due to requiring Base64 encoding.If you do want to use these parameters with
Start-Process, see this answer for an example.