How to Chain Commands at a Special PowerShell 4 Command Prompt?

Normally, PowerShell commands can be chained with semicolons. The following opens 2 notepads:

PS> notepad; notepad

You can also chain a more complex statement:

PS> Add-Type -AssemblyName System.IO.Compression; `
> $src = "C:aFolder"; $zip="C:my.zip"; `
> [io.compression.zipfile]::CreateFromDirectory($src, $zip)

Chained PowerShell commands can also be called from a CMD command-line:

C:> powershell notepad; notepad

This post describes a method to create a .Net 4.0 PowerShell prompt, even if .Net 2.0 is the active framework on your OS. You create a .cmd script, and run that. Now you're in a .Net 4.0 environment.

Chaining also works at that 4.0 prompt:

C:> ps4.cmd
PS> notepad; notepad

And also works from standard CMD prompt:

C:> ps4 notepad; notepad

This post describes a way to do Add-Type to an explicit pathname (needed to reference 4.0 assemblies from the ps4 prompt):

Add-Type -Path "C:WindowsMicrosoft.NETassemblyGAC_MSILSystem.IO.Compression.FileSystemv4.0_4.0.0.0__b77a5c561934e089System.IO.Compression.FileSystem.dll"

That works, even when chained at the ps4 prompt:

C:> ps4
PS> Add-Type -Path "C:xSystem.IO.Compression.FileSystem.dll"; `
> $src = "C:xxl"; $zip="C:xxl.zip"; `
> [io.compression.zipfile]::CreateFromDirectory($src, $zip)

Problem: chaining the above statement fails when ps4 is launched at a standard command prompt (error in full at bottom of post):

C:> ps4 Add-Type -Path "C:xSystem.IO.Compression.FileSystem.dll"; $src = "C:xxl"; $zip="C:xxl.zip"; [io.compression.zipfile]::CreateFromDirectory($src, $zip)

Yet, all the above methods work. Why? How can I make this work?

The term 'C:xxl' 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.
At line:1 char:73
+ Add-Type -Path C:xSystem.IO.Compression.FileSystem.dll; $src = C:xxl <<<< ; $zip=C:xxl.zip;
[io.compression.zipfile]::CreateFromDirectory($src, $zip)
    + CategoryInfo          : ObjectNotFound: (C:xxl:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

The term 'C:xxl.zip' 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.
At line:1 char:91
+ Add-Type -Path C:xSystem.IO.Compression.FileSystem.dll; $src = C:xxl; $zip=C:xxl.zip <<<< ;
[io.compression.zipfile]::CreateFromDirectory($src, $zip)
    + CategoryInfo          : ObjectNotFound: (C:xxl.zip:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

Exception calling "CreateFromDirectory" with "2" argument(s): "The path is not
of a legal form."
At line:1 char:138
+ Add-Type -Path C:xSystem.IO.Compression.FileSystem.dll; $src = C:xxl; $zip=C:xxl.zip;
[io.compression.zipfile]::CreateFromDirectory <<<< ($src, $zip)
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : DotNetMethodException

The double quotes around the strings are removed when the daisy-chained commands are passed to powershell.exe . Add-Type isn't affected by this, since the path doesn't contain spaces, so it doesn't require quotes:

Add-Type -Path C:xSystem.IO.Compression.FileSystem.dll   # <- this works

However, in an assignment operation PowerShell requires strings to be in quotes, otherwise it will interpret the string as a command and try to execute it:

$src = C:xxl  # <- this would try to run a (non-existent) command 'C:xxl'
                #    and assign its output to the variable instead of assigning
                #    the string "C:xxl" to the variable

That is what causes the first two errors you observed. The third error is a subsequent fault, because the two path variables weren't properly initialized.

You should be able to avoid this behavior by escaping the double quotes:

ps4 Add-Type -Path "C:xSystem.IO.Compression.FileSystem.dll"; $src = "C:xxl"; $zip="C:xxl.zip"; [io.compression.zipfile]::CreateFromDirectory($src, $zip)

or by replacing them with single quotes (because the latter are not recognized by CMD as quoting characters and are thus passed as-is to PowerShell, which does recognize them as quoting characters):

ps4 Add-Type -Path 'C:xSystem.IO.Compression.FileSystem.dll'; $src = 'C:xxl'; $zip='C:xxl.zip'; [io.compression.zipfile]::CreateFromDirectory($src, $zip)

However, rather than working around this issue I'd recommend creating and running proper PowerShell scripts, so you can avoid this problem entirely:

#requires -version 4
[CmdletBinding()]
Param(
  [Parameter(Mandatory=$true)]
  [string]$Path,
  [Parameter(Mandatory=$true)]
  [string]$Zipfile,
)

Add-Type -Assembly 'System.IO.Compression.FileSystem' | Out-Null
[IO.Compression.ZipFile]::CreateFromDirectory($Path, $Zipfile)

The script would be run like this:

powershell.exe -File zip.ps1 -Path "C:xxl" -Zipfile "C:xxl.zip"

If you change the execution policy to RemoteSigned or Unrestricted and also change the default handler for .ps1 files you could even run the script like this:

zip.ps1 -Path "C:xxl" -Zipfile "C:xxl.zip"
链接地址: http://www.djcxy.com/p/29040.html

上一篇: 'useLegacyV2RuntimeActivationPolicy'在.NET 4配置中做了什么?

下一篇: 如何在特殊的PowerShell链接命令4命令提示符?