[玩转系统] 应对 WSMan PowerShell 挑战
作者:精品下载站 日期:2024-12-14 07:59:52 浏览:15 分类:玩电脑
应对 WSMan PowerShell 挑战
今天,我想分享一下我最近的 Iron Scripter 挑战的解决方案。我认为这是一项令人着迷的任务,并且具有实际成果。我鼓励你尝试一下挑战,然后回来看看我是如何应对的。
该挑战不仅是对您的 PowerShell 脚本编写技能的良好测试,也是对您对 PowerShell 远程处理的理解程度的测试。从长远来看,我毫不怀疑 PowerShell 远程处理将意味着 SSH。但这不会很快发生。使用 WSMan 的传统 PowerShell 远程处理仍然是大多数 IT 专业人员管理远程服务器的方式。这意味着您应该理解它并能够管理它。
脚本挑战是创建一个工具,该工具可以查询远程服务器的 WSMan 连接,并将具有特定信息的自定义对象写入管道。我是这样处理的。
了解您的流程
首先要知道的是,当建立 PowerShell 远程连接时,它会在 wsmprovhost 进程中运行。查询这个过程很简单。
流程对象可以提供挑战所寻找的许多信息。尽管如此,要求之一是获取关联的子进程。我发现使用 Get-CimInstance 对于此任务很有用。
获取 WSManInstance
挑战的其他部分需要付出更多努力。当建立 PowerShell 远程连接时,就会有一个相应的 WSMan 实例。您可能知道,当您通过 PowerShell 远程处理进行连接时,您正在连接到会话端点。 Get-PSSessionConfiguration cmdlet 显示这些端点。这些端点几乎总是在远程计算机上启动 PowerShell 会话。用 WSMan 的话来说,它在 shell 中运行。
PowerShell 有一个名为 Get-WSManInstance 的 cmdlet,可让您枚举这些连接。
幸运的是,有一个 XML 方法可以转换这些值。
获取 PSRemoteSessionUser
那些棘手的地方。使用 Resolve-DNSName 可以轻松完成从 IP 地址获取源主机名等任务。考虑到所有这些,我编写了一个名为 Get-PSRemoteSessionUser 的 PowerShell 函数。
Function Get-PSRemoteSessionUser {
[cmdletbinding(DefaultParameterSetName = "ComputerName")]
Param(
[Parameter(ParameterSetName = 'Session', Position = 0)]
[ValidateNotNullOrEmpty()]
[System.Management.Automation.Runspaces.PSSession[]]$Session,
[Parameter(ParameterSetName = 'ComputerName', Mandatory, Position = 0)]
[Alias('Cn')]
[ValidateNotNullOrEmpty()]
[string[]]$ComputerName,
[Parameter(ParameterSetName = 'ComputerName', ValueFromPipelineByPropertyName)]
[pscredential]$Credential,
[Parameter(ParameterSetName = 'ComputerName')]
[System.Management.Automation.Runspaces.AuthenticationMechanism]$Authentication,
[Parameter(ParameterSetName = 'ComputerName')]
[Parameter(ParameterSetName = 'Session')]
[int]$ThrottleLimit
)
Begin {
Write-Verbose "[BEGIN ] Starting: $($MyInvocation.Mycommand)"
#define the scriptblock to run remotely
$run = {
$VerbosePreference = $using:VerbosePreference
Write-Verbose "[$([environment]::machinename)] Querying for local WSMan sessions"
$process = 'wsmprovhost'
#these helper functions will be used to get and format connection data
Function _enumWsMan {
[cmdletbinding()]
Param()
Get-WSManInstance -ResourceURI Shell -Enumerate |
Select-Object -Property Name, State, ShellID, Owner, ClientIP, ProcessID,
@{Name = "Memory"; Expression = { _parseMemoryString $_.memoryUsed } },
@{Name = "ShellRunTime"; Expression = { [System.Xml.XmlConvert]::ToTimeSpan($_.ShellRunTime) } },
@{Name = "ShellInactivity"; Expression = { [System.Xml.XmlConvert]::ToTimeSpan($_.ShellInactivity) } },
@{Name = "MaxIdleTimeout"; Expression = { [System.Xml.XmlConvert]::ToTimeSpan($_.MaxIdleTimeout) } },
@{Name = "SessionConfiguration"; Expression = { Split-Path -path $_.resourceuri -leaf } }
}
Function _parseMemoryString {
#convert values like 11MB to 11534336
[cmdletbinding()]
Param([string]$StringValue)
switch -Regex ($StringValue ) {
"\d+KB" {
$val = 1KB
}
"\d+MB" {
$val = 1MB
}
"\d+GB" {
$val = 1GB
}
} #switch
if ($val) {
[int]$i = ([regex]"\d+").Match($StringValue).value
$i * $val
}
else {
Write-Warning "Failed to parse $StringValue"
$stringValue
}
} #close function
try {
Write-Verbose "[$([environment]::machinename)] Getting $process process excluding id $PID"
$p = (Get-Process -Name $process -IncludeUserName -erroraction stop).where({ $_.id -ne $pid })
}
Catch [Microsoft.PowerShell.Commands.ProcessCommandException] {
Write-Warning "Could not find process $process on this computer."
}
Catch {
Throw $_
}
if ($p) {
foreach ($item in $p) {
if ($item.username) {
Write-Verbose "[$([environment]::machinename)] Getting the SID for $($item.username)"
$SID = [System.Security.Principal.NTAccount]::new("$($item.username)").Translate([System.Security.Principal.SecurityIdentifier]).value
}
else {
$SID = $null
}
#call a private function to enumerate WSMan connection associated with this process ID
Write-Verbose "[$([environment]::machinename)] Enumerating WSMan connections"
$connData = $(_enumWsMan).where({ $_.processid -eq $item.ID })
#get child process IDs
Write-Verbose "[$([environment]::machinename)] Getting child processes for id $($item.id)"
$childProcs = (Get-CimInstance -ClassName win32_process -filter "ParentProcessId = $($item.id)" -Property ProcessID).ProcessID
#resolve the hostname
#temporarily disable Verbose to eliminate verbose messages from loading the DNSClient module
$VerbosePreference = "SilentlyContinue"
Import-Module DNSClient
$VerbosePreference = $using:VerbosePreference
Try {
Write-Verbose "[$([environment]::machinename)] Resolving the hostname for $($conndata.ClientIP)"
$rHost = (Resolve-DnsName -Name $connData.ClientIP -ErrorAction Stop).NameHost
}
Catch {
Write-Verbose "[$([environment]::machinename)] Failed to resolve a hostname for $($connData.ClientIP)."
$rHost = $connData.clientIP
}
Write-Verbose "[$([environment]::machinename)] Returning connection data"
#Send data back to the host to construct a custom object
@{
rHost = $rHost
Item = $item
SID = $SID
Computername = [environment]::MachineName
ChildProcs = $childProcs
ConnData = $connData
}
} #foreach item
}
else {
Write-Verbose "[$([environment]::machinename)] No running $process process(e$as) found"
}
} #close scriptblock
$PSBoundParameters.add("Scriptblock", $Run)
$PSBoundParameters.Add("HideComputername", $True)
} #begin
Process {
Write-Verbose "[PROCESS] Getting remote connection data"
$data = Invoke-Command @PSBoundParameters
foreach ($result in $data) {
Write-Verbose "[PROCESS] Processing data for $($result.computername)"
[pscustomobject]@{
PSTypename = "PSRemoteSessionUser"
Computername = $result.Computername
DateUTC = (Get-Date).ToUniversalTime()
StartTimeUTC = $result.item.StartTime.ToUniversalTime()
ProcessID = $result.item.id
ChildProcesses = $result.childProcs
Username = $result.item.Username
SID = $result.sid
State = $result.connData.State
RemoteHost = $result.rHost
RemoteIPAddress = $result.connData.ClientIP
ShellRunTime = $result.conndata.ShellRunTime
SessionConfiguration = $result.connData.SessionConfiguration
Memory = $result.connData.Memory
}
} #foreach result
} #process
End {
Write-Verbose "[END ] Ending: $($MyInvocation.Mycommand)"
} #end
} #close Get-RemoteSessionUser
该功能旨在让我通过名称或通过现有会话查询远程计算机。如果我使用现有会话,它将从结果中过滤掉。大多数核心查询都是远程发生的。 “原始”数据从 Invoke-Command 返回到本地主机,并转换为自定义对象。
我的函数使用详细输出,甚至将我的详细首选项传递给远程计算机。
自定义格式
但还有一件事。挑战的最后一部分是创建自定义格式文件。我得到的结果很好,但也许我通常只需要查看格式化的属性子集。使用 PSScriptTools 模块中的 New-PSFormatXML,我创建了一个 format.ps1xml。在 VS Code 中进行一些调整后,我可以将其加载到我的会话中。
Update-FormatData psremotesessionuser.format.ps1xml
现在就可以得到格式良好的结果。
这是格式文件。
<?xml version="1.0" encoding="UTF-8"?>
<!--
format type data generated 09/15/2020 08:54:32 by BOVINE320\Jeff
using New-PSFormatXML from the PSScriptTools module.
Install-Module PSScriptTools
-->
<Configuration>
<ViewDefinitions>
<View>
<!--Created 09/15/2020 08:54:32 by BOVINE320\Jeff-->
<Name>default</Name>
<ViewSelectedBy>
<TypeName>PSRemoteSessionUser</TypeName>
</ViewSelectedBy>
<GroupBy>
<PropertyName>Computername</PropertyName>
</GroupBy>
<TableControl>
<!--Delete the AutoSize node if you want to use the defined widths.-->
<AutoSize />
<TableHeaders>
<TableColumnHeader>
<Label>SessionConfiguration</Label>
<Width>23</Width>
<Alignment>left</Alignment>
</TableColumnHeader>
<TableColumnHeader>
<Label>Address</Label>
<Width>14</Width>
<Alignment>left</Alignment>
</TableColumnHeader>
<TableColumnHeader>
<Label>Username</Label>
<Width>15</Width>
<Alignment>left</Alignment>
</TableColumnHeader>
<TableColumnHeader>
<Label>State</Label>
<Width>12</Width>
<Alignment>left</Alignment>
</TableColumnHeader>
<TableColumnHeader>
<Label>Runtime</Label>
<Width>15</Width>
<Alignment>left</Alignment>
</TableColumnHeader>
<TableColumnHeader>
<Label>MemMB</Label>
<Width>12</Width>
<Alignment>right</Alignment>
</TableColumnHeader>
<TableColumnHeader>
<Label>PID</Label>
<Width>12</Width>
<Alignment>right</Alignment>
</TableColumnHeader>
</TableHeaders>
<TableRowEntries>
<TableRowEntry>
<TableColumnItems>
<TableColumnItem>
<PropertyName>SessionConfiguration</PropertyName>
</TableColumnItem>
<TableColumnItem>
<PropertyName>RemoteIPAddress</PropertyName>
</TableColumnItem>
<TableColumnItem>
<PropertyName>Username</PropertyName>
</TableColumnItem>
<TableColumnItem>
<PropertyName>State</PropertyName>
</TableColumnItem>
<TableColumnItem>
<PropertyName>ShellRunTime</PropertyName>
</TableColumnItem>
<TableColumnItem>
<ScriptBlock>$_.Memory/.1MB -as [int]</ScriptBlock>
</TableColumnItem>
<TableColumnItem>
<PropertyName>ProcessID</PropertyName>
</TableColumnItem>
</TableColumnItems>
</TableRowEntry>
</TableRowEntries>
</TableControl>
</View>
</ViewDefinitions>
</Configuration>
局限性
我现在有一个 PowerShell 工具,可以运行它来查看谁连接到服务器以及这些会话的状态。
下一步
我希望您能尝试一下挑战,并密切关注 Iron Scripter 网站以应对未来的挑战。它们是测试您的知识和扩展您的技能的好方法。如果您想了解有关 PowerShell 的更多信息,可以查看 Pluralsight 提供的我的 PowerShell 远程处理基础课程。或者访问我的书籍和培训页面。
我希望您发现本文内容丰富且有用。随时欢迎提出意见和反馈。
猜你还喜欢
- 03-30 [玩转系统] 如何用批处理实现关机,注销,重启和锁定计算机
- 02-14 [系统故障] Win10下报错:该文件没有与之关联的应用来执行该操作
- 01-07 [系统问题] Win10--解决锁屏后会断网的问题
- 01-02 [系统技巧] Windows系统如何关闭防火墙保姆式教程,超详细
- 12-15 [玩转系统] 如何在 Windows 10 和 11 上允许多个 RDP 会话
- 12-15 [玩转系统] 查找 Exchange/Microsoft 365 中不活动(未使用)的通讯组列表
- 12-15 [玩转系统] 如何在 Windows 上安装远程服务器管理工具 (RSAT)
- 12-15 [玩转系统] 如何在 Windows 上重置组策略设置
- 12-15 [玩转系统] 如何获取计算机上的本地管理员列表?
- 12-15 [玩转系统] 在 Visual Studio Code 中连接到 MS SQL Server 数据库
- 12-15 [玩转系统] 如何降级 Windows Server 版本或许可证
- 12-15 [玩转系统] 如何允许非管理员用户在 Windows 中启动/停止服务
取消回复欢迎 你 发表评论:
- 精品推荐!
-
- 最新文章
- 热门文章
- 热评文章
[影视] 黑道中人 Alto Knights(2025)剧情 犯罪 历史 电影
[古装剧] [七侠五义][全75集][WEB-MP4/76G][国语无字][1080P][焦恩俊经典]
[实用软件] 虚拟手机号 电话 验证码 注册
[电视剧] 安眠书店/你 第五季 You Season 5 (2025) 【全10集】
[电视剧] 棋士(2025) 4K 1080P【全22集】悬疑 犯罪 王宝强 陈明昊
[软件合集] 25年6月5日 精选软件22个
[软件合集] 25年6月4日 精选软件36个
[短剧] 2025年06月04日 精选+付费短剧推荐33部
[短剧] 2025年06月03日 精选+付费短剧推荐25部
[软件合集] 25年6月3日 精选软件44个
[剧集] [央视][笑傲江湖][2001][DVD-RMVB][高清][40集全]李亚鹏、许晴、苗乙乙
[电视剧] 欢乐颂.5部全 (2016-2024)
[电视剧] [突围] [45集全] [WEB-MP4/每集1.5GB] [国语/内嵌中文字幕] [4K-2160P] [无水印]
[影视] 【稀有资源】香港老片 艺坛照妖镜之96应召名册 (1996)
[剧集] 神经风云(2023)(完结).4K
[剧集] [BT] [TVB] [黑夜彩虹(2003)] [全21集] [粤语中字] [TV-RMVB]
[实用软件] 虚拟手机号 电话 验证码 注册
[资源] B站充电视频合集,包含多位重量级up主,全是大佬真金白银买来的~【99GB】
[影视] 内地绝版高清录像带 [mpg]
[书籍] 古今奇书禁书三教九流资料大合集 猎奇必备珍藏资源PDF版 1.14G
[电视剧] [突围] [45集全] [WEB-MP4/每集1.5GB] [国语/内嵌中文字幕] [4K-2160P] [无水印]
[剧集] [央视][笑傲江湖][2001][DVD-RMVB][高清][40集全]李亚鹏、许晴、苗乙乙
[电影] 美国队长4 4K原盘REMUX 杜比视界 内封简繁英双语字幕 49G
[电影] 死神来了(1-6)大合集!
[软件合集] 25年05月13日 精选软件16个
[精品软件] 25年05月15日 精选软件18个
[绝版资源] 南与北 第1-2季 合集 North and South (1985) /美国/豆瓣: 8.8[1080P][中文字幕]
[软件] 25年05月14日 精选软件57个
[短剧] 2025年05月14日 精选+付费短剧推荐39部
[短剧] 2025年05月15日 精选+付费短剧推荐36部
- 最新评论
-
- 热门tag