且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

PowerShell 脚本添加“--prod"参数以构建 Angular CLI 项目

更新时间:2023-10-15 18:47:40

Neko Musume 的有用回答 为您的当前问题提供了解决方案.

但是,退一步是值得的:

要同步执行控制台应用程序或批处理文件,请直接调用它们(ng build ...& ng build ...),不要使用 Start-Process - 参见 this answerthis GitHub docs issue 详细说明了适当的与不适当的用例并要求将指南添加到 Start-Process 帮助主题.

因此:

# 同步执行 ng,其输出流连接到 PowerShell 的ng build --prod D:\pathToAngularProject


至于你尝试了什么:

补充 Neko 的回答:

您的第一个命令起作用的原因如下:

Start-Process -FilePath ng build ...

相当于:

Start-Process -FilePath -FilePath ng -ArgumentList build ...

也就是说,build 参数是位置绑定的,无需明确命名其目标参数,-ArgumentList.>

利用这一点,并且 -FilePath 隐含在 first 位置参数中,您的问题的直接解决方案可以简化为:

# 第一个位置参数,'ng',绑定到 -FilePath# 第二个位置参数,要传递给 'ng' 的参数的 *array*,# 'build' 和 '--prod',绑定到 -ArgumentList开始处理 ng build, --prod ...

也就是说,Start-Process 有一个长期存在的错误,导致它错误地传递带有嵌入空格的参数 - 参见 GitHub 问题 #5576.为了保持向后兼容性,此错误可能不会得到修复(除非通过 引入新参数).

因此***将参数作为单个数组元素传递,有效地作为命令行(没有可执行文件),其中如有必要,可以使用嵌入的"..."引用适当地表示参数之间的边界:

# 将 'ng' 的参数 * 作为单个字符串 * 传递,可能# 带有嵌入的...";引用(这里不需要).开始处理 ng 'build --prod' ...

嵌入引用的示例:

# 项目路径需要嵌入...";引用,因为它包含空格.Start-Process ng 'build --prod "D:\Work Projects\Foo"'...


关于引用数组元素的一般说明:

因为命令参数在PowerShell中是使用所谓的参数(解析)模式(shell-like)解析的,(隐含)的(字符串)元素-ArgumentList不需要通常需要引用.

也就是说,参数模式中的数组build,--prod等价于'build','--prod'表达式模式(类编程语言).

有关 PowerShell 解析模式的概述,请参阅此答案.

但是,您也可以在参数模式中使用引用形式,并且 - 根据元素值 - 您可能必须引用,例如当元素包含空格或其他 shell 元字符时;此外,如果 first 元素看起来像一个 PowerShell 参数名称(例如,-prod 而不是 --prod),也必须引用.

一些例子:

注意:为简单起见,示例中使用了 Write-Output,它只是在自己的行上回显每个数组元素.传递给any cmdlet 的数组以参数模式进行解析.

# 不需要引用.# 元素不包含 PowerShell 元字符.写输出一、二# 第二个数组元素需要引用,因为包含# PowerShell 元字符(空格、括号)写输出一,'二(2)'# 第一个数组元素需要引用,因为它看起来# 就像一个 PowerShell 参数名称.# (当然,在这种情况下,您可以选择引用 *both* 元素,# 为了一致性).写输出-一",二# 如果类似参数的参数不是 *first* 数组元素,# 不再需要引用写输出一,-二

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:

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

Neko Musume'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, effectively as a command line (without the executable), where the boundaries between the arguments can properly be signaled with embedded "..." 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"' ...


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