[玩转系统] 应对 CIM 目录挑战
作者:精品下载站 日期:2024-12-14 08:00:57 浏览:14 分类:玩电脑
应对 CIM 目录挑战
2020 年的最后一项 Iron Scripter 挑战是一项重大挑战。如果你没有机会去做,看看你能想出什么,然后回来看看我的方法。与许多挑战一样,我们的目标不是生成可用于生产的 PowerShell 工具,而是突破 PowerShell 脚本编写和工具制作能力的极限。从这方面来说,这是一个巨大的挑战。
目标是使用 WMI/CIM 获取文件和文件夹的目录列表。这可能是传统文件系统列表的潜在替代方案。正如您将看到的,完成此任务是可能的。然而,并不是每个文件和/或文件夹都被注册,我还没有找到一致的原因。这意味着无法保证当我运行代码时我会得到明确的答案。但目标是学习,所以我对此表示同意。让我们深入探讨一下。
Win32_目录
解决方案的基础始于 Win32_Directory WMI 类。我将过滤单个文件夹以了解它的外观。
Get-CimInstance win32_directory -Filter "Name='C:\Work\samples'" | Tee-Object -Variable d
您还可以使用 Get-CimClass 检查类属性。请记住,对于 WMI/CIM 过滤器,要使用旧版运算符,例如=符号。\是一个特殊字符,需要转义。
现在是有趣的部分。在 WMI 中,几乎所有内容都是相关的。使用 Get-CimAssociatedInstance 命令检索相关对象。您可以通过过滤类名来限制结果类型。
出于我的目的,我只想查看直接子目录,因此我将修改代码以过滤掉父目录。
$d | Get-CimAssociatedInstance -ResultClassName Win32_Directory |
Where-Object { (Split-Path $_.name) -eq $d.name } |
Select-Object Hidden, Archive, System, Compressed, Writeable, Encrypted, LastModified, Name, Path
CIM_数据文件
现在我有了获取文件夹的方法,我需要查找文件。这将使用 CIM_DataFile 类。我可以使用相同的技术。
$d | Get-CimAssociatedInstance -ResultClassName CIM_DATAFile | Select-Object -First 1 -Property *
同样,我也可以使用 Get-CimClass 来发现属性,但查看实际示例通常会有所帮助。
部分挑战是复制 Get-ChildItem 的输出,因此这样的内容是一个很好的概念验证。
$d | Get-CimAssociatedInstance -ResultClassName CIM_DATAFile |
Format-Table -GroupBy @{Name = "Path"; Expression = { Resolve-Path (Join-Path -Path $_.drive -ChildPath $_.Path) } } -Property Hidden, Archive, System, LastModified, FileSize, Name
创建自定义类
现在我知道如何检索文件和文件夹,我想要一种更简单的方法来显示它们,而不必依赖繁琐的选择对象语法。我的答案是创建 PowerShell 类。
Class cimFolder {
[string]$FullName
[string]$Name
[bool]$Archive
[bool]$Compressed
[DateTime]$CreationDate
[string]$Computername
[string]$Drive
[bool]$Encrypted
[bool]$Hidden
[DateTime]$LastAccessed
[DateTime]$LastModified
[string]$Path
[bool]$Readable
[bool]$System
[bool]$Writeable
[string]$Mode
}
Class cimFile {
[string]$FullName
[string]$Name
[bool]$Archive
[bool]$Compressed
[DateTime]$CreationDate
[string]$Computername
[string]$Drive
[bool]$Encrypted
[bool]$Hidden
[int64]$FileSize
[DateTime]$LastAccessed
[DateTime]$LastModified
[string]$Path
[bool]$Readable
[bool]$System
[bool]$Writeable
[string]$Mode
}
本质上,这些是原始 WMI 类的克隆。我将编写一个 PowerShell 函数,将原始 WMI 类“转换”为我的自定义类,而不是定义构造函数。
Function New-CimFile {
[cmdletbinding()]
Param(
[Parameter(Position = 0, Mandatory, ValueFromPipeline)]
[object]$CimObject
)
Begin {
$properties = [CimFile].DeclaredProperties.Name
}
Process {
$file = [CimFile]::New()
foreach ($item in $properties) {
$file.$item = $CimObject.$item
}
$file.name = Split-Path -Path $CimObject.caption -Leaf
$file.fullname = $CimObject.Caption
$file.computername = $CimObject.CSName
$file.mode = Get-Mode $CimObject
$file
}
End {
#not used
}
}
我还编写了一个辅助函数来获取文件模式。
Function Get-Mode {
[cmdletbinding()]
param([object]$CimObject)
# use the ternary operator to simplify the code,
# although this will require PowerShell 7.x
$dir = $CimObject.CimClass.Cimclassname -match 'Directory' ? "d" : "-"
$archive = $CimObject.archive ? "a" : "-"
$ro = $CimObject.writeable ? "-" : "r"
$system = $CimObject.System ? "s" : "-"
$hidden = $CimObject.Hidden ? "h" : "-"
"{0}{1}{2}{3}{4}" -f $Dir, $Archive, $RO, $Hidden, $System
}
请注意,此函数使用三元运算符,因此它只能在 PowerShell 7 中运行。除了我想找个借口尝试一下之外,没有真正的理由使用该运算符。将这些元素加载到我的 PowerShell 会话中后,我可以验证这个概念。
$d | Get-CimAssociatedInstance -ResultClassName CIM_DATAFile | New-CimFile
我可以对目录对象执行类似的过程。最后,我可以将它们全部放在一个命令中。
Function Get-CimFolder {
[cmdletbinding(DefaultParameterSetName = "computer")]
[alias("cdir")]
[OutputType("cimFolder", "cimFile")]
Param(
[Parameter(Position = 0, HelpMessage = "Enter the folder path. Don't include the trailing \.")]
[ValidateNotNullorEmpty()]
[string]$Path = ".",
[switch]$Recurse,
[Parameter(ParameterSetName = "computer")]
[ValidateNotNullOrEmpty()]
[alias("cn")]
[string]$Computername = $ENV:Computername,
[Parameter(ParameterSetName = "session")]
[ValidateNotNullOrEmpty()]
[Microsoft.Management.Infrastructure.CimSession]$CimSession
)
Begin {
Write-Verbose "Starting $($myinvocation.MyCommand)"
$cimParams = @{
Classname = "win32_directory"
Filter = ""
CimSession = ""
}
} #begin
Process {
#convert Path to a file system path
if ($path -match '\\$') {
Write-Verbose "Stripping off a trailing slash"
$path = $path -replace "\\$", ""
}
Try {
$cpath = Convert-Path -Path $path -ErrorAction Stop
#escape any \ in the path
$rPath = $cpath.replace("\", "\\")
$cimParams.Filter = "Name='$rpath'"
Write-Verbose "Using query $($cimparams.filter)"
}
Catch {
Write-Warning "Can't validate the path $path. $($_.Exception.Message)"
#bail out
return
}
if ($pscmdlet.ParameterSetName -eq 'computer') {
Try {
$cimSession = New-CimSession -ComputerName $computername -ErrorAction Stop
$tmpSession = $True
}
Catch {
Throw $_
}
}
Else {
Write-Verbose "Using an existing CIMSession to $($cimsession.computername)"
$tmpSession = $False
}
$cimParams.Cimsession = $CimSession
Write-Verbose "Getting $cpath on $($cimsession.computername)"
$main = Get-CimInstance @cimParams
#filter out the parent folder
$main | Get-CimAssociatedInstance -ResultClassName Win32_Directory |
Where-Object { (Split-Path $_.name) -eq $main.name } | New-CimFolder -outvariable cf
$main | Get-CimAssociatedInstance -ResultClassName CIM_DATAFile | New-Cimfile
if ($cf -AND $recurse) {
Write-Verbose "Recursing..."
foreach ($fldr in $cf.fullname) {
Write-Verbose $fldr
Get-CimFolder -path $Fldr -CimSession $cimSession
}
}
if ($cimSession -AND $tmpSession) {
Write-Verbose "Remove the temporary session"
Remove-CimSession $cimSession
}
} #Process
End {
Write-Verbose "Ending $($myinvocation.MyCommand)"
}
}
因为我使用的是 CIM cmdlet,所以我可以选择查询远程计算机上的文件夹,这也是挑战的一部分。我的函数使用参数集来支持通过计算机名称和 CIMSession 进行连接。
定制结果
如果您尝试该代码,您将看到结果是具有所有属性的完整对象。不一定容易阅读,也肯定达不到挑战目标。创建自己的独特类的原因之一是我可以定义自定义类型扩展,例如一组默认属性。
Update-TypeData -TypeName cimFolder -DefaultDisplayPropertySet Mode, LastModified, Size, Name -Force
Update-TypeData -TypeName cimFile -MemberType AliasProperty -MemberName Size -Value FileSize -Force
Update-TypeData -TypeName cimFile -DefaultDisplayPropertySet Mode, LastModified, Size, Name -Force
这大大清理了输出。
但定义的对象也可以具有自定义格式文件。我使用值得信赖的 New-PSFormatXML 命令创建了一个。
<?xml version="1.0" encoding="UTF-8"?>
<!--
Format type data generated 10/21/2020 17:19:32 by PROSPERO\Jeff
This file was created using the New-PSFormatXML command that is part
of the PSScriptTools module.
https://github.com/jdhitsolutions/PSScriptTools
This file will only work properly in PowerShell 7
-->
<Configuration>
<SelectionSets>
<SelectionSet>
<Name>cimFileTypes</Name>
<Types>
<TypeName>cimFolder</TypeName>
<TypeName>cimFile</TypeName>
</Types>
</SelectionSet>
</SelectionSets>
<ViewDefinitions>
<View>
<Name>default</Name>
<ViewSelectedBy>
<SelectionSetName>cimFileTypes</SelectionSetName>
</ViewSelectedBy>
<GroupBy>
<!--
You can also use a scriptblock to define a custom property name.
You must have a Label tag.
<ScriptBlock>$_.machinename.toUpper()</ScriptBlock>
<Label>Computername</Label>
Use <Label> to set the displayed value.
-->
<Label>Path</Label>
<ScriptBlock>Join-Path -path $_.drive -childpath $_.path </ScriptBlock>
</GroupBy>
<TableControl>
<!--Delete the AutoSize node if you want to use the defined widths.
<AutoSize />-->
<TableHeaders>
<TableColumnHeader>
<Label>Mode</Label>
<Width>6</Width>
<Alignment>left</Alignment>
</TableColumnHeader>
<TableColumnHeader>
<Label>LastModified</Label>
<Width>24</Width>
<Alignment>right</Alignment>
</TableColumnHeader>
<TableColumnHeader>
<Label>Size</Label>
<Width>14</Width>
<Alignment>right</Alignment>
</TableColumnHeader>
<TableColumnHeader>
<Label>Name</Label>
<!-- <Width>10</Width> -->
<Alignment>left</Alignment>
</TableColumnHeader>
</TableHeaders>
<TableRowEntries>
<TableRowEntry>
<TableColumnItems>
<!--
By default the entries use property names, but you can replace them with scriptblocks.
<ScriptBlock>$_.foo /1mb -as [int]</ScriptBlock>
-->
<TableColumnItem>
<PropertyName>Mode</PropertyName>
</TableColumnItem>
<TableColumnItem>
<PropertyName>LastModified</PropertyName>
</TableColumnItem>
<TableColumnItem>
<PropertyName>Size</PropertyName>
</TableColumnItem>
<TableColumnItem>
<ScriptBlock>
<!-- show Directories, hidden, compressed or encrypted files in color using ANSI-->
if ($_.GetType().Name -eq 'cimFolder') {
"`e[38;5;228m$($_.name)`e[0m"
}
elseif ($_.Encrypted -OR $_.compressed) {
"`e[38;5;201m$($_.name)`e[0m"
}
elseif ($_.Hidden) {
"`e[38;5;105m$($_.name)`e[0m"
}
else {
$_.name
}
</ScriptBlock>
</TableColumnItem>
</TableColumnItems>
</TableRowEntry>
</TableRowEntries>
</TableControl>
</View>
</ViewDefinitions>
</Configuration>
该文件使用脚本块以彩色显示某些文件,这是另一个挑战任务。我的代码使用 PowerShell 7 的 ANSI 转义序列。当我使用 Update-FormatData 加载文件后,请查看惊人的差异。
创建模块
正如您所看到的,该解决方案有很多移动部件。我决定采取额外的步骤,将所有内容整合到一个名为 CimFolder 的模块中。您可以在 GitHub 上找到该模块:https://github.com/jdhisolutions/CimFolder。该模块是一个概念验证,不一定是生产就绪的代码,因此我不打算将其发布到 PowerShell Gallery。
也有可能出现不完整的结果。并非每个文件和文件夹都注册到 WMI。在我的测试中,我遇到了我的命令无法枚举的文件夹,但 Get-ChildItem 工作得很好。我还没有找到一致的解释或修复,这就是为什么我不会依赖我的代码进行生产。然而,我希望我如何以及为什么把这些东西放在一起是有教育意义的。
该模块具有本博客文章中代码示例的最新更新。但我不得不说,我对结果很满意。
我希望您能浏览代码以获取想法和灵感。
拓展你的技能
我希望您能关注 Iron Scripter 网站并尝试应对挑战。这些挑战是开放式的,因此我鼓励您浏览该网站并解决其中的一些挑战。
如果您喜欢从挑战中学习,我建议您获取一份《PowerShell 实践入门》的副本。本书包含 100 个练习题,从非常简单的水平开始,然后难度逐渐增加。答案应该不超过您将在控制台中运行的几个 PowerShell 表达式。这些不是脚本挑战。
或者,要将您的脚本编写技能提升到一个新的水平,请查看 LeanPub 上的 The PowerShell Scripting and Toolmaking Book。
无论如何,提高 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