3

I am creating PowerShell script to automatically build Angular CLI project. When I use this command in my .ps1 file:

Start-Process -FilePath ng build -WorkingDirectory D:\pathToAngularProject -Wait

it works perfectly but create not uglified javascript build. To be able to create production build I need to add '--prod' argument. But when I change example above on :

Start-Process -FilePath ng build -ArgumentList '--prod' -WorkingDirectory D:\pathToAngularProject -Wait

I am getting the error: enter image description here

Does anyone have a suggestion how can I add an argument to 'ng build' command in PowerShell script?

1
  • 4
    What is ng build? If it is a file, surround it in quotes "ng build" if it is an argument, add it to the argument list -ArgumentList '--prod', 'build' Commented Jul 7, 2020 at 20:27

2 Answers 2

5

Neko Nekoru's helpful answer provides a solution to your immediate problem.

However, it's worth taking a step back:

To synchronously execute console applications or batch files, call them directly (ng build ... or & ng build ...), do not use Start-Process - see this answer and this GitHub docs issue detailing appropriate vs. non-appropriate use cases and requesting that guidance be added to the Start-Process help topic.

Therefore:

# Execute ng synchronously, with its output streams connected to PowerShell's
ng build --prod D:\pathToAngularProject

As for what you tried:

To add to Neko's answer:

The reason that your first command worked is that the following:

Start-Process -FilePath ng build

is equivalent to:

Start-Process -FilePath -FilePath ng -ArgumentList build

That is, the build argument was bound positionally, without the need to name its target parameter, -ArgumentList, explicitly.

Taking advantage of this, and also that -FilePath is implied for the first positional argument, the immediate solution to your problem could be simplified to:

# The 1st positional argument, 'ng', binds to -FilePath
# The 2nd positional argument, the *array* of arguments to pass to 'ng',
# 'build' and '--prod', binds to -ArgumentList
Start-Process ng  build, --prod

That said, Start-Process has a long-standing bug that causes it to pass arguments with embedded spaces incorrectly - see GitHub issue #5576. To preserve backward compatibility, this bug will likely not get fixed (except perhaps by introducing a new parameter).

It is therefore preferable to pass the arguments as a single array element, i.e. as a single string that encodes all arguments, where the boundaries between the arguments can properly be signaled with embedded double-quoting ("..."), if necessary:

# Pass the arguments for 'ng' *as a single string*, potentially
# with embedded "..." quoting (not needed here).
Start-Process ng  'build --prod'

An example with embedded quoting:

# Project path needs embedded "..." quoting, because it contains spaces.
Start-Process ng  'build --prod "D:\Work Projects\Foo"' ...

An example that uses an expandable (double-quoted) string ("...") in order to embed the values of variables / subexpressions (the embedded " chars. must then be escaped as `" (or "")):

$projDir = 'D:\Work Projects'
Start-Process ng  "build --prod `"$projDir\Foo`"" ...

Alternatively, using a here-string obviates the need for escaping the embedded quotes:

$projDir = 'D:\Work Projects'
Start-Process ng @"
build --prod "$projDir\Foo"
"@ ...

A general note on quoting array elements:

Because command arguments in PowerShell are parsed using the so-called argument (parsing) mode (shell-like), the (string) elements of the (implied) -ArgumentList do not generally require quoting.

That is, array build, --prod in argument mode is the equivalent of 'build', '--prod' in expression mode (programming-language-like).

See this answer for an overview of PowerShell's parsing modes.

However, you may use the quoted form in argument mode too, and - depending on the element values - you may have to quote, such as when elements contain spaces or other shell metacharacter; additionally, if the first element looks like a PowerShell parameter name (e.g., -prod rather than --prod), it must be quoted too.

A few examples:

Note: For simplicity, Write-Output is used in the examples, which simply echoes each array element on its own line. An array passed to any cmdlet is parsed in argument mode.

# No quoting needed.
# Elements contain no PowerShell metacharacters.
Write-Output one, two

# Quoting needed for the 2nd array element, due to containing
# PowerShell metacharacters (space, parentheses)
Write-Output one, 'two (2)'

# Quoting needed for the 1st array element, because it looks
# like a PowerShell parameter name.
# (Of course, you may choose to quote *both* elements in this case,
# for consistency).
Write-Output '-one', two

# If the parameter-like argument isn't the *first* array element,
# the need for quoting goes away
Write-Output one, -two
Sign up to request clarification or add additional context in comments.

Comments

3

Add build to the -argumentlist if it is an argument like:

Start-Process -FilePath ng -ArgumentList 'build', '--prod' -WorkingDirectory D:\pathToAngularProject -Wait 

If it is part of the path quote it in the -path parameter because there are spaces:

Start-Process -FilePath "ng build" -ArgumentList '--prod' -WorkingDirectory D:\pathToAngularProject -Wait

2 Comments

The executable is ng by itself, which is the Angular CLI. However, it's worth pointing out that Start-Process is usually the wrong tool for invoking CLIs (console applications).
Also, while -ArgumentList should be the proper way to pass arguments through individually, it unfortunately isn't in the general case, due to a longstanding bug (see this GitHub issue) - since the arguments in this particular case contain no spaces, the command works, however.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.