【问题标题】:Powershell Array methods for looping and comparison?用于循环和比较的 Powershell Array 方法?
【发布时间】:2021-05-18 20:22:59
【问题描述】:

我有各种各样的计算机,我正在编写一个 Powershell 脚本,该脚本将网络共享与我的服务器上的计算机驱动程序的本地存储库一起安装在自己的单独目录中,作为每台计算机的品牌和型号(例如联想 E460、戴尔 Latitude E5450 等)。

这是我想要做的:

我想要获取计算机的信息(品牌和型号)并将其连接成一个字符串。然后我希望将该字符串引用到驱动程序目录的数组中,如果计算机制造商+型号匹配,我希望计算机下载该目录中的驱动程序。我来自 web 开发背景,在这里我通常会使用 JavaScript Array.prototype.filter() 方法来过滤数组以将 $computer$drivers 数组中的每个子项进行比较。

$computer = (gwmi Win32_ComputerSystem).Manufacturer + " " + (dwmi Win32_ComputerSystem).Model
$drivers = Get-ChildItem \\zapp\pc\!Drivers

完成此任务的最佳方法是 Powershell? Powershell 有类似 JavaScript 的过滤和比较 Array 方法吗?或者Foreach-match-eq 是最有效的编写方式吗?

谢谢!

【问题讨论】:

  • 看看.Where()收集方法。 [咧嘴]

标签: arrays powershell if-statement foreach foreach-object


【解决方案1】:

你好,晚上好。

直到有人比我聪明得多(不会很长),我可以尝试为您指出正确的方向。

您实际上有几个选择。您可以使用依赖于布尔值(布尔值 - 只是一种时髦的说法)的条件语句,以及将 Where-Object 与一些运算符结合使用。

让我先发布这个,这样它就不会在我身上崩溃(我的屏幕裂了,它的行为很不稳定)。我们将从Switch 声明开始。如果满足一个条件,就做点什么。

$computer = (gwmi Win32_ComputerSystem).Manufacturer + " " + (gwmi Win32_ComputerSystem).Model
$drivers = Get-ChildItem \\zapp\pc\!Drivers | Select-Object -ExpandProperty Name
    Switch ($drivers){
        "$computer" {"Found: $_" }
        
        }

我回来了! 所以,回到我离开的地方......你可以使用 switch 语句,它会在满足特定条件时执行某些操作;在这种情况下,一旦它检测到字符串与您要查找的内容匹配,它就会从远程 PC 执行复制项到本地 PC。见下文:

$computer = (gwmi Win32_ComputerSystem).Manufacturer + " " + (gwmi Win32_ComputerSystem).Model
    Switch (Get-ChildItem \\zapp\pc\!Drivers){
        "$computer" {Copy-Item -Path $_.FullName -Destination C:\DriverStore }
            }

使用Foreach 循环,我们可以遍历每个文件并尝试使用if 语句匹配您传递给它的值,在远程PC 上执行Copy-Item 一旦找到您的。

Foreach($file in (Get-ChildItem \\zapp\pc\!Drivers)){
    if($file -match  $computer){ Copy-Item -Path $file.FullName -Destination C:\DriverStore}
        }

接下来,我们只是在-match 运算符的帮助下将文件传送到Where-Object,将为其指定的值与左侧的对象进行匹配。最后使用Foreach-Object cmdlet(不要与Foreach 混淆)和-Process 参数来运行输入对象内的每个元素。然后将与您的 PC 匹配的文件夹从远程 PC 复制到您的文件夹。

$computer = (gwmi Win32_ComputerSystem).Manufacturer + " " + (gwmi Win32_ComputerSystem).Model
Get-ChildItem \\zapp\pc\!Drivers | Where-Object {$_.Name -match $computer} |ForEach-Object -process{ Copy-Item -Path $_.fullname -Destination C:\DriverStore}

希望这是有道理的,可以让您走上正轨。为了简单起见,我没有提到其他几个,但@Lee_Daily 确实提到了.Where() 方法,它也可以在这种情况下使用。

【讨论】:

  • 对不起,我的电脑死机了。将修复它并完成它,太多了,无法在我的手机上输入。
  • 感谢您抽出宝贵时间写出此回复!它的打字很好而且很全面。虽然我没有将它作为我的最终解决方案,但我确实学到了一些东西。再次感谢。
【解决方案2】:

您应该能够在没有数组或任何(显式)过滤的情况下完成此操作。

首先,为了效率,我会像这样初始化$computer...

$computerSystem = gwmi Win32_ComputerSystem -Property 'Manufacturer', 'Model'
$computer = $ComputerSystem.Manufacturer + " " + $computerSystem.Model

如果你想变得花哨,你也可以这样做......

$computer = $computerSystem.Manufacturer, $computerSystem.Model -join " "

现在,您可以让文件系统为您执行此操作,而不是自己管理和搜索驱动程序目录数组...

$driverDirectory = Get-Item -LiteralPath "\\zapp\pc\!Drivers\$computer"

如果指定路径中不存在对象,这将引发错误。你可以这样对抗...

$driverDirectory = Get-Item -LiteralPath "\\zapp\pc\!Drivers\$computer" -ErrorAction SilentlyContinue
if ($null -ne $driverDirectory)
{
    # $driverDirectory exists; copy drivers
}

...或者像这样...

$driverDirectoryPath = "\\zapp\pc\!Drivers\$computer"
if (Test-Path -Path $driverDirectoryPath)
{
    # $driverDirectoryPath exists; copy drivers
}

这样做的唯一真正缺点是,如果!Drivers\ 是一个巨大的目录(即数千个子目录)并且您反复查找驱动程序目录,那么该目录枚举可能会明显变慢而不是自己将结果缓存在数组中。我猜你的脚本只会复制适用于本地系统的驱动程序,所以就像我说的,我会让文件系统做它最擅长的事情。

【讨论】:

  • 这很漂亮,正是我所需要的。谢谢你。如果我可能会问,您为什么要以您的方式初始化 $computer 和 make/model 变量?为什么这样更有效率?另外,我从来没有遇到过-ne。我假设在这种情况下它的意思是“不相等”。你能确认一下吗?
  • 是的,-ne 是“不等于”运算符。任何 WMI 操作往往都很慢,在原始代码中,您执行两个操作:一个检索完整的 Win32_ComputerSystem 对象并获取其 Manufacturer 属性,第二个检索另一个完整的 Win32_ComputerSystem 对象并获取其 @ 987654334@ 财产。在我的代码中,我只执行一次这样的检索,然后使用同一个对象来获取这两个属性。我还使用-Property 参数仅指定我将要访问的属性,这样就不会打扰填充其他属性。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-02-11
  • 2018-07-09
  • 1970-01-01
  • 2012-09-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多