PowerShell 技能连载 - 当前用户的 SID
以下是一行返回当前用户 SID 并且可以用于登录脚本的代码,例如:
1 | ([System.Security.Principal.WindowsIdentity]::GetCurrent()).User.Value |
以下是一行返回当前用户 SID 并且可以用于登录脚本的代码,例如:
1 | ([System.Security.Principal.WindowsIdentity]::GetCurrent()).User.Value |
以下是一个扫描本地或远程系统端口的一个直接的方法。您甚至可以指定一个超时值(以毫秒为单位):
1 | function Get-PortInfo |
扫描端口现在变得十分简单:
1 | PS> Get-PortInfo -Port 139 -TimeoutMilliseconds 1000 |
在 PowerShell 控制台里很容易把控制台颜色搞乱。一个不经意的调用意外地改变了颜色值,或者脚本错误地设置了颜色,可能会导致意外的结果。要验证这种情况,请打开一个 PowerShell 控制台(不是编辑器!),并且运行这段代码:
1 | PS> [Console]::BackgroundColor = "Green" |
要快速地清除颜色,请运行这段代码:
1 | PS> [Console]::ResetColor() |
接着运行 Clear-Host
可以清空显示。
有些时候当您尝试连接 WEB 服务时,PowerShell 可能会弹出无法设置安全的 SSL 通道提示。
让我们来深入了解一下这个问题。以下是一段调用德国铁路系统 WEB 服务的代码。它应该返回指定城市的火车站列表:
1 | $city = "Hannover" |
不过,它弹出了一系列关于 SSL 连接问题的异常。通常,这些错误源于两种情况:
要解决这些情况,只需要运行以下代码:
1 | # ignore invalid SSL certificates |
只要执行一次,对当前的 PowerShell 会话都有效。以上代码现在能够正常返回 Hannover 地区的车站信息。而且如果深入地了解该对象的模型,您甚至可以通过 PowerShell 订火车票。
name nummer
---- ------
Hannover Hbf 8000152
Hannover-Linden/Fi. 8002586
Hannover-Nordstadt 8002576
Hannover Bismarckstr 8002580
Hannover-Ledeburg 8002583
Hannover-Vinnhorst 8006089
Hannover-Leinhausen 8002585
Hannover Wiech-Allee 8002591
Hannover Ander.Misb. 8000578
Hannover Flughafen 8002589
Hannover-Kleefeld 8002584
Hannover-Bornum 8002581
Hann Münden 8006707
HannoverMesseLaatzen 8003487
如果您正在将日志活动写入文件,可能需要清除一些东西,例如在增加一个新文件的时候总是需要删除最旧的日志文件。
以下是一个简单的实现:
1 | # this is the folder keeping the log files |
如果只希望保留最新的 5 个文件,请像这样更改:
1 | # this is the folder keeping the log files |
传统的 foreach
循环是最快速的循环方式,但是它有一个严重的限制。foreach
循环不支持管道。用户只能等待整个 foreach
循环结束才能处理结果。
以下是一些演示这个情况的示例。在以下代码中,您需要等待一段很长的时间才能“看见”执行结果:
1 | $result = foreach ($item in $elements) |
您无法直接通过管道输出结果。以下代码会产生语法错误:
1 | $elements = 1..100 |
可以使用 $()
语法来使用管道,但是仍然要等待循环结束并且将整个结果作为一个整体发送到管道:
1 | $elements = 1..100 |
一下是一个鲜为人知的技巧,向 foreach
循环增加实时流功能:只需要使用一个脚本块!
1 | $elements = 1..100 |
现在您可以“看到”它们处理的结果,并且享受实时流的效果。
让然,您可以一开始就不使用 foreach
,而是使用 ForEach-Object
管道 cmdlet 来代替:
1 | $elements = 1..100 |
但是,ForEach-Object
比 foreach
关键字慢得多,并且有些场景无法使用 ForEach-Object
。例如,在许多数据库代码中,代码需要一次次地检测结束标记,所以无法使用 ForEach-Object
。
有着许多方法可以创建网络驱动器的列表。其中一个需要调用 COM 接口。这个接口也可以通过 VBScript 调用。我们将利用它演示一个特殊的 PowerShell 技术。
要列出所有网络驱动器,只需要运行这几行代码:
1 | $obj = New-Object -ComObject WScript.Network |
结果类似这样:
1 | PS> $obj.EnumNetworkDrives() |
这个方法对每个网络驱动器返回两个字符串:挂载的驱动器号,以及原始 URL。要将它转为有用的东西,您需要创建一个循环,每次迭代返回两个元素。
以下是一个聪明的方法来实现这个目标:
1 | $obj = New-Object -ComObject WScript.Network |
在 foreach
循环中,有一个很少人知道的自动变量,名为 $foreach
,它控制着迭代。当您调用 MoveNext()
方法时,它对整个集合迭代,移动到下一个元素。通过 Current
属性,可以读取到迭代器的当前值。
通过这种方法,循环每次处理两个元素,而不仅仅是一个。两个元素合并为一个自定义对象。结果看起来类似这样:
DriveLetter UNCPath
----------- -------
X: \\storage4\data
Z: \\127.0.0.1\c$
您可以用 Send-MailMessage
通过任何 SMTP 服务器放松右键。不过,如果您希望使用 Outlook 客户端,例如要访问地址簿、使用公司的 Exchange 服务器,或者将邮件保存到邮件历史中,那么可以通过这个快速方法来实现:
1 | function Send-OutlookMail |
这只是一个基本的模板,您可以投入一些时间使它变得更好。例如,当前版本总是需要一个附件。在更复杂的版本中,您可以使附件变成可选的,并且支持多个附件。或者寻找一种方法发送邮件而不需要用户交互。
修饰一段文本并不太简单,如果您希望名字或者文本格式正确,并且每个单词都以大写开头,那么工作量通常很大。
有趣的是,每个 CultureInfo
对象有一个内置的 ToTitleCase()
方法,可以完成上述工作。如果您曾经将纯文本转换为全部消协,那么它也可以处理所有大写的单词:
1 | $text = "here is some TEXT that I would like to title-case (all words start with an uppercase letter)" |
以下是执行结果:
Here Is Some TEXT That I Would Like To Title-Case (All Words Start With An Upper Letter
Here Is Some Text That I Would Like To Title-Case (All Words Start With An Upper Letter
This method may be especially useful for list of names.
这个方法对于姓名列表很有用。
假设一个脚本已经向某个文件夹写入了多个日志文件,所有文件名都为 *.log。您可能希望将它们合并为一个大文件。以下是一个简单的实践:
1 | $OutPath = "$env:temp\summary.log" |
然而,这个方法并不能提供充分的控制权:所有文件需要放置在同一个文件夹中,并且必须有相同的文件扩展名,而且您无法控制它们合并的顺序。
一个更多功能的方法类似这样:
1 | $OutPath = "$env:temp\summary.log" |
它利用了 Get-ChildItem
的灵活性,而且可以在读取内容之前对文件排序。通过这种方法,日志保持了顺序,并且最终的日志信息总是在日志文件的最上部。