PowerShell 技能连载 - 显示 Path 环境变量
当您启动一个程序时,$env:Path
环境变量列出了 Windows 搜索路径中的所有目录。类似地,$env:PSModulePath
列出了 PowerShell 搜索 PowerShell 模块(包括它的自动加载模块)的所有目录。
这些变量包含了以分号分隔的信息。所以使用 -split
操作符分隔并显示它们:
顺便说一下,第三行(在 Program Files 中的)是在 PowerShell 4.0 中才加入的。
当您启动一个程序时,$env:Path
环境变量列出了 Windows 搜索路径中的所有目录。类似地,$env:PSModulePath
列出了 PowerShell 搜索 PowerShell 模块(包括它的自动加载模块)的所有目录。
这些变量包含了以分号分隔的信息。所以使用 -split
操作符分隔并显示它们:
顺便说一下,第三行(在 Program Files 中的)是在 PowerShell 4.0 中才加入的。
要查看磁盘分区信息,请使用 WMI:
Get-WmiObject -Class Win32_DiskPartition |
Select-Object -Property *
然后,选择您感兴趣的属性,然后将 *
号替换成逗号分隔的属性列表。例如:
Get-WmiObject -Class Win32_DiskPartition |
Select-Object -Property Name, BlockSize, Description, BootPartition
如果您选择四个或四个以下的属性,结果是一个干净的表格,否则将是一个列表:
如果您想知道更多的信息,请使用 -List
参数来搜索其它 WMI 类,或者和 “disk” 有关的,或者其它完全不相关的:
编写 Active Directory 脚本不需要额外的 module。通过简单的 .NET 框架方法,您可以实现令人惊叹的功能。实际上,这个技术十分强大,您不应该在您的生产环境下运行以下的例子,除非您知道自己在做什么。
一下代码片段在您的 Active Directory 中查找存储于 CN=Users
并且没有邮箱地址的的所有用户。然后,脚本将为他们设置一个缺省的邮箱地址。该地址由姓名 + “mycompany.com” 组成。
# adjust LDAP path (i.e. remove CN=Users to search the entire domain):
$SearchRoot = 'LDAP://CN=Users,{0}' -f ([ADSI]'').distinguishedName.ToString()
# adjust LDAPFilter. Example: (!mail=*) = all users with no defined mail attribute
$LdapFilter = "(&(objectClass=user)(objectCategory=person)(!mail=*))"
$Searcher = New-Object DirectoryServices.DirectorySearcher($SearchRoot, $LdapFilter)
$Searcher.PageSize = 1000
$Searcher.FindAll() | ForEach-Object {
$User = $_.GetDirectoryEntry()
try
{
# Set mail attribute
$User.Put("mail", ('{0}.{1}@mycompany.com' -f $user.givenName.ToString(), $user.sn.ToString()))
# Commit the change
$User.SetInfo()
}
catch { Write-Warning "Problems with $user. Reason: $_" }
}
这个示例代码可以读取并且修改、设置任意的属性。它特别适用于不能通过 cmdlet 设置的自定义属性。
借助 WPF,PowerShell 用几行代码就可以创建窗口。以下是一个有趣的关于透明屏幕覆盖层的例子。
您可以调用 Lock-Screen
并且传入一个脚本块和一个标题。PowerShell 将会用它的覆盖层锁定屏幕,再次执行代码将解锁。
function Lock-Screen([ScriptBlock] $Payload={Start-Sleep -Seconds 5}, $Title='Busy, go away.')
{
try
{
$window = New-Object Windows.Window
$label = New-Object Windows.Controls.Label
$label.Content = $Title
$label.FontSize = 60
$label.FontFamily = 'Consolas'
$label.Background = 'Transparent'
$label.Foreground = 'Red'
$label.HorizontalAlignment = 'Center'
$label.VerticalAlignment = 'Center'
$Window.AllowsTransparency = $True
$Window.Opacity = .7
$window.WindowStyle = 'None'
$window.Content = $label
$window.Left = $window.Top = 0
$window.WindowState = 'Maximized'
$window.Topmost = $true
$null = $window.Show()
Invoke-Command -ScriptBlock $Payload
}
finally { $window.Close() }
}
$job =
{
Get-ChildItem c:\windows -Recurse -ErrorAction SilentlyContinue
}
Lock-Screen -Payload $job -Title 'I am busy, go away and grab a coffee...'
您很快就会发现,锁屏确实可以防止鼠标点击,但是并不会屏蔽按键。这是一个有趣的技术,不是绝对安全的锁定。
以下是一些为您创建不同长度随机密码的代码:
$length = 8
$characters = [Char[]]((31..50) + (65..90) + (97..122))
$characters = $characters -ne 'O' -ne 'o' -ne 'l' -ne '1' -ne '-'
$password = -join ($characters | Get-Random -Count $length)
"Your temporary $length-character-password is $password"
您的密码长度通过 $length
变量设置。用于构成密码的字符集存放在 $characters
变量中。缺省情况下使用 ASCII 编码为 31-50、65-90、97-122 的所有字符。如您所见,通过 -ne
操作符,您可以调整列表和排除字符。在我们的例子中,我们排除了容易拼写错的字母。
您有没有办法安全地将机密的密码包含在 PowerShell 脚本中?您肯定不敢。但您可以使得别人更难以获取到秘密的信息。
以下是一个设计成在 PowerShell ISE 编辑器中使用的代码生成器脚本:
# ask for credentials
$cred = Get-Credential
$pwd = $cred.Password
$user = $cred.UserName
# create random encryption key
$key = 1..32 | ForEach-Object { Get-Random -Maximum 256 }
# encrypt password with key
$pwdencrypted = $pwd | ConvertFrom-SecureString -Key $key
# turn key and password into text representations
$secret = -join ($key | ForEach-Object { '{0:x2}' -f $_ })
$secret += $pwdencrypted
# create code
$code = '$i = ''{0}'';' -f $secret
$code += '$cred = New-Object PSCredential('''
$code += $user + ''', (ConvertTo-SecureString $i.SubString(64)'
$code += ' -k ($i.SubString(0,64) -split "(?<=\G[0-9a-f]{2})(?=.)" |'
$code += ' % { [Convert]::ToByte($_,16) })))'
# write new script
$editor = $psise.CurrentPowerShellTab.files.Add().Editor
$editor.InsertText($code)
$editor.SetCaretPosition(1,1)
当您运行它的时候,它将询问用户输入一个用户名和密码。然后,它将会生成一段加密的 PowerShell 脚本片段。您可以在您的脚本中使用它。
以下是由以上脚本生成的一段加密的脚本片段:
$i = '73cc7284f9e79f68e9d245b5b2d96c4026397d96cfac6023325d1375414e5f7476492d1116743f0423413b16050a5345MgB8AGgAdABLAEkARABiAFIARgBiAGwAZwBHAHMAaQBLAFoAeQB2AGQAOQAyAGcAPQA9AHwAMgBiADIAMABmADYANwA1ADYANwBiAGYAYwA3AGMAOQA0ADIAMQA3ADcAYwAwADUANAA4ADkAZgBhADYAZgBkADkANgA4ADMAZAA5ADUANABjADgAMgAwADQANQA1ADkAZAA3AGUAMwBmADMAMQAzADQAZgBmADIAZABlADgAZQA=';$cred = New-Object PSCredential('contoso\fabrikam', (ConvertTo-SecureString $i.SubString(64) -k ($i.SubString(0,64) -split "(?<=\G[0-9a-f]{2})(?=.)" | % { [Convert]::ToByte($_,16) })))
这段自动生成的加密脚本片段将会定义一个 $cred
变量,用于保存包括密码在内的合法凭据。接下来您可以将 $cred
变量传递给您脚本中任何需要用户和密码的 -Credential
参数。
问了让您的脚本增加一些魅力,以下几行代码可以显示一个文件夹选择对话框。当用户选择了一个文件夹,您的脚本可以接收到选择的结果并且可以获得选择的路径:
Add-Type -AssemblyName System.Windows.Forms
[System.Windows.Forms.Application]::EnableVisualStyles()
$FolderBrowser = New-Object System.Windows.Forms.FolderBrowserDialog
$null = $FolderBrowser.ShowDialog()
$Path = $FolderBrowser.SelectedPath
"You selected: $Path"
请注意前两行:当您在 ISE 编辑器中运行代码时不需要它们,但当您从 powershell.exe 中运行代码时需要它们。所以我们保留着两行来确保您的代码在各个 PowerShell 宿主中都能有效运行。
您知道吗?Group-Object
可以方便地以自定义的规则来对元素分组。以下通过简单的一行代码实现根据前三个字母对文件夹分组:
Get-ChildItem -Path C:\Windows -Directory |
Group-Object -Property { $_.Name.PadRight(3).Substring(0,3)}
稍微做一些额外的改动,您可以以这三个首字母做为键,创建一个哈希表:
$lookup = Get-ChildItem -Path $env:windir -Directory |
Group-Object -Property { $_.Name.PadRight(3).Substring(0,3).ToUpper()} -AsHashTable -AsString
$lookup.Keys
现在我们可以很容易地取得其中的文件夹,比如说我们要取以“SYS”开头的文件夹:
PS C:\Windows\System32> $lookup.SYS
目录: C:\Windows
Mode LastWriteTime Length Name
---- ------------- ------ ----
d---- 2013/9/24 21:50 System
d-r-- 2013/12/8 13:40 System32
d---- 2013/8/22 23:36 SystemResources
d---- 2013/12/5 11:29 SysWOW64
这有什么实用价值呢?有些公司使用文件夹前缀作为业务单元。用上这个技术之后,我们可以很容易地把所有的业务单元文件夹“收拢”起来——您可以秒杀地计算它们的存储容量并且创建一个自动化的报表。
您知道吗?Windows 维护着一个关于所有插入过您机器中的 USB 存储设备列表。要导出这个列表十分简单:
$Path = 'HKLM:\SYSTEM\CurrentControlSet\Enum\USBSTOR\*\*'
Get-ItemProperty -Path $Path |
Select-Object -Property FriendlyName, CompatibleIDs, Mfg
结果看起来如下:
FriendlyName CompatibleIDs Mfg
------------ ------------- ---
SCANNER USB Device {USBSTOR\Disk, USBSTOR\RAW, GenDisk} @disk.inf,%genmanufacturer%;(Standard d...
Android UMS Composite USB Device {USBSTOR\Disk, USBSTOR\RAW, GenDisk} @disk.inf,%genmanufacturer%;(Standard d...
Android UMS Composite USB Device {USBSTOR\Disk, USBSTOR\RAW, GenDisk} @disk.inf,%genmanufacturer%;(Standard d...
Generic Flash Disk USB Device {USBSTOR\Disk, USBSTOR\RAW, GenDisk} @disk.inf,%genmanufacturer%;(Standard d...
Hitachi HTS545050B9A300 USB Device {USBSTOR\Disk, USBSTOR\RAW, GenDisk} @disk.inf,%genmanufacturer%;(Standard d...
Landi A015 USB Device {USBSTOR\Disk, USBSTOR\RAW, GenDisk} @disk.inf,%genmanufacturer%;(Standard d...
Landi A015 USB Device {USBSTOR\Disk, USBSTOR\RAW, GenDisk} @disk.inf,%genmanufacturer%;(Standard d...
Landi A015 USB Device {USBSTOR\Disk, USBSTOR\RAW, GenDisk} @disk.inf,%genmanufacturer%;(Standard d...
Linux File-CD Gadget USB Device {USBSTOR\Disk, USBSTOR\RAW, GenDisk} @disk.inf,%genmanufacturer%;(Standard d...
Linux File-CD Gadget USB Device {USBSTOR\Disk, USBSTOR\RAW, GenDisk} @disk.inf,%genmanufacturer%;(Standard d...
Linux File-CD Gadget USB Device {USBSTOR\Disk, USBSTOR\RAW, GenDisk} @disk.inf,%genmanufacturer%;(Standard d...
Linux File-CD Gadget USB Device {USBSTOR\Disk, USBSTOR\RAW, GenDisk} @disk.inf,%genmanufacturer%;(Standard d...
Multiple Card Reader USB Device {USBSTOR\Disk, USBSTOR\RAW, GenDisk} @disk.inf,%genmanufacturer%;(Standard d...
SAMSUNG GT-I9000 USB Device {USBSTOR\Disk, USBSTOR\RAW, GenDisk} @disk.inf,%genmanufacturer%;(Standard d...
SAMSUNG GT-I9000 Card USB Device {USBSTOR\Disk, USBSTOR\RAW, GenDisk} @disk.inf,%genmanufacturer%;(Standard d...
SAMSUNG GT-I9000 Card USB Device {USBSTOR\Disk, USBSTOR\RAW, GenDisk} @disk.inf,%genmanufacturer%;(Standard d...
Ut165 USB Flash Disk USB Device {USBSTOR\Disk, USBSTOR\RAW, GenDisk} @disk.inf,%genmanufacturer%;(Standard d...
WD Elements 1042 USB Device {USBSTOR\Disk, USBSTOR\RAW, GenDisk} @disk.inf,%genmanufacturer%;(Standard d...
列表越长,说明您的计算机插入过越多种不同的 USB 存储设备。
是否需要获取一个 DLL 文件列表以及它们的版本信息?Get-ChildItem
可以为您获取这些信息。您只需要解开其中的一些属性,例如:
Get-ChildItem c:\windows\system32\*.dll |
Select-Object -ExpandProperty VersionInfo |
Select-Object -Property FileName, Productversion, ProductName
以上实际上将原始的 FileInfo
对象替换(-ExpandProperty
)成了 VersionInfo
对象。您所做的大概是将一个对象转换成另一个对象,并且丢掉前者的一部分信息。例如,您无法再存取某些属性,如 LastWriteTime
等。
如果您希望保持原有的 FileInfo
对象,但是为它加入某些额外的信息,那么请像这样使用 Add-Member
:
Get-ChildItem c:\windows\system32\*.dll |
Add-Member -MemberType ScriptProperty -Name Version -Value {
$this.VersionInfo.ProductVersion
} -PassThru |
Select-Object -Property LastWriteTime, Length, Name, Version |
Out-GridView
“$this”是您需要扩展的对象。