【问题标题】:Unable to search directory subtree with WQL query无法使用 WQL 查询搜索目录子树
【发布时间】:2018-04-10 00:55:54
【问题描述】:

我正在尝试查找已登录用户的所有 .PST 文件。但是,我似乎无法添加到“驱动器”的路径。我想搜索 C:\users\ + $env:UserName

下的所有文件

此命令似乎可以找到 C:\ 上的所有 PST 文件

$Res = Get-CimInstance CIM_DataFile -filter "Drive='c:' AND extension='pst'" -OutVariable m | Select-Object -Property Name

但是,当我将其更改为:

$Res = Get-CimInstance CIM_DataFile -filter "Drive='C:\users\' + $env:UserName AND extension='pst'" -OutVariable m | Select-Object -Property Name

甚至只是:

$Res = Get-CimInstance CIM_DataFile -filter "Drive='C:\users\' AND extension='pst'" -OutVariable m | Select-Object -Property Name

我收到以下错误:

Get-CimInstance : 无效查询 在 C:\Users\mntle2\Documents\PSTMig.ps1:2 char:8 + $Res = Get-CimInstance CIM_DataFile -filter "Drive='c:\users\' AND ex ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~ + CategoryInfo : InvalidArgument: (:) [Get-CimInstance], CimException + FullyQualifiedErrorId : HRESULT 0x80041017,Microsoft.Management.Infrastructure.CimCmdlets.GetCimInstanceCommand

有人可以帮我解决这个问题吗?

【问题讨论】:

  • 我对此进行了更多研究:CIM 对于 subtree 搜索效率低下,因此最好使用Get-ChildItem -Recurse 解决方案。此外,CIM 方法在来自1703 更新通道的至少一个 Windows 10 版本上损坏

标签: powershell powershell-4.0 wmi-query wql cim


【解决方案1】:

tl;dr

  • 为了在目录子树(而不是单个目录)中执行基于CIM的文件搜索,您必须使用LIKE 运算符将Path 属性与drive-relative 路径通配符 表达式进行比较。

    "Drive='C:' AND Extension='pst' AND Path LIKE '\\Users\\$env:USERNAME\\%'"
    
    • 但是这是低效且缓慢的,因为这种操作仍然会搜索所有文件。

      • 相比之下,在单个目录(而不是其子目录)中查找文件效率很高;例如:
        "Drive='C:' AND Extension='pst' AND Path='\\Users\\$env:USERNAME\\'"
        将在用户的主目录中高效搜索,但仅在其中直接(注意所需的尾随\\
    • 此外,此功能在 Windows 10 的某些版本中暂时中断(在1703 服务通道中的至少一个版本中观察到)。

  • 因此,为了在目录的子树中有效地定位文件,请改用Get-ChildItem(如果需要,使用Invoke-Command -ComputerName 进行远程处理) - 见下文。


基于Get-ChildItem 的首选、更快的替代方案:

$res = (Get-ChildItem -Recurse $HOME -File -Filter *.pst -OutVariable m).FullName

注意:严格来说,原始命令中的Select-Object -Property Name 不会像上面的命令那样直接返回完整的文件路径,而是将它们包装在.Name 属性包含它们的自定义对象中。支持>

为了在远程机器上运行此命令,请将其传递给Invoke-Command -ComputerName(来自提升会话,设置PS remoting):

$res = Invoke-Command -ComputerName $targetComputer { 
         (Get-ChildItem -Recurse $HOME -File -Filter *.pst -OutVariable m).FullName 
       }

次优 CIM 解决方案和基于 CIM/WMI 的文件搜索的一般提示:

这是 OP 问题的完整解决方案,但是,如上所述:

  • 效率低且慢

  • 它在1703 更新通道中的至少一个 Windows 10 版本上被破坏。

$filter = "Drive='C:' AND Extension='pst' AND Path LIKE '\\Users\\$env:USERNAME\\%'"
$Res = Get-CimInstance CIM_DataFile -Filter $filter -OutVariable m |
  Select-Object -Property Name

-Filter 参数接受 WQL 表达式,这可能很难构造:

  • Drive 只能接受一个驱动器规范,所以为了在特定的目录中搜索你必须使用Path来定位a - 驱动器相关 - 目录路径

    • 通常,请务必按驱动器缩小搜索范围,因为默认情况下会搜索所有个驱动器,包括网络驱动器,这可能非常慢。
  • Path 参数必须有其\ 字符。 加倍 (\\),因为\ 在字符串操作数中充当转义字符。

    • 如果使用运算符=指定路径,只搜索指定目录本身,但是, 是高效的;请注意,路径必须以 \\ 结尾。

    • 相比之下,为了搜索指定路径及其整个子树

      • 如上所述,这通常效率低下且缓慢,并且在某些 W10 版本中被破坏
      • 使用运算符LIKE 而不是=
      • 将 WQL 通配符 % 附加到路径中; (在 WQL(以及 WQL 所基于的 SQL)中,% 等同于通常的* 通配符,_ 对应于?

【讨论】:

    【解决方案2】:

    您可以尝试在查询中使用path 属性:

    $Res = Get-CimInstance CIM_DataFile -filter "Drive='C:' AND path='\\users\\' AND extension='pst'" -OutVariable m | Select-Object -Property Name
    

    【讨论】:

    • 似乎没有按预期运行。没有返回错误,但是也没有返回任何结果...... C:\users 中肯定有文件,所以它应该把它们捡起来? ://
    • 你确定C:\users下有扩展名为.pst的文件吗?你echo $Res的时候有输出吗?
    • path='\\users\\' 仅直接在 \users 中搜索,而不是在其子树中递归搜索。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-02-12
    • 1970-01-01
    • 1970-01-01
    • 2013-10-21
    • 2017-04-06
    • 2011-08-21
    • 1970-01-01
    相关资源
    最近更新 更多