Powershell Command Processing (Passing in Variables)

后端 未结 6 2225
没有蜡笔的小新
没有蜡笔的小新 2021-02-15 23:01

I\'m creating a Powershell script to deploy some code and part of the process is to call a command-line compression tool called RAR.EXE to back-up some folders.

I\'m at

相关标签:
6条回答
  • 2021-02-15 23:42

    The call operator '&' is unnecessary in this case. It is used to invoke a command in a new scope. This is typically used to invoke a command specified by a string or scriptblock. It also has the side benefit that any variables created in say a PowerShell script are discarded after the command finishes and the scope goes away.

    However since the cmd is an EXE it executes in a completely different process. FWIW, you get similar output directly from cmd.exe:

    > cmd "/c echo foo"
    foo"
    

    So the extra quote on the end is a cmd.exe issue. Typically you need to keep the command separate from the parameters when PowerShell is doing the parsing to invoke the command e.g.

    45> & { $foo = "foo" }
    46> $foo  # Note that $foo wasn't found - it went away with the scope
    47> . { $foo = "foo" } # dotting executes in the current scope
    48> $foo 
    foo
    

    The notable exception here is that Invoke-Expression behaves like an "evaluate this string" function. Use with care, especially if the user provides the string. Your day could suck if they provided "ri C:\ -r".

    In this case, as others have suggested I would pull the /c out of the string $param string and specify it e.g.:

    cmd /c $param
    

    Or use Invoke-Expression but use with care. BTW when you are trying to debug issues with sending arguments to EXE from PowerShell, check out the echoargs utility in PowerShell Community Extensions (http://pscx.codeplex.com). It is very handy:

    49> $param = "/c echo foo"
    50> echoargs $param
    Arg 0 is </c echo foo>
    

    This shows that cmd.exe receives "/c echo foo" as a single argument. "/c" should be a separate argument from "echo foo" (the command to execute).

    0 讨论(0)
  • 2021-02-15 23:50

    Args are treated differently when they are contained in a String:

    PS D:\> echo "1 2 3"
    1 2 3
    PS D:\> echo 1 2 3
    1
    2
    3
    

    The same results occur when you use a variable for the args:

    PS D:\> $param = "1 2 3"
    PS D:\> echo $param
    1 2 3
    

    The SOLUTION is to use an Array:

    PS D:\> $param = @(1,2,3)
    PS D:\> echo $param
    1
    2
    3
    
    0 讨论(0)
  • 2021-02-15 23:53

    I have had problems with the & call operator in the past when trying to invoke executable type commands like you are trying. Not sure I understand why. Invoke-Expression however, always seems to work in this context:

    PS C:\> $cmd = "cmd /c echo foo"
    PS C:\> Invoke-expression $cmd
    foo
    
    0 讨论(0)
  • 2021-02-15 23:55

    Your last example if failing because "&" treats the string as one argument, so it is looking for a program named "cmd /c echo foo.exe". :)

    This works:

    & $cmd $params
    

    As for the double quote issue, it does seem that cmd does not like the quotes around arguments that PowerShell puts. It gets this:

    cmd "/c echo foo"
    

    So I think it treats everything after /c as the exact command, so like so:

    echo foo"
    

    Some command line programs and funky parsing of the command line (that is why PowerShell takes over this job for functions and cmdlets). In the case of cmd, I would suggest this:

    $param = "echo foo"
    & cmd /c $param
    
    0 讨论(0)
  • 2021-02-16 00:00

    One other way I found to do this was to create an array of arguments for the command line and use that with the apersand & call operator. Something like this:

    $exe = "cmd";
    [Array]$params = "/c", "echo", "foo";
    
    & $exe $params;
    

    It's worked well for me.

    I originally found this technique here: http://techstumbler.blogspot.com/2009/12/windows-commands-with-arguments-in.html

    0 讨论(0)
  • 2021-02-16 00:06

    it's an artifact of using cmd /c, I think. running

    $param = "echo foo"
    cmd /c $param
    

    works fine. Unless you have a real code example, it's a bit hard to trouble shoot.

    0 讨论(0)
提交回复
热议问题