PowerShell 技能连载 - 探索函数源码

在 PowerShell 中,cmdlet 和 function 的唯一根本区别是它们是怎么编程的:函数用的是纯粹的 PowerShell 代码,这也是查看它们的源代码,并学习新东西的有趣之处。

这行代码列出所有当前从 module 中加载的所有 PowerShell function:

1
Get-Module | ForEach-Object { Get-Command -Module $_.Name -CommandType Function }

一旦您知道了内存中某个函数的名字,可以用这种方法快捷查看它的源代码。在这些例子中,我们将探索 Format-Hex 函数。只需要将这个名字替换成内存中存在的其它函数名即可:

1
${function:Format-Hex} | clip.exe

这行代码将源代码存入剪贴板,您可以将它粘贴到您喜欢的编辑器中。另外,您也可以用这种方式运行:

1
2
3
Get-Command -Name Format-Hex -CommandType Function |
Select-Object -ExpandProperty Definition |
clip.exe

PowerShell 技能连载 - 在同一台机器上运行 32 位代码

如果您需要在 64 位脚本中运行 32 位 PowerShell 代码,假设您是管理员,并且使用远程操作功能,您可以远程操作您的系统:

1
2
3
4
5
6
7
$code = {
[IntPtr]::Size
Get-Process
}


Invoke-Command -ScriptBlock $code -ConfigurationName microsoft.powershell32 -ComputerName $env:COMPUTERNAME

这将在 32 位环境中运行 $code 中的脚本块。该指针返回的 size 是 4,这是 32 位的证据。当您直接运行脚本块,返回的是 8 字节(64 比特)。

PowerShell 技能连载 - systeminfo.exe 的最新替代

曾几何时,systeminfo.exe 返回一台电脑所有的分析信息,并且有一些能够在 PowerShell 中变成面向对象的:

PS C:\> $info = systeminfo.exe /FO CSV | ConvertFrom-Csv

PS C:\> $info.Domain
WORKGROUP

PS C:\> $info.'Logon Server'
\\DESKTOP-7AAMJLF

在 PowerShell 5.1 (Windows 10 和 Server 2016 )中,有一个现代的替代品:

PS C:\> Get-ComputerInfo


WindowsBuildLabEx                                       : 14393.321.amd64fre.rs1_release_inmarket.161004-2338
WindowsCurrentVersion                                   : 6.3
WindowsEditionId                                        : Professional
WindowsInstallationType                                 : Client
WindowsInstallDateFromRegistry                          : 8/17/2016 1:40:27 PM
WindowsProductId                                        : 00350-50721-50845-ACOEM
WindowsProductName                                      : Windows 10 Pro
WindowsRegisteredOrganization                           :
WindowsRegisteredOwner                                  : topoftheworld
WindowsSystemRoot                                       : C:\WINDOWS
BiosCharacteristics                                     : {7, 9, 11, 12...}
BiosBIOSVersion                                         : {DELL   - 1072009, 1.4.4, American Megatrends - 5000B}
BiosBuildNumber                                         :
BiosCaption                                             : 1.4.4
BiosCodeSet                                             :
BiosCurrentLanguage                                     : en|US|iso8859-1
BiosDescription                                         : 1.4.4
BiosEmbeddedControllerMajorVersion                      : 255
BiosEmbeddedControllerMinorVersion                      : 255
BiosFirmwareType                                        : Uefi
BiosIdentificationCode                                  :
BiosInstallableLanguages                                : 2
BiosInstallDate                                         :
BiosLanguageEdition                                     :
BiosListOfLanguages                                     : {en|US|iso8859-1, }
BiosManufacturer                                        : Dell Inc.
BiosName                                                : 1.4.4
BiosOtherTargetOS                                       :
BiosPrimaryBIOS                                         : True
BiosReleaseDate                                         : 6/14/2016 2:00:00 AM
BiosSeralNumber                                         : DLGQD72
BiosSMBIOSBIOSVersion                                   : 1.4.4
BiosSMBIOSMajorVersion                                  : 2
BiosSMBIOSMinorVersion                                  : 8
BiosSMBIOSPresent                                       : True
BiosSoftwareElementState                                : Running
BiosStatus                                              : OK
BiosSystemBiosMajorVersion                              : 1
BiosSystemBiosMinorVersion                              : 4
BiosTargetOperatingSystem                               : 0
BiosVersion                                             : DELL   - 1072009
CsAdminPasswordStatus                                   : Unknown
CsAutomaticManagedPagefile                              : True
CsAutomaticResetBootOption                              : True
CsAutomaticResetCapability                              : True
CsBootOptionOnLimit                                     :
CsBootOptionOnWatchDog                                  :
CsBootROMSupported                                      : True
CsBootStatus                                            : {0, 0, 0, 0...}
CsBootupState                                           : Normal boot
CsCaption                                               : CLIENT
CsChassisBootupState                                    : Safe
CsChassisSKUNumber                                      : Laptop
CsCurrentTimeZone                                       : 120
CsDaylightInEffect                                      : True
CsDescription                                           : AT/AT COMPATIBLE
CsDNSHostName                                           : DESKTOP-7AAMJLF
CsDomain                                                : WORKGROUP
CsDomainRole                                            : StandaloneWorkstation
CsEnableDaylightSavingsTime                             : True
CsFrontPanelResetStatus                                 : Unknown
CsHypervisorPresent                                     : False
CsInfraredSupported                                     : False
CsInitialLoadInfo                                       :
CsInstallDate                                           :
CsKeyboardPasswordStatus                                : Unknown
CsLastLoadInfo                                          :
CsManufacturer                                          : Dell Inc.
CsModel                                                 : XPS 13 9350
CsName                                                  : CLIENT
CsNetworkAdapters                                       : {WiFi, Bluetooth-Netzwerkverbindung}
CsNetworkServerModeEnabled                              : True
CsNumberOfLogicalProcessors                             : 4
CsNumberOfProcessors                                    : 1
CsProcessors                                            : {Intel(R) Core(TM) i7-6500U CPU @ 2.50GHz}
CsOEMStringArray                                        : {Dell System, 1[0704], 3[1.0], 12[www.dell.com]...}
CsPartOfDomain                                          : False
CsPauseAfterReset                                       : -1
CsPCSystemType                                          : Mobile
CsPCSystemTypeEx                                        : Mobile
CsPowerManagementCapabilities                           :
CsPowerManagementSupported                              :
CsPowerOnPasswordStatus                                 : Unknown
CsPowerState                                            : Unknown
CsPowerSupplyState                                      : Safe
CsPrimaryOwnerContact                                   :
CsPrimaryOwnerName                                      : user@company.de
CsResetCapability                                       : Other
CsResetCount                                            : -1
CsResetLimit                                            : -1
CsRoles                                                 : {LM_Workstation, LM_Server, NT, Potential_Browser...}
CsStatus                                                : OK
CsSupportContactDescription                             :
CsSystemFamily                                          :
CsSystemSKUNumber                                       : 0704
CsSystemType                                            : x64-based PC
CsThermalState                                          : Safe
CsTotalPhysicalMemory                                   : 17045016576
CsPhyicallyInstalledMemory                              : 16777216
CsUserName                                              : CLIENT12\TEST
CsWakeUpType                                            : PowerSwitch
CsWorkgroup                                             : WORKGROUP
OsName                                                  : Microsoft Windows 10 Pro
OsType                                                  : WINNT
OsOperatingSystemSKU                                    : 48
OsVersion                                               : 10.0.14393
OsCSDVersion                                            :
OsBuildNumber                                           : 14393
OsHotFixes                                              : {KB3176936, KB3194343, KB3199209, KB3199986...}
OsBootDevice                                            : \Device\HarddiskVolume1
OsSystemDevice                                          : \Device\HarddiskVolume3
OsSystemDirectory                                       : C:\WINDOWS\system32
OsSystemDrive                                           : C:
OsWindowsDirectory                                      : C:\WINDOWS
OsCountryCode                                           : 1
OsCurrentTimeZone                                       : 120
OsLocaleID                                              : 0409
OsLocale                                                : en-US
OsLocalDateTime                                         : 10/28/2016 4:11:51 PM
OsLastBootUpTime                                        : 10/19/2016 7:48:03 AM
OsUptime                                                : 9.08:23:47.7627676
OsBuildType                                             : Multiprocessor Free
OsCodeSet                                               : 1252
OsDataExecutionPreventionAvailable                      : True
OsDataExecutionPrevention32BitApplications              : True
OsDataExecutionPreventionDrivers                        : True
OsDataExecutionPreventionSupportPolicy                  : OptIn
OsDebug                                                 : False
OsDistributed                                           : False
OsEncryptionLevel                                       : 256
OsForegroundApplicationBoost                            : Maximum
OsTotalVisibleMemorySize                                : 16645524
OsFreePhysicalMemory                                    : 9128212
OsTotalVirtualMemorySize                                : 19135892
OsFreeVirtualMemory                                     : 8607696
OsInUseVirtualMemory                                    : 10528196
OsTotalSwapSpaceSize                                    :
OsSizeStoredInPagingFiles                               : 2490368
OsFreeSpaceInPagingFiles                                : 2442596
OsPagingFiles                                           : {C:\pagefile.sys}
OsHardwareAbstractionLayer                              : 10.0.14393.206
OsInstallDate                                           : 8/17/2016 3:40:27 PM
OsManufacturer                                          : Microsoft Corporation
OsMaxNumberOfProcesses                                  : 4294967295
OsMaxProcessMemorySize                                  : 137438953344
OsMuiLanguages                                          : {de-DE, en-US}
OsNumberOfLicensedUsers                                 :
OsNumberOfProcesses                                     : 157
OsNumberOfUsers                                         : 2
OsOrganization                                          :
OsArchitecture                                          : 64-bit
OsLanguage                                              : de-DE
OsProductSuites                                         : {TerminalServicesSingleSession}
OsOtherTypeDescription                                  :
OsPAEEnabled                                            :
OsPortableOperatingSystem                               : False
OsPrimary                                               : True
OsProductType                                           : WorkStation
OsRegisteredUser                                        : test@company.com
OsSerialNumber                                          : 00330-50021-50665-AAOEM
OsServicePackMajorVersion                               : 0
OsServicePackMinorVersion                               : 0
OsStatus                                                : OK
OsSuites                                                : {TerminalServices, TerminalServicesSingleSession}
OsServerLevel                                           :
KeyboardLayout                                          : de-DE
TimeZone                                                : (UTC+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna
LogonServer                                             : \\CLIENT
PowerPlatformRole                                       : Mobile
HyperVisorPresent                                       : False
HyperVRequirementDataExecutionPreventionAvailable       : True
HyperVRequirementSecondLevelAddressTranslation          : True
HyperVRequirementVirtualizationFirmwareEnabled          : True
HyperVRequirementVMMonitorModeExtensions                : True
DeviceGuardSmartStatus                                  : Off
DeviceGuardRequiredSecurityProperties                   :
DeviceGuardAvailableSecurityProperties                  :
DeviceGuardSecurityServicesConfigured                   :
DeviceGuardSecurityServicesRunning                      :
DeviceGuardCodeIntegrityPolicyEnforcementStatus         :
DeviceGuardUserModeCodeIntegrityPolicyEnforcementStatus :

PowerShell 技能连载 - 本地帐户的内置支持

从 PowerShell 5.1 开始,终于内置支持了本地用户账户。PowerShell 5.1 现在支持 Windows 10 和 Windows Server 2016:

PS C:\> Get-Command -Module *LocalAccounts | Select-Object -ExpandProperty Name

Add-LocalGroupMember
Disable-LocalUser
Enable-LocalUser
Get-LocalGroup
Get-LocalGroupMember
Get-LocalUser
New-LocalGroup
New-LocalUser
Remove-LocalGroup
Remove-LocalGroupMember
Remove-LocalUser
Rename-LocalGroup
Rename-LocalUser
Set-LocalGroup
Set-LocalUser

PowerShell 技能连载 - 使用 Add-Member 时请注意!

Add-Member 常用来创建自定义对象,例如:

1
2
3
4
5
$o = New-Object -TypeName PSObject
$o | Add-Member -MemberType NoteProperty -Name Notes -Value 'Something'
$o | Add-Member -MemberType NoteProperty -Name Date -Value (Get-Date)

$o

这可以工作,结果类似这样:

PS C:\> $o

Notes     Date
-----     ----
Something 10/28/2016 3:56:53 PM

然而,这样做效率不高。因为 Add-Member 时动态地扩展现有的对象,而不是创建新的对象。以上代码可以用这种方法更容易地实现:

1
2
3
4
5
6
$o = [PSCustomObject]@{
Notes = 'Something'
Date = Get-Date
}

$o

Add-Member 可以做更多高级的事情,例如添加脚本属性和方法。请检查当您向以上对象添加动态脚本属性时发生了什么:

1
2
3
4
5
6
$o = [PSCustomObject]@{
Notes = 'Something'
Date = Get-Date
}

$o | Add-Member -MemberType ScriptProperty -Name CurrentDate -Value { Get-Date }

现在请看多次查询该对象时,它的 DateCurrentDate 属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
PS C:\> $o

Notes Date CurrentDate
----- ---- -----------
Something 10/28/2016 4:01:54 PM 10/28/2016 4:01:57 PM



PS C:\> $o

Notes Date CurrentDate
----- ---- -----------
Something 10/28/2016 4:01:54 PM 10/28/2016 4:02:00 PM



PS C:\> $o

Notes Date CurrentDate
----- ---- -----------
Something 10/28/2016 4:01:54 PM 10/28/2016 4:02:02 PM

Date 属性返回的是静态信息而CurrentDate 属性总是返回当前时间,因为它的值是一个脚本,每次查询这个属性的时候都会执行一次。

PowerShell 技能连载 - PSCustomObject 到底如何工作

在前一个技能中我们介绍了如何快速用 PSCustomObject 创建一个新对象:

$o = [PSCustomObject]@{
    Date     = Get-Date
    BIOS     = Get-WmiObject -Class Win32_BIOS
    Computer = $env:COMPUTERNAME
    OS       = [Environment]::OSVersion
    Remark   = 'Some remark'
}

实际中,[PSCustomObject] 并不是一个类型,并且也不是在转型一个哈希表。这个场景背后实际发生的是两个步骤的组合,您也可以分别执行这两个步骤:

1
2
3
4
5
6
7
8
9
10
11
12
13
#requires -Version 3.0

# create an ordered hash table
$hash = [Ordered]@{
Date = Get-Date
BIOS = Get-WmiObject -Class Win32_BIOS
Computer = $env:COMPUTERNAME
OS = [Environment]::OSVersion
Remark = 'Some remark'
}

# turn hash table in object
$o = New-Object -TypeName PSObject -Property $hash

由于这段代码用到了 PowerShell 3.0 引入的排序的哈希表,所以无法在 PowerShell 2.0 中使用相同的做法。要支持 PowerShell 2.0 ,请用无序的(传统的)哈希表代替:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#requires -Version 2.0

# create a hash table
$hash = @{
Date = Get-Date
BIOS = Get-WmiObject -Class Win32_BIOS
Computer = $env:COMPUTERNAME
OS = [Environment]::OSVersion
Remark = 'Some remark'
}

# turn hash table in object
$o = New-Object -TypeName PSObject -Property $hash

$o

PowerShell 技能连载 - 创建新对象的快速方法

要将一系列信息打包起来的最好方法就是将它们存储在自定义对象中。最简单最快捷的方法就是用 PSCustomObject

1
2
3
4
5
6
7
8
#requires -Version 3.0
$o = [PSCustomObject]@{
Date = Get-Date
BIOS = Get-WmiObject -Class Win32_BIOS
Computer = $env:COMPUTERNAME
OS = [Environment]::OSVersion
Remark = 'Some remark'
}

在大括号内,将一系列信息(或命令执行结果)存储在键中。这将创建一个将包含一系列信息的对象:

PS C:\> $o


Date : 10/28/2016 3:47:27 PM
BIOS : \DESKTOP-7AAMJLF\root\cimv2:Win32_BIOS.Name=”1.4.4”,SoftwareElementID=”1.4.4”,SoftwareElementState=3,TargetOpera
tingSystem=0,Version=”DELL - 1072009”
Computer : DESKTOP-7AAMJLF
OS : Microsoft Windows NT 10.0.14393.0
Remark : Some remark



PS C:> $o.Remark
Some remark

PS C:\> $o.OS

Platform ServicePack Version      VersionString
-------- ----------- -------      -------------
 Win32NT             10.0.14393.0 Microsoft Windows NT 10.0.14393.0


PS C:> $o.OS.VersionString
Microsoft Windows NT 10.0.14393.0

PS C:\>

PowerShell 技能连载 - 利用命令行历史

PowerShell 将您的所有交互命令行输入“记录”到它的命令行历史中,而 Get-History 负责显示它们。如果您运行了一段时间 PowerShell 并且觉得运行的效果不错,那么可以用以下脚本将所有的交互命令从命令行历史中复制到剪贴板中。接下来您可以将它们粘贴到 PowerShell ISE 中,并使之成为一个脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# define how old your commands may be at most to be included
$MaxAgeHours = 4

# get all command history items that were started after this
$DateLimit = (Get-Date).AddHours(-$MaxAgeHours)


# get all command-line commands
Get-History |
# exclude all that were aborted
Where-Object ExecutionStatus -eq Completed |
# exclude all that are older than the limit set above
Where-Object StartExecutionTime -gt $DateLimit |
# get just the command-line
Select-Object -ExpandProperty CommandLine |
# copy all to clipboard
clip.exe

PowerShell 技能连载 - 获取PowerShell Gallery 模块的最新版本

www.powershellgallery.com ,Microsoft 发布了一个公开的脚本和模块的仓库。您可以在这里和其他人交流 PowerShell 代码(请见网站)。

要使用这个仓库,您需要 PowerShell 5 或者手动安装 PowerShellGet 模块(在 powershellgallery.com 可以下载到)。接下来您可以使用诸如 Find/Save/Install/Update/Remove-Script/Module 等 cmdlet。

目前缺乏的是一个查看模块当前最新版本号的方法。以下是解决方案:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
function Get-PublishedModuleVersion($Name)
{
# access the main module page, and add a random number to trick proxies
$url = "https://www.powershellgallery.com/packages/$Name/?dummy=$(Get-Random)"
$request = [System.Net.WebRequest]::Create($url)
# do not allow to redirect. The result is a "MovedPermanently"
$request.AllowAutoRedirect=$false
try
{
# send the request
$response = $request.GetResponse()
# get back the URL of the true destination page, and split off the version
$response.GetResponseHeader("Location").Split("/")[-1] -as [Version]
# make sure to clean up
$response.Close()
$response.Dispose()
}
catch
{
Write-Warning $_.Exception.Message
}
}

Get-PublishedModuleVersion -Name ISESteroids

当您运行 Get-PublishedModuleVersion 并传入发布的模块名,执行结果类似如下:

PS C:\> Get-PublishedModuleVersion -Name ISESteroids

Major  Minor  Build  Revision
-----  -----  -----  --------
2      6      3      25

这个操作非常非常快,而且可以用来检测已安装的模块,看它们是否是最新版本。

PowerShell 技能连载 - (分别)测试文件和文件夹

Test-Path 在测试一个文件或文件夹是否存在时十分有用,它可以用在任何 PowerShell 驱动器上。所以它也可以测试一个变量、一个函数,或一个证书是否存在(举个例子)。

In recent PowerShell versions, Test-Path can now differentiate between containers (i.e. folders) and leafs (i.e. files), too:

在近期的 PowerShell 版本中,Test-Path 还可以区分容器(例如文件夹)和叶子(例如文件):

1
2
3
4
5
6
7
$path = 'c:\windows\explorer.exe'
# any item type
Test-Path -Path $path
# just files
Test-Path -Path $path -PathType Leaf
# just folders
Test-Path -Path $path -PathType Container