PowerShell 技能连载 - 创建文件共享
在 Server 2012 R2 和 Windows .1 中,有许多有用的新模块,包含了许多新的 cmdlet,例如 New-SmbShare
可以快速地创建新的文件共享。
如果您没有这些 cmdlet,您通常可以使用 WMI。那需要更多的研究和搜索,但是一旦您有了一个代码模板,它就能很好地工作了。
例如要以管理员身份创建一个新的文件共享,试试以下代码:
1 | $share = [wmiclass]"Win32_Share" |
在 Server 2012 R2 和 Windows .1 中,有许多有用的新模块,包含了许多新的 cmdlet,例如 New-SmbShare
可以快速地创建新的文件共享。
如果您没有这些 cmdlet,您通常可以使用 WMI。那需要更多的研究和搜索,但是一旦您有了一个代码模板,它就能很好地工作了。
例如要以管理员身份创建一个新的文件共享,试试以下代码:
1 | $share = [wmiclass]"Win32_Share" |
昨天我们看了自定义作用域能够自动还原变量并在您的代码之后清除现场。
自定义作用域也可以用来忽略域里任何一段代码输出的任何结果。要实现它,请使用这样的解构:$null = .{[code]}
。无论您在方括号里执行什么代码,您创建的所有的变量和函数在域外都能使用,但是不会产生任何输出。
让我们看看这个函数:
1 | function Out-Voice ($Text) |
当你运行它时,它将能播放语音,但也输出了数字“1”。所以 Speak()
方法会造成这样的现象——当您的代码变得庞大而复杂时,有许多地方在输出不必要的数字。
以下是一个极简单的“补丁”函数能产生相同的小郭,但是保证不会返回任何值:
1 | function Out-Voice ($Text) |
当您改变变量时,您可能需要在稍后清除它们并且确保它们回退到缺省值——用自定义作用域就可以做到。昨天,我们学习了如何处理控制台程序的错误。并且回顾那段代码,您会发现重置 $ErrorActionPreference
系统变量要费很多事:
1 | try |
一个简单得多的办法是使用自定义作用域:
1 | & { |
${[code]}
这段代码创建了一个新的作用域,并且任何在其中定义的变量都会在退出该作用域时删除。这是为何在上述例子中,$ErrorActionPreference
能够自动还原为它之前的值。
是否想知道如何捕获 native 控制台 EXE 程序的错误?PowerShell 的错误处理器只能处理 .NET 代码的错误。
这段代码是捕获控制台应用程序错误的框架:
1 | try |
一旦控制台程序发出一个错误,它就会输出到控制台的 #2 通道。由于示例代码中该通道直接重定向到普通的 output,所以 PowerShell 能接收到它。当 ErrorActionPreference
设成 “Stop
“ 时,PowerShell 会将任何该通道的输入数据转发到一个 .NET RemoteException
,这样您就可以捕获它。
1 | WARNING: The user name could not be found. |
在处理错误时,您有时会希望将原始的异常替换成您自己的。以下是一个例子:
1 | function Do-Something |
调用者看到的内容如下:
1 | PS C:\> Do-Something |
如果调用者也用一个错误处理函数来接收它,则会出现这种情况:
1 | try |
结果看起来如下:
1 | Message Originalmessage |
这样调用者可以看到返回的错误信息,并且经过内部处理之后,还可以传递原始的错误信息。
假设您想以不同的身份打开多个 PowerShell 控制台,或以其他人的身份打开任何程序。
要实现这个目标,您需要以其他人的身份登录,这很明显是个负担。以下是将凭据以安全的方式保存到文件的方法:密码采用您的身份和您的机器加密成密文。只有保存它们的那个人可以取回它,而且只能在保存该文件的机器上操作:
1 | # saving credential securely to file |
这个凭据将保存到用户配置中。如果您希望保存到其它地方,请改变路径。喜欢保存多少份,就调用多少次该方法。
下一步,假设您加载了一个保存的凭据,并且使用该身份启动了一个程序:
1 | # getting back saved credential |
这将以您之前指定的用户身份创建一个新的 PowerShell 实例——无需手动登录。
PowerShell 同时有五个主要版本在发行。除掉最新的小版本,例如 Windows 10 和 Server 2016 上的 PowerShell 5.1。加上 beta 版和预发行版本,以及 Linux 和 Nano 服务器上的 PowerShell。哇哦!
要跟踪这些版本,并知道正在用哪个版本、它从哪里来、可能有哪些兼容性问题很不容易。MVP 大学里的 Egil Ring 维护着一个很酷的模块。如果您装了 PowerShell 5 或从 powershellgallery.com 安装了 PowerShellGet,您可以用一行代码下载这个模块:
1 | PS C:\> Install-Module -Name PSVersion -Scope CurrentUser |
回答几个问题后,该模块安装完成。它只包含两个命令:
1 | PS C:\> Get-Command -Module PSVersion |
PSVersion 是一个社区项目,跟踪 PowerShell 的发行编号、它们的含义、它们的来源:
1 | PS C:\> Get-PSVersion -ListVersion |
这是在您的企业中以友好的 PowerShell 版本名称获得 PowerShell 版本号的方法:
1 | PS C:\> Get-PSVersion |
使用 Update-Help
下载 PowerShell 的帮助文件时,PowerShell 5 有一个 bug,目前可以修复:基于文本的帮助文件扩展名是“.txt”而不是“.help.txt”,所以 PowerShell 帮助系统会忽略它们。您可以自己试验一下——以下命令可能会返回一大堆关于主题:
1 | PS C:\> Get-Help about* |
如果没有显示上述的内容,您也许还没有事先运行过 Update-Help
来下载帮助文件,或者您被 bug 吃了。
无论这个 bug 是否正在修复中,用 PowerShell 您可以轻松地修改这些东西。以下是一个用于修复这些受影响的帮助文件的扩展名的脚本。
这个脚本需要管理员权限,因为帮助文件是位于受保护的 Windows 文件夹中:
1 | # find all text files inside the PowerShell folder that start |
当您创建 PowerShell 函数时,参数可以是命名的也可以是按位置的。以下是一个例子:
如果您想检测文件系统中的非法字符,以下是一个简单的适配:
1 | function Test-Command |
如您所见,使用按位置的参数(只需要指定参数,不需要显式地指定参数名)可能更适用于为特定目的编写的代码,但是可读性更差。这是有可能的,因为上述函数的语法看起来如下:
1 | Test-Command [[-Name] <string>] [[-Id] <int>] |
那么一个编写一个效果相反的 PowerShell 函数,实现这种语法呢:
1 | Test-Command [-Name <string>] [-Id <int>] [<CommonParameters>] |
目前这个方法比较生僻,不过是完全可行的:
1 | function Test-Command |
一旦开始使用参数集合,缺省情况下所有参数都是命名的参数。
当您创建一个 PowerShell 函数时,所有参数都有默认的位置,除非人为地加上“Position
”属性。一旦加上这个属性,所有不带“Position
”的参数将立刻变为命名的必须参数。让我们看看例子:
这是一个经典的函数定义,创建了三个固定位置的参数:
1 | function Test-Command |
语法如下:
1 | Test-Command [[-Name] <string>] [[-ID] <int>] [[-Email] <string>] |
一旦您在任何一个参数上添加“Position
”属性,其它的就变为命名的参数:
1 | function Test-Command |
以下是它的语法:
1 | Test-Command [[-Name] <string>] [[-ID] <int>] [-Email <string>] [<CommonParameters>] |
区别在哪?您不需要指定参数名 -Name
和 -ID
,但如果您希望为第三个参数指定一个值,必须指定 -Email
。在第一个例子中,所有三个参数都可以按照位置来定位。