[玩转系统] 清理你的道路的更多 PowerShell 冒险
作者:精品下载站 日期:2024-12-14 07:55:09 浏览:13 分类:玩电脑
清理你的道路的更多 PowerShell 冒险
几天前,我发布了一篇文章,演示了许多 PowerShell 技术和概念,您可以使用它们来清除 %PATH% 环境变量中的过时位置。对于那些刚接触我的博客的人,我想确保您了解我经常使用一个场景(例如这个场景)来演示和教授 PowerShell。不要假设任何功能或代码示例都是完整的并且可以投入生产。 \发帖后,我听到很多人建议使用 .NET Framework 中的 SetEnvironmentVariable() 方法,特别是因为我使用该框架来发现路径分割器。那么让我们回到当前的问题并探索这种方法。
Cmdlet 优先
我有一个我拥护的 PowerShell 脚本哲学,特别是对于初学者。如果有一个 cmdlet 可以实现任务,请通过 .NET Framework 使用它。我的意思是,使用 Get-Date cmdlet 来获取当前日期和时间,而不是 [datetime]::Now。有几个原因。
首先,我不希望 PowerShell 初学者觉得需要成为 .NET 开发人员来编写脚本和函数。 PowerShell 的全部要点在于存在大量抽象,因此脚本编写者不必了解 .NET Framework。 Cmdlet 更容易发现。它们被记录下来。最重要的是,在我们使用的场景中,应该支持-WhatIf。如果运行 .NET 方法,则没有内置安全性。它运行了。不过,您可以添加对 -WhatIf 的支持,我稍后会介绍。
是的,在某些时候,您可能会求助于 .NET Framework 来提高性能或在没有 cmdlet 的情况下完成某些任务。但这是在你获得了一些经验之后。并且不要忘记,您无法直接对 .NET Framework 进行 Pester 测试。无法模拟 [Environment]::SetEnvironmentVariable()。跳转到 .NET Framework 并没有什么问题。我只是认为你需要一个很好的理由,并确保添加大量的代码文档。
探索 .NET 类
考虑到这一切,让我逐步完成使用 [system.environment] 类构建一些 PowerShell 工具的过程。我们假设您在某处读到过或在 Stack Overflow 问题中看到过它。您可以而且可能应该搜索 system.enviroment,这应该会让您进入 Microsoft 文档页面。或者您可以尝试在 PowerShell 中探索它。在提示符下键入 [System.Environment]:: 并按空格键。您可以循环访问静态属性和方法。或者,如果您加载了 PSReadline 模块,请按 Ctrl+Space
顺便说一句,从技术上讲,您不需要包含系统前缀。如果您只输入 [Environment]:: PowerShell 知道您指的是 System.Environment。
查看列表,有一个名为 GetEnvironmentVariable 的东西。 PowerShell 可能会插入一个左括号,这是一个方法的线索。如果您使用 PSReadline,您可以看到方法定义。或者直接按 Enter 键,不带()。
输出表明有两种方法可以使用此方法,每种方法都会生成一个字符串。第一个采用变量的名称。这似乎很简单,可以测试。
第二种方法采用第二个参数。如果您看到的类型不是 string、int 或 boolean 等典型类型,那么它很可能是枚举。您可以使用相同的技术来发现可能的值。
这是有道理的,因为您可以拥有用户或系统环境变量。咱们试试吧。
我不需要专门指定“用户”或“机器”。因为它是第二个参数,所以 PowerShell 知道它应该是什么。
测试%PATH%
考虑到这一点,让我们转向验证路径。这里有一些命令将成为功能的基础。
[System.Environment]::GetEnvironmentVariable("PATH", "User") -split ";" | where-object { $_ -AND -Not (Test-Path $_) }
[System.Environment]::GetEnvironmentVariable("PATH", "Machine") -split ";" | where-object {$_ -AND -Not (Test-Path $_) }
我的Where-Object 语句还过滤掉了变量以分号结尾时可能出现的空白。
我可以只关注字符串值——比如不存在的路径——但我总是喜欢考虑管道中的丰富对象。我可能会以我从未想过的方式消费和重复使用的东西。考虑到这一点,我编写了这个函数。
Function Get-EnvPath {
[cmdletbinding()]
[OutputType("myEnvPath")]
Param(
[ValidateSet("All","User","System")]
[string]$Scope = "All"
)
#get the path separator character specific to this operating system
$splitter = [System.IO.Path]::PathSeparator
if ($scope -ne "System") {
Write-Verbose "Validating USER paths"
#filter out blanks if path ends in a splitter
[System.Environment]::GetEnvironmentVariable("PATH", "User") -split $splitter |
Where-Object { $_ } | Foreach-Object {
# create a custom object based on each path
Write-Verbose " $_"
[pscustomobject]@{
PSTypeName = "myEnvPath"
Scope = "User"
Computername = [System.Environment]::MachineName
UserName = [System.Environment]::UserName
Target = "User"
Path = $_
Exists = Test-Path $_
}
} #foreach
}
if ($Scope -ne "User") {
Write-Verbose "Validating MACHINE paths"
[System.Environment]::GetEnvironmentVariable("PATH", "Machine") -split $splitter |
Where-Object { $_ } | Foreach-Object {
# create a custom object based on each path
Write-Verbose " $_"
[pscustomobject]@{
PSTypeName = "myEnvPath"
Scope = "System"
Computername = [System.Environment]::MachineName
UserName = [System.Environment]::UserName
Target = "Machine"
Path = $_
Exists = Test-Path $_
}
} #foreach
}
} #end function
我就合适的动词进行了辩论。在上一篇文章中,我使用了 Test 动词。但我想得越多,我意识到我真正在做的是获取一堆反映 %PATH% 中每个位置状态的对象。可能有人认为测试路径功能应该单独处理,但由于我知道这是我编写此函数的主要原因,所以我不介意将其包含在这里。现在我有了一个易于使用的功能。
修复 %PATH% 变量
下半场的挑战是去除不好的地点。这是我可以使用 SetEnvironmentVariable() 方法的地方。如果您使用我展示的技术,您会发现您需要提供变量的名称、新路径和目标。像这样的东西:
[System.Environment]::SetEnvironmentVariable("PATH",$revised,"User")
但是,正如我提到的,不支持 -WhatIf 或其他安全检查。如果我运行该命令,PowerShell 会很乐意执行它。我想记住这一点。我还想创建一个可以使用管道中的对象的函数。让我向您展示我的想法,然后我们将进行讨论。
Function Repair-EnvPath {
[cmdletbinding(SupportsShouldProcess)]
Param(
[Parameter(Position = 0, Mandatory, ValueFromPipelineByPropertyName)]
[string]$Path,
[Parameter(Mandatory, ValueFromPipelineByPropertyName)]
[ValidateSet("User","Machine")]
[string]$Target
)
Begin {
Write-Verbose "Starting $($myinvocation.MyCommand)"
#get the path separator character specific to this operating system
$splitter = [System.IO.Path]::PathSeparator
}
Process {
Write-Verbose "Removing $path from Target %PATH% setting"
#get current values as an array
$paths = [system.environment]::GetEnvironmentVariable("PATH", $Target) -split $splitter
$Corrected = (($paths).where( { $_ -ne $Path })) -join $splitter
Write-Verbose "Setting a new value of $corrected"
#add code support for -WhatIf
if ($PSCmdlet.ShouldProcess("$Target %Path% variable", "Remove $Path")) {
[System.Environment]::SetEnvironmentVariable("PATH", $Corrected, $Target)
}
}
End {
Write-Verbose "Ending $($myinvocation.MyCommand)"
}
}
我再次尝试选择一个有意义的动词。可能有人认为 Set-EnvPath 应该与 Get-EnvPath 一起使用。或者也许是 Update-EnvPath。对我来说,我正在使用这个命令来修复问题。
首先要注意的是 [cmdletbinding()]。我告诉 PowerShell 在该函数中自动包含对 -WhatIf 的支持。我可以运行 Repair-EnvPath -Whatif,并且 ShouldProcess 指令将传递到也支持 -WhatIf 的函数中的任何 cmdlet。但是,该函数中的大部分代码都是本机 .NET。我得自己处理。
该函数采用两个强制参数:路径字符串和环境目标。我已经对后者进行了验证测试。这意味着用户只能输入用户或机器。作为额外的好处,PowerShell 会将这些选项呈现为选项卡完整选项。
请注意,参数名称与 Get-EnvPath 函数的某些属性相同。因为我已经告诉 PowerShell 使用通过属性名称绑定这些参数,当函数看到具有 Path 属性的对象时,它将使用该值。塔吉特也是如此。
Process 脚本块从给定目标获取所有路径并将它们分割成一个数组。
$paths = [system.environment]::GetEnvironmentVariable("PATH", $Target) -split $splitter
然后我可以构建不包含“坏”路径的新路径字符串。
$Corrected = (($paths).where( { $_ -ne $Path })) -join $splitter
现在进行最后一步。我需要调用 SetEnvironmentVariable 方法,但我需要添加对 -WhatIf 的支持。
编写你自己的假设
编写 PowerShell 脚本或函数时,您有一个由 $PSCmdlet 引用的内置对象。该对象有一个名为 ShouldProcess() 的方法。要使用,请创建一个 IF 语句。如果未检测到 -Whatif,IF 块中的代码将会运行。
If ($PSCmdlet.ShouldProcess("target")) {
#do something serious
}
如果 PowerShell 检测到运行脚本的人使用了 -WhatIf,则 PowerShell 将使用 ShouldProcess 方法中的参数来创建您看到的消息:“What if: Performing the operation on target :”通常,您需要做的就是为目标提供一个值,例如路径、名称或您正在修改的任何内容。但是,您可以进行更多控制,因为还有一些其他参数选项。
我经常也会定义动作。这就是我在代码中所做的。
if ($PSCmdlet.ShouldProcess("$Target %Path% variable", "Remove $Path")) {
[System.Environment]::SetEnvironmentVariable("PATH", $Corrected, $Target)
}
正如您所看到的,您可以对目标和行动值进行创意。
不要忘记,您需要 [cmdletbinding()] 中的 SupportsShouldProcess 指令和 If 语句。顺便说一句,您可以在代码中添加任意数量的 WhatIf 语句。
清理我的道路
考虑到所有这些,以下是我如何使用我的命令。
请注意,它们是为协同工作而编写的。我可能会考虑修改 Get-EnvPath 函数以包含 Target 的过滤选项以及路径是否存在。创建 PowerShell 工具时,您需要考虑谁将使用它、如何使用以及他们的期望。由于我最有可能使用此工具来清理过时的路径,因此最好包含一个过滤选项,这样我就不必记住使用中间的Where-Object 表达式。但如果你有兴趣的话,我会把这个留给你。否则,是时候清理了。
您甚至可以考虑对 Repair-EnvPath 进行一些增强,例如提供有关删除内容的反馈或添加 -Passthru 参数。再说一次,我会把这个乐趣留给你。
我仍然更喜欢尽可能使用 cmdlet 和本机 PowerShell,但 .NET Framework 可以填补空白。您是否负责任地使用它取决于您。
猜你还喜欢
- 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