选择字符串不显示与 get-appxPackage 的所有匹配项



我使用Get-AppxPackage在我的电脑上安装了所有的软件包,并试图在使用Select-String之前和之后用N行查找其中的所有匹配项。

但是,select字符串只显示一行匹配项,也没有显示所有匹配项。只有当我通过管道从Get-AppxPackage输出时才会发生这种情况,而不是当我将其写入文件然后执行cat <filename> | select-string ...时。

正如您在下面的示例中看到的,使用pipe和cat的两个结果。我对cat的结果感兴趣,即关于该应用程序的详细信息。

那么我在这里做错了什么?为什么输出不同?


示例(每个人都应该有MS Edge,所以我将使用它作为示例(:

PS > Get-AppxPackage | Select-String -pattern 'edge' -context 3, 3 -allmatches
Microsoft.Windows.StartMenuExperienceHost_10.0.18362.329_neutral_neutral_cw5n1h2txyewy
Microsoft.Windows.Cortana_1.13.0.18362_neutral_neutral_cw5n1h2txyewy
Microsoft.AAD.BrokerPlugin_1000.18362.329.0_neutral_neutral_cw5n1h2txyewy
> Microsoft.MicrosoftEdge_44.18362.329.0_neutral__8wekyb3d8bbwe
Microsoft.Windows.CloudExperienceHost_10.0.18362.329_neutral_neutral_cw5n1h2txyewy
Microsoft.Windows.ContentDeliveryManager_10.0.18362.329_neutral_neutral_cw5n1h2txyewy
Windows.CBSPreview_10.0.18362.329_neutral_neutral_cw5n1h2txyewy
Microsoft.Windows.Apprep.ChxApp_1000.18362.329.0_neutral_neutral_cw5n1h2txyewy
Microsoft.Win32WebViewHost_10.0.18362.329_neutral_neutral_cw5n1h2txyewy
Microsoft.PPIProjection_10.0.18362.329_neutral_neutral_cw5n1h2txyewy
> Microsoft.MicrosoftEdgeDevToolsClient_1000.18362.329.0_neutral_neutral_8wekyb3d8bbwe
Microsoft.LockApp_10.0.18362.329_neutral__cw5n1h2txyewy
> Microsoft.EdgeDevtoolsPlugin_10.0.18362.329_neutral_neutral_cw5n1h2txyewy
Microsoft.ECApp_10.0.18362.329_neutral__8wekyb3d8bbwe
Microsoft.CredDialogHost_10.0.18362.329_neutral__cw5n1h2txyewy
Microsoft.BioEnrollment_10.0.18362.329_neutral__cw5n1h2txyewy
PS > cat .appx-packages.txt | select-string -pattern 'edge' -context 3, 3 -allmatches
SignatureKind     : System
Status            : Ok
> Name              : Microsoft.MicrosoftEdge
Publisher         : CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US
Architecture      : Neutral
ResourceId        :
Version           : 44.18362.329.0
> PackageFullName   : Microsoft.MicrosoftEdge_44.18362.329.0_neutral__8wekyb3d8bbwe
> InstallLocation   : C:WindowsSystemAppsMicrosoft.MicrosoftEdge_8wekyb3d8bbwe
IsFramework       : False
> PackageFamilyName : Microsoft.MicrosoftEdge_8wekyb3d8bbwe
PublisherId       : 8wekyb3d8bbwe
IsResourcePackage : False
IsBundle          : False
SignatureKind     : System
Status            : Ok
> Name              : Microsoft.MicrosoftEdgeDevToolsClient
Publisher         : CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US
Architecture      : Neutral
ResourceId        : neutral
Version           : 1000.18362.329.0
> PackageFullName   : Microsoft.MicrosoftEdgeDevToolsClient_1000.18362.329.0_neutral_neutral_8wekyb3d8bbwe
> InstallLocation   : C:WindowsSystemAppsMicrosoft.MicrosoftEdgeDevToolsClient_8wekyb3d8bbwe
IsFramework       : False
> PackageFamilyName : Microsoft.MicrosoftEdgeDevToolsClient_8wekyb3d8bbwe
PublisherId       : 8wekyb3d8bbwe
IsResourcePackage : False
IsBundle          : False
SignatureKind     : System
Status            : Ok
> Name              : Microsoft.EdgeDevtoolsPlugin
Publisher         : CN=Microsoft Windows, O=Microsoft Corporation, L=Redmond, S=Washington, C=US
Architecture      : Neutral
ResourceId        : neutral
Version           : 10.0.18362.329
> PackageFullName   : Microsoft.EdgeDevtoolsPlugin_10.0.18362.329_neutral_neutral_cw5n1h2txyewy
> InstallLocation   : C:WindowsSystemAppsMicrosoft.EdgeDevtoolsPlugin_cw5n1h2txyewy
IsFramework       : False
> PackageFamilyName : Microsoft.EdgeDevtoolsPlugin_cw5n1h2txyewy
PublisherId       : cw5n1h2txyewy
IsResourcePackage : False
IsBundle          : False

tl;dr

从PowerShell v7.3开始,要使Select-String通过控制台(终端(中看到的相同富字符串表示搜索非字符串输入,必须首先将输入管道传输到oss

Get-AppxPackage | oss | Select-String -Pattern 'edge' -Context 3, 3

注:

  • 正如GitHub第10726期中所讨论的,这个中间步骤应该是而不是

  • 事实上,当您将非字符串输入管道传输到外部程序时,例如findstr.exe,这已经没有必要了,因为PowerShell随后隐式使用富字符串表示,因为它必须将输入作为(有意义的(字符串发送[1]

  • 顺便说一句:Select-String可以方便地搜索文本行,使用oss可以搜索对象的格式化字符串表示,而不必知道或关心它们的特定结构。

    • 但是,如果确实了解结构,则通过不同的cmdlet(如Where-ObjectSelect-Object(使用OO技术会更健壮。例如,以下程序根据.Name属性过滤包,然后只选择感兴趣的属性:

      # Note: Get-AppXPackage *edge* would obviate the need for Where-Object
      Get-AppXPackage | 
      Where-Object Name -like *edge* |
      Select-Object Name, Version
      

背景信息:

Select-String,当给定输入而不是字符串时,在查找给定模式之前,对每个输入对象使用简单的.ToString()字符串化[2]

在您的情况下,Get-AppXPackage字符串输出的[Microsoft.Windows.Appx.PackageManager.Commands.AppxPackage]实例将变为完整的包名称(例如,Microsoft.MicrosoftEdge_44.18362.387.0_neutral__8wekyb3d8bbwe(,这解释了您的输出。

为了使Select-String中搜索对象-的显示字符串表示,因为它们将打印到控制台,并且它们将出现在使用>/Out-File保存的文件中(catOut-File在Windows上的内置别名(-令人惊讶的是,
使用Out-String -Stream作为中间管道段;从PowerShell v5开始,如果内存可用,为了简洁起见,可以使用内置的包装函数oss

# oss is a built-in wrapper function for Out-String -Stream
Get-AppxPackage | oss | Select-String -Pattern 'edge' -Context 3, 3

Out-String使用PowerShell的格式化系统生成输入对象的人性化显示表示,与默认控制台输出、Format-*cmdlet和>/Out-File的方式相同。
-Stream导致输出行通过管道逐个发送,以便Select-String可以匹配各个行。


考虑到该解决方案既不明显又繁琐,如果Select-String直接支持这种行为会很好,理想情况下默认,但至少在通过开关参数选择加入的基础上-请参阅GitHub上的功能请求#10726-如果您同意,请在那里投票支持该提案。


[1]自v7.3起,仅PowerShell";说出文本";当与外部程序通信时,因此在向非字符串对象传递数据时,它必须创建非字符串对象的字符串表示:请参阅此答案。虽然默认以显示此类对象的字符串表示形式是有意义的,但请注意,此表示形式不适用于编程处理;对于后者,最好显式输出结构化文本格式,例如通过ConvertTo-Json输出JSON

[2]更准确地说,.psobject.ToString()是按原样调用的,或者-如果对象的ToString方法支持IFormatProvider类型的参数-则为.psobject.ToString([cultureinfo]::InvariantCulture),以获得区域性不变表示-有关详细信息,请参阅此答案

相关内容

  • 没有找到相关文章

最新更新