PowerShell 技能连载 - 将机器加入域

以下是 PowerShell 将机器加入 AD 域的基本步骤:

1
2
3
4
5
6
7
8
9
10
11
12
# do not store passwords in production solutions,
# or you MUST control access permissions to this sensitive data
$username = "mydomain\UserName"
$password = 'Password' | ConvertTo-SecureString -AsPlainText -Force
$domainName = 'NameOfDomain'

# convert username and password to a credential
$cred = [PSCredential]::new($username, $password)
# join computer
Add-Computer -DomainName $domainName -Credential $cred
# restart computer
Restart-Computer

您可以根据需要修改这段代码。这个例子中用明文存储密码,这是不安全的。您可能需要从一个文件中读取密码。

PowerShell 技能连载 - 覆盖 Execution Policy 设置

如果 PowerShell 不允许执行脚本,您可能需要先允许脚本执行,例如:

1
Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy Bypass -Force

当 execution policy 是在组策略中定义时,这样操作不会起作用,因为组策略设置优先级更高:

1
2
3
4
5
6
7
8
9
PS C:\> Get-ExecutionPolicy -List

Scope ExecutionPolicy
----- ---------------
MachinePolicy Restricted
UserPolicy Undefined
Process Bypass
CurrentUser Bypass
LocalMachine Undefined

在这种情况下,您可以将 PowerShell 内置的授权管理器替换成一个新的。只需要运行以下代码,PowerShell 将总是允许在指定的会话中执行脚本:

1
2
3
$context = $executioncontext.gettype().getfield('_context','nonpublic,instance').getvalue($executioncontext);
$field = $context.gettype().getfield('_authorizationManager','nonpublic,instance');
$field.setvalue($context,(new-object management.automation.authorizationmanager 'Microsoft.PowerShell'))

PowerShell 技能连载 - 格式化文本输出

如果您希望将输出文本格式化漂亮,您可能需要用 PSCustomObject 并且将它输出为一个格式化的列表,例如:

1
2
3
4
5
6
7
$infos = [PSCustomObject]@{
Success = $true
Datum = Get-Date
ID = 123
}

Write-Host ($infos| Format-List | Out-String) -ForegroundColor Yellow

实际使用时只需要增加或者调整哈希表中的键即可。

PowerShell 技能连载 - 将用户名转换为 SID

以下代码演示了如何查找一个用户名的 SID:

1
2
$domain = 'MyDomain'
$username = 'User01'
1
2
3
$sid = (New-Object Security.Principal.NTAccount($domain, $username)).Translate([Security.Principal.SecurityIdentifier]).Value

$sid

只需要确保正确地调整了域名和用户名。如果您需要查看本地用户的 SID,只需要将域名设置为本地计算机的名称。

1
2
3
4
5
$username = 'Administrator'

$sid = (New-Object Security.Principal.NTAccount($env:computername, $username)).Translate([Security.Principal.SecurityIdentifier]).Value

$sid

这在 PowerShell 5 中更简单,因为有一个新的 Get-LocalUser cmdlet:

1
2
3
4
5
6
7
8
PS C:\> Get-LocalUser | Select-Object -Property Name, Sid

Name SID
---- ---
Administrator S-1-5-21-2951074159-1791007430-3873049619-500
CCIE S-1-5-21-2951074159-1791007430-3873049619-1000
DefaultAccount S-1-5-21-2951074159-1791007430-3873049619-503
Guest S-1-5-21-2951074159-1791007430-3873049619-501

PowerShell 技能连载 - 测试运行 PowerShell 6 - 并行运行

PowerShell 可以下载并和 Windows 官方的 PowerShell 并行运行。如果您想测试运行它,请访问 https://github.com/PowerShell/PowerShell/releases,并选择合适您平台的发布版本。

其注意要下载 50MB 内容。当解压/安装发行版之后,将会得到一个全黑的 PowerShell 图标,代表 PowerShell 6。文件名也改了:可执行文件名不再是 “powershell.exe” 而是 “pwsh.exe”。

PowerShell 技能连载 - 在 Grid View 窗口中垂直显示数据

Out-GridView 总是以每个对象一行的方式生成表格:

1
Get-Process -Id $pid | Out-GridView

有些时候,在 grid view 窗口中垂直显示对象属性,每个属性一行,更有用。

要做到这个效果,请看看 Flip-Object:这个函数输入对象,并将它们按每个属性分割成独立的键-值对象。它们可以通过管道导到 Out-GridView 中。通过这种方式,对象属性可以以更详细的方式查看:

1
Get-Process -Id $pid | Flip-Object | Out-GridView

以下是 Flip-Object 函数的实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
function Flip-Object
{
param
(
[Object]
[Parameter(Mandatory=$true, ValueFromPipeline=$true)]
$InputObject
)
process
{

$InputObject |
ForEach-Object {
$instance = $_
$instance |
Get-Member -MemberType *Property |
Select-Object -ExpandProperty Name |
ForEach-Object {
[PSCustomObject]@{
Name = $_
Value = $instance.$_
}
}
}

}
}

PowerShell 技能连载 - 将信息转换为区域性特定的文本

如果您希望将信息转换为指定的区域标准,那么可以轻松地用 ToString() 方法和合适的目标信息。

这个例子将短浅的日期和时间转换为法国的格式:

1
2
3
4
$date = Get-Date
$frenchCulture = New-Object -TypeName CultureInfo("fr")
$dateString = $date.ToString($frenchCulture)
$dateString

当您选择了泰国区域,您会注意到一个完全不同的年份,因为泰国使用不同的日历模型:

1
2
3
4
$date = Get-Date
$thaiCulture = New-Object -TypeName CultureInfo("th")
$dateString = $date.ToString($thaiCulture)
$dateString

当您选择了一个不同的区域,Windows 也会相应地翻译并显示月份和日期名称:

1
2
3
4
$date = Get-Date
$chineseCulture = New-Object -TypeName CultureInfo("zh")
$dateString = $date.ToString('dddd dd.MMMM yyyy',$chineseCulture)
$dateString

结果类似这样:

星期三 01.十一月 2017

PowerShell 技能连载 - 转换区域性特定的信息

假设您以文本的形式收到了数字或日期等数据。当信息转为文本的时候,您会遇到区域性特定的格式:不同区域的小数点和日期时间可能会不同。

以下是一个如何解析数据的简单例子,假设您知道它的来源区域信息:

1
2
3
4
5
6
# number in German format
$info = '1,2'

# convert to real value
$culture = New-Object -TypeName CultureInfo("de")
$number = [Double]::Parse($info,$culture)

每一个目标类型有一个 Parse() 方法,所以如果您收到一个日期和/或时间信息,您可以将它如此简单地转换它。这个例子输入的是以法国标准格式化的日期和时间,并返回一个真正的 DateTime 对象:

1
2
3
4
5
6
7
# date and time in French format:
$info = '01/11/2017 16:28:45'

# convert to real value
$culture = New-Object -TypeName CultureInfo("fr")
$date = [DateTime]::Parse($info,$culture)
$date

PowerShell 技能连载 - 理解文本转换

有许多方法能将对象转换为文本。如果您在某些情况下弄糊涂了,这篇文章能帮您快速搞清。请看:

有三个基础的将对象转换为文本的方法。

1
2
3
4
5
6
7
$a = 4.5
# simple conversion
$a.ToString()
# slightly better conversion
"$a"
# richest conversion
$a | Out-String

对于简单对象,三个方法的结果不会有差别。然而,对于更复杂的对象,结果差异可能很大。请看一下数组:

1
2
3
4
5
6
7
$a = 1,2,3

$a.ToString()

"$a"

$a | Out-String

并且看看复杂对象如何转换为文本:

1
2
3
4
5
6
7
$a = Get-Process

$a.ToString()

"$a"

$a | Out-String

PowerShell 技能连载 - 强制允许 PowerShell 脚本执行

执行策略 (Execution Policy) 可以禁止脚本执行。它被设计成一个用户的首选项,所以您总是可以改变有关的执行策略。不过,在一些环境下,组策略可以强制改变设置,并且禁止运行脚本。

在这种情况下,您可以考虑重置内部的 PowerShell 授权管理。将它替换为一个缺省的实例以后,您可以忽略之前的执行策略设置,执行 PowerShell 脚本:

1
$context = $executioncontext.gettype().getfield('_context','nonpublic,instance').getvalue($executioncontext); $field = $context.gettype().getfield('_authorizationManager','nonpublic,instance'); $field.setvalue($context,(New-Object management.automation.authorizationmanager 'Microsoft.PowerShell'))

请注意,这不是一个安全问题。执行策略的控制权在用户。这并不是一个安全边界。