PowerShell中运行CMD命令的技巧总结(解决名称冲突和特殊字符等问题)

引言

我从老旧的 CMD.EXE 命令行换到优秀的 POWSERSHELL.EXE 已经有一段时间啦。您可能知道新的 Windows PowerShell 可以运行任何旧命令。不过有些旧命令的名称或语法可能会产生问题。但这都不是事儿。

麻烦 1:名称冲突

PowerShell 的 cmdlet 别名和旧命令的名称有冲突是个常见的问题。比如说您喜欢的服务控制命令 SC.EXE。SC.EXE 非常灵活!我能理解您为什么喜欢它(不要为用 NET.EXE 管理服务找借口)。如果您想查看 SMB Server 服务的状态,可以在 CMD.EXE 里这样用:


代码如下:

C:\>SC QUERY LANMANSERVER

SERVICE_NAME: LANMANSERVER
TYPE : 20 WIN32_SHARE_PROCESS
STATE : 4 RUNNING
(STOPPABLE, PAUSABLE, IGNORES_SHUTDOWN)
WIN32_EXIT_CODE : 0 (0x0)
SERVICE_EXIT_CODE : 0 (0x0)
CHECKPOINT : 0x0
WAIT_HINT : 0x0

如果您在 PowerShell 中尝试同样的事,会得到:


代码如下:

PS C:\> SC QUERY LANMANSERVER
Set-Content : Access to the path 'C:\QUERY' is denied.
At line:1 char:1
+ SC QUERY LANMANSERVER
+ ~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : PermissionDenied: (C:\QUERY:String) [Set-Content], UnauthorizedAccessException
+ FullyQualifiedErrorId : GetContentWriterUnauthorizedAccessError,Microsoft.PowerShell.Commands.SetContentCommand

因为 SC 是 Set-Content 的别名。它优先于 SC.EXE 文件。

方案 1A:使用 .EXE 扩展名

为了克服这个问题,您可以简单地将 .EXE 扩展名包含进旧命令。这消除了歧义并使相同的命令在 CMD.EXE 和 PowerShell 里都能用。还可以清楚告诉使用您脚本的人这里用的是旧 .EXE 命令而非 PowerShell 别名。

代码如下:

PS C:\> SC.EXE QUERY LANMANSERVER

SERVICE_NAME: LANMANSERVER
TYPE : 20 WIN32_SHARE_PROCESS
STATE : 4 RUNNING
(STOPPABLE, PAUSABLE, IGNORES_SHUTDOWN)
WIN32_EXIT_CODE : 0 (0x0)
SERVICE_EXIT_CODE : 0 (0x0)
CHECKPOINT : 0x0
WAIT_HINT : 0x0

方案 1B:使用 CMD /C

另一个办法是把您的命令用引号括起让 CMD.EXE 来运行。但这样做没啥效率,仅仅为了执行您的命令就得运行一个 CMD.EXE 实例。

代码如下:

PS C:\> CMD /C "SC QUERY LANMANSERVER"

SERVICE_NAME: LANMANSERVER
TYPE : 20 WIN32_SHARE_PROCESS
STATE : 4 RUNNING
(STOPPABLE, PAUSABLE, IGNORES_SHUTDOWN)
WIN32_EXIT_CODE : 0 (0x0)
SERVICE_EXIT_CODE : 0 (0x0)
CHECKPOINT : 0x0
WAIT_HINT : 0x0

方案 1C:用等效的 PowerShell

很多情况下,可以用 PowerShell cmdlet 来代替您的旧命令。
例如这里您就可以直接使用 Get-Service:


代码如下:

PS C:\> Get-Service LANMANSERVER | FL

Name : LANMANSERVER
DisplayName : Server
Status : Running
DependentServices : {Browser}
ServicesDependedOn : {SamSS, Srv}
CanPauseAndContinue : True
CanShutdown : False
CanStop : True
ServiceType : Win32ShareProcess

麻烦 2:PowerShell 的特殊字符

有时旧命令的参数使用的字符在 PowerShell 里有特殊意义。
比如您想让某个目录被所有用户完全控制。在 CMD.EXE 里您可以这样做:


代码如下:

C:\>ICACLS.EXE C:\TEST /GRANT USERS:(F)
processed file: C:\TEST
Successfully processed 1 files; Failed processing 0 files

在 CMD.EXE 做这些没问题,但如果你在 PowerShell 运行就会报错:


代码如下:

PS C:\> ICACLS.EXE C:\TEST /GRANT USERS:(F)
The term 'F' 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:34
+ ICACLS.EXE C:\TEST /GRANT USERS:(F)
+ ~
+ CategoryInfo : ObjectNotFound: (F:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundExceptionn

试图给名字以 $ 结尾的电脑对象授权时也会引起一个类似的错误。


代码如下:

PS C:\> ICACLS.EXE C:\TEST /GRANT COMPUTERNAME$:(F)
At line:1 char:39
+ ICACLS.EXE C:\TEST /GRANT COMPUTERNAME$:(F)
+ ~~
Invalid variable reference. '$' was not followed by a valid variable name character. Consider using ${} to delimit the
name.
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : InvalidVariableReference

这个问题是因为括号和美元符在 PowerShell 中都有特殊意义。例如大括号之类常用字符也会引发相似的冲突。也有几种不同的方案来解决这个问题。

方案 2A:使用 CMD /C

和第一个问题一样,你可以引号括起您的命令交给 CMD.EXE 来处理。先不考虑效率,PowerShell 不会去解析引号里的字符串,这样就能正常工作。


代码如下:

PS C:\> CMD.EXE /C "ICACLS.EXE C:\TEST /GRANT USERS:(F)"
processed file: C:\TEST
Successfully processed 1 files; Failed processing 0 files

方案 2B:使用 PowerShell 的转义字符

对于这个方案,您必须先知道使用的字符哪些对 PowerShell 有特殊意义。然后在它们每一个前面加上个反引号(`),它就是 PowerShell 的转义字符。这个方案的主要问题是你必须知道哪些字符需要转义,这让读写您的脚本更困难。
我们的例子里,你需要处理 ( 和 ) 这两个字符:


代码如下:

PS C:\> ICACLS.EXE C:\TEST /GRANT USERS:`(F`)
processed file: C:\TEST
Successfully processed 1 files; Failed processing 0 files

方案 2C:使用 PowerShell v3 的新语法“–%”

在 PowerShell v3 中有另一种选择来解决这个问题。您只需在命令行的任意位置添加 –% 序列(两个短划线和一个百分号)PowerShell 就不会再去解析剩下的部分。
我们的例子里,您可以这样用:


代码如下:

PS C:\> ICACLS.EXE --% C:\TEST /GRANT USERS:(F)
processed file: C:\TEST
Successfully processed 1 files; Failed processing 0 files

也可以这样用:


代码如下:

PS C:\> ICACLS.EXE C:\TEST --% /GRANT USERS:(F)
processed file: C:\TEST
Successfully processed 1 files; Failed processing 0 files

方案 2D:使用等效的 PowerShell

使用等效的 PowerShell 也是种选择。ICACLS.EXE 可以用 Set-ACL 代替。可以从这篇博客中找到更多的 Set-ACL 例子。

混搭

这里展示如何让您安全地享受 PowerShell 结合您的旧命令带来的灵活性。您可能会学到几个技巧并以全新的方式开始新老结合。

例如您能用灵活的 Get-Service 通配符代替 SC.EXE 里晦涩选项:


代码如下:

Get-Service LAN* | % { $_.Name; SC.EXE SDSHOW $_.Name }

或者您可以使用 PowerShell 的 Get-Item(别名 Dir)过滤文件子集传递给 ICACLS.EXE 来处理:


代码如下:

DIR C:\TEST -Recurse | ? {$_.Length -ge 1MB} | % { ICACLS.EXE $_.FullName /Grant Administrator:`(F`) }

您甚至可以循环遍历几个数并结合好用的 FSUTIL.EXE 来创建一批大小不同的文件用于测试项目:


代码如下:

1..100 | % { FSUTIL.EXE FILE CREATENEW C:\TEST\FILE$_.TXT ($_*10KB)

尾声

事到如今,您可能已经确信 Windows PowerShell 是管理员的好朋友啦。然而您可能因为有些旧命令带着古怪的名字或参数而不能使用 POWERSHELL.EXE。我非常鼓励您使用这些技巧来彻底停用 CMD.EXE 并永久迁移到 PowerShell 来作为您主要的 shell。

文章出处:http://www.pstips.net/using-windows-powershell-to-run-old-command-line-tools-and-their-weirdest-parameters.html

(0)

相关推荐

  • Shell脚本中的位置变量参数(特殊字符)实例讲解

    $# : 传递到脚本的参数个数 $* : 以一个单字符串显示所有向脚本传递的参数.与位置变量不同,此选项参数可超过 9个 $$ : 脚本运行的当前进程 ID号 $! : 后台运行的最后一个进程的进程 ID号 $@ : 与$#相同,但是使用时加引号,并在引号中返回每个参数 $- : 显示shell使用的当前选项,与 set命令功能相同 $? : 显示最后命令的退出状态. 0表示没有错误,其他任何值表明有错误. 复制代码 代码如下: #!/bin/sh #param.sh # $0:文件完整路径名

  • Shell命令行中特殊字符与其转义详解(去除特殊含义)

    特殊符号及其转义 大家都知道在一个shell命令是由命令名和它的参数组成的, 比如 cat testfile, 其中cat是命令名, testfile是参数. shell将参数testfile传递给cat命令. 但是, 如果参数中含有特殊字符, 比如说*, *我们知道,是表示任意多个(包括0个)任意字符. 那么shell的工作方式是,它会对这些特殊字符进行预先处理, 然后再将处理的结果传给那个命令. 比如说,如果你的当前目录有file, file1, file2 三个文件, 那么当你执行cat

  • shell脚本中28个特殊字符的作用简明总结

    1. # 注释作用, #! 除外此外, 在参数替换 echo ${PATH#*:} 这里不表示注释, 数制转换, 不表示注释 echo $((2#101011)) 2. ; 命令行分隔符, 可以在一行中写多个命令. echo hello; echo there 3. ;; 终止 case 选项 复制代码 代码如下: case "$variable" inabc) echo "\$variable = abc";;xyz) echo "\$variable

  • Shell脚本中的特殊字符(美元符、反斜杠、引号等)作用介绍

    Shell中的特殊字符有 1.$ 美元符 2.\ 反斜杠 3.` 反引号 4." 双引号 5.< ,>;,*,?,[,] 下面我一一举列说明 一.$符号 1.echo $? 显示的是上一条指令退出状态 2.echo "$?" 效果同上 3.echo '$?' 显示的是$? 4.echo \$? 显示的是$? 5.echo "\$?" 显示的是$? 大家可能已经看出 $符号在双引号中具有特殊意义 双引号对$符号不起作用 而单引号可以将特殊字符的的

  • PowerShell中运行CMD命令的技巧总结(解决名称冲突和特殊字符等问题)

    引言 我从老旧的 CMD.EXE 命令行换到优秀的 POWSERSHELL.EXE 已经有一段时间啦.您可能知道新的 Windows PowerShell 可以运行任何旧命令.不过有些旧命令的名称或语法可能会产生问题.但这都不是事儿. 麻烦 1:名称冲突 PowerShell 的 cmdlet 别名和旧命令的名称有冲突是个常见的问题.比如说您喜欢的服务控制命令 SC.EXE.SC.EXE 非常灵活!我能理解您为什么喜欢它(不要为用 NET.EXE 管理服务找借口).如果您想查看 SMB Serv

  • PowerShell中使用Get-ChildItem命令读取目录、文件列表使用例子和小技巧

    本文介绍一个PowerShell中使用Get-ChildItem这个cmdlet来获取目录下的文件列表.Get-ChildItem是获取子项目的意思,可以获取一个目录下的文件和子目录. 在DOS系统下,我们想查看一个目录下有哪些子目录和文件,我们可以通过dir命令来实现.在PowerShell中,dir命令貌似仍然可用.但洪哥告诉你,这个dir已经不是cmd.exe中的那个dir了,它是Get-ChildItem这个cmdlet的别名.也就是说,使用Get-ChildItem和使用dir得到的效

  • PHP中执行cmd命令的方法

    本文介绍下,在php代码中执行cmd命令的方法,介绍下在php.ini文件中配置safe_mode参数支持命令执行的方法,有需要的朋友参考下. 说明: 本节内容在wamp包安装的环境实现. 首先,打开php.ini,关掉安全模式safe_mode = off,然后在看看 禁用函数列表 disable_functions = proc_open, popen, exec, system, shell_exec ,把exec去掉. php代码: 复制代码 代码如下: <?php exec("m

  • C#隐式运行CMD命令(隐藏命令窗口)

    本文实现了C#隐式运行CMD命令的功能.下图是实例程序的主画面.在命令文本框输入DOS命令,点击"Run"按钮,在下面的文本框中输出运行结果. 下面是程序的完整代码.本程序没有使用p.StandardOutput.ReadtoEnd()和p.StandardOutput.ReadLine()方法来获得输出,因为这些方法执行后画面容易卡死.而是通过调用异步方法BeginOutputReadLine来获取输出,并在事件p.OutputDataReceived的事件处理方法中来处理结果. u

  • PowerShell中使用Get-Alias命令获取cmdlet别名例子

    PowerShell中为了与原来的cmd命令保持兼容,特别为很多cmdlet设置了别名.这些别名跟cmd命令是同名的,但它代表着一个PowerShell中的cmdlet.比如dir这个cmd命令,它用于列出一个目录下的子文件夹和文件,在PowerShell有一个Get-ChildItem的cmdlet,它的作用也是列出一个目录下的子文件夹和文件,于是微软就给Get-ChildItem设置了一别名叫dir. 在PowerShell中,使用Get-Alias这个cmdlet,可以列出所有的别名,以及

  • PowerShell中Job相关命令及并行执行任务详解

    前言 在 PowerShell 中可以轻松的执行后台任务并且让多个后台任务并行执行.本文介绍 PowerShell 中 Job 相关的一些命令,并通过 demo 演示如何在后台同时执行多个任务.下面话不多说了,来一起看看详细的介绍吧. PowerShell 中执行后台任务的模式 下图描述了在 PowerShell 中执行后台任务的进程模型(此图来自互联网): 首先我们需要一个 PowerShell 进程执行与用户交互的命令,比如执行 Start-Job 命令运行一个后台任务.每一个这样的后台任务

  • C#中隐式运行CMD命令行窗口的方法

    MS的CMD命令行是一种重要的操作界面,一些在C#中不那么方便完成的功能,在CMD中几个简单的命令或许就可以轻松搞定,如果能在C#中能完成CMD窗口的功能,那一定可以使我们的程序简便不少. 下面介绍一种常用的在C#程序中调用CMD.exe程序,并且不显示命令行窗口界面,来完成CMD中各种功能的简单方法. 如下所示: 复制代码 代码如下: System.Diagnosties.Process p=new System.Diagnosties.Process(); p.StartInfo.FileN

  • 在PHP中运行Linux命令并启动SSH服务的例子

    升级 VPS 后,由于 Ubuntu 的 upstart 与 OpenVZ 的兼容问题,导致 sshd 服务不自动启动了,在尝试了 vePortal 的 console 与 file manager 及提交技术支持后都不能解决问题之后. 只能靠自己了,大概的思路是在 PHP 中进行 su 命令以执行 sshd 服务,因为 WordPress 还活着,并且可以在后台直接编辑主题相关的 PHP 脚本.只要把准备好的代码片断插入到 header.php 中,并在浏览器中访问一下主页即可. 相关的代码逻

  • Linux中使用top命令的技巧

    首先介绍top中一些字段的含义:  VIRT:virtual memory usage 虚拟内存 1.进程"需要的"虚拟内存大小,包括进程使用的库.代码.数据等 2.假如进程申请100m的内存,但实际只使用了10m,那么它会增长100m,而不是实际的使用量 RES:resident memory usage 常驻内存 1.进程当前使用的内存大小,但不包括swap out 2.包含其他进程的共享 3.如果申请100m的内存,实际使用10m,它只增长10m,与VIRT相反 4.关于库占用内

  • PowerShell中使用Out-String命令把对象转换成字符串输出的例子

    本文介绍在PowerShell中如何将cmdlet输出的对象,转换为string字符串类型,便于后期的处理. PowerShell中的cmdlet输出的结果都是以对象(Object)的形式存在的.对于Object类型,在后期处理时有利有弊,当然利大于弊.但某些时候,我们希望cmdlet输出的结果直接是字符串,那应该怎么来实现呢? PowerShell中提供了一个Out-String的cmdlet,来看看它的介绍:Out-String cmdlet 将 Windows PowerShell 管理的

随机推荐