简体   繁体   English

如何将 If 语句传递给 PowerShell 的启动进程的参数列表?

[英]How to pass an If statement to the Argumentlist of Start-process for PowerShell?

if ($PSVersionTable.PSVersion.Major,$PSVersionTable.PSVersion.Minor -join "." -gt 5.1) {   
    
Start-Process -FilePath "PowerShell.exe" -ArgumentList 'if((get-WindowsOptionalFeature -Online -FeatureName SmbDirect).state -eq "disabled"){Enable-WindowsOptionalFeature -Online -FeatureName SmbDirect -norestart}'
}

else
{
if((get-WindowsOptionalFeature -Online -FeatureName SmbDirect).state -eq "disabled"){Enable-WindowsOptionalFeature -Online -FeatureName SmbDirect -norestart}
}

even though I made it a one-liner, It still won't work.即使我把它做成了单线,它仍然行不通。 the result is a new PowerShell window opening for a split second and closing.结果是一个新的 PowerShell window 打开瞬间关闭。

how can I make it work?我怎样才能让它工作?

I studied the Argumentlist but couldn't find a way.我研究了Argumentlist但找不到方法。

This looks like a "losing the doublequotes problem".这看起来像是“丢失双引号问题”。

powershell '"a"'

a : The term 'a' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and
try again.

Swap the single and doublequotes.交换单引号和双引号。 Not that start-process is needed.不需要启动过程。 See also PowerShell stripping double quotes from command line arguments另见PowerShell 从命令行剥离双引号 arguments

Start-Process -FilePath "PowerShell.exe" -ArgumentList "if((get-WindowsOptionalFeature -Online -FeatureName SmbDirect).state -eq 'disabled'){Enable-WindowsOptionalFeature -Online -FeatureName SmbDirect -norestart}"

tl;dr tl;博士

  • To make your command work, escaped the embedded " chars in your -ArgumentList argument as \" .为了使您的命令正常工作,请将-ArgumentList参数中嵌入的"字符转义为\"

    • Alternatively, use embedded ' chars escaped as '' , or use "..." for the outer quoting, in which case you can use ' as-is - but note that this bears the risk of up-front expansion of variable references and expressions, unless you escape $ instances as `$ .或者,使用嵌入'转义为''的字符,或使用"..."作为外部引号,在这种情况下,您可以按原样使用' - 但请注意,这具有预先扩展变量引用的风险,并且表达式,除非你将$实例转义为`$
  • However, Start-Process may not be the best way to invoke your command ;但是, Start-Process可能不是调用命令的最佳方式 if synchronous invocation with output to the caller's console is desired / acceptable, use a script block to pass your command as-is (works from inside PowerShell only):如果需要/可以接受与 output同步调用到调用者的控制台,请使用脚本块按原样传递命令(仅在 PowerShell内部工作):

     PowerShell.exe { if((get-WindowsOptionalFeature -Online -FeatureName SmbDirect).state -eq "disabled"){Enable-WindowsOptionalFeature -Online -FeatureName SmbDirect -norestart} }

Background information:背景资料:

js2010's answer provides effective solutions, but let me try to provide a systematic overview of the issues involved , to avoid potential misconceptions: js2010的回答提供了有效的解决方案,但让我尝试对所涉及的问题进行系统的概述,以避免潜在的误解:

  • Calling powershell.exe , the Windows PowerShell CLI (or its PowerShell (Core) equivalent, pwsh , from PowerShell is rarely necessary .很少需要从 PowerShell调用powershell.exe 、Windows PowerShell CLI(或其PowerShell(核心)等价物pwsh

  • As with any external program , you have two basic invocation choices :与任何外部程序一样,您有两个基本的调用选择

    • Direct invocation (possibly via & , the call operator , which is situationally required for syntactic reasons ).直接调用(可能通过&调用运算符出于句法原因在某些情况下是必需的)。

      • Direct invocation is usually the right approach, as it executes the program synchronously , with the program's output streams connected to PowerShell's, which by default displays them in the caller's console .直接调用通常是正确的方法,因为它同步执行程序,程序的 output 流连接到 PowerShell 的,默认情况下将它们显示在调用者的控制台中。

      • From inside PowerShell , irrespective of whether you're calling the respective other edition on Windows, using a script block ( {... } ) is the best choice - see this answer .PowerShell 内部,无论您是否在 Windows 上调用相应的其他版本,使用脚本块 ( {... } ) 是最佳选择 - 请参阅此答案

    • Invocation via Start-Process , which by default executes asynchronously , in a new window , and is therefore only needed in special circumstances .通过Start-Process调用,默认情况下在新的 window异步执行,因此仅在特殊情况下才需要。


The fundamental problem with your own approach is that any " characters in the -ArgumentList argument must be escaped as \" :您自己的方法的根本问题是-ArgumentList参数中的任何"字符必须转义为\"

  • Passing a piece of PowerShell code to a PowerShell CLI's -Command ( -c ) parameter ( by default with powershell.exe only, explicitly with pwsh ) employs two parsing passes :将一段 PowerShell 代码传递给 PowerShell CLI 的-Command ( -c ) 参数默认情况下仅使用powershell.exe显式使用pwsh )使用两个解析过程:

    • In short: unescaped " chars. are stripped during command-line parsing , and only then are the argument(s) interpreted as PowerShell code .简而言之:转义"字符。在命令行解析期间被剥离,然后参数才被解释为 PowerShell 代码

    • Any " characters you want to be part of the PowerShell code to evaluate , must be escaped .任何您希望成为PowerShell 代码一部分的"都必须进行转义

      • Using embedded '...' quoting, if possible, is a way to avoid this need.如果可能,使用嵌入式'...'引号是避免这种需要的一种方法。
      • PowerShell itself, in both editions, always recognizes \" as an escaped " , but when calling from cmd.exe , different forms are needed in edge cases - see this answer . PowerShell 本身,在两个版本中,始终\"识别为转义的" ,但是当cmd.exe调用时,在边缘情况下需要不同的 forms - 请参阅此答案
  • When using Start-Process with a single-string -ArgumentList argument:Start-Process单字符串-ArgumentList参数一起使用时:

    • The (possibly preprocessed by PowerShell) string's verbatim value becomes part of the raw process command line that is constructed behind the scenes, so using \" to escape " chars. (可能由 PowerShell 预处理)字符串的逐字值成为在幕后构建的原始进程命令行的一部分,因此使用\"转义"字符。 is enough.足够。
  • When using direct invocation :使用直接调用时

    • It is reasonable to expect PowerShell to automatically escape embedded " characters, such as when calling powershell.exe '"hi"'期望PowerShell自动转义嵌入的"字符是合理的,例如调用powershell.exe '"hi"'

      • However, due to a long-standing bug up to v7.2.x, this does not work as expected - see this answer .但是,由于一直存在到 v7.2.x 的错误,这无法按预期工作- 请参阅此答案
    • In PowerShell 7.3.0 and 7.3.1 , specifically, it does work as expected by default , however, a future update will likely require opt-in - see GitHub issue #18694PowerShell 7.3.0 和 7.3.1中,具体来说,默认情况下确实按预期工作,但是,未来的更新可能需要选择加入- 请参阅GitHub 问题 #18694

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM