无法从get-filehash获取输出

3
我正在寻找一个可靠的命令行方法来获取Windows中文件的SHA256哈希值。据我所知,可以通过PowerShell下的Microsoft's Get-FileHash cmdlet来完成此操作。我已经浏览了若干网站的示例并查看了Microsoft自己的文档。在Windows Server 2012上,以下语法似乎可以工作:
Get-FileHash myfile.txt -Algorithm SHA256

该命令运行没有错误,但是没有输出。如果我将输出发送到文件,那么生成的文件没有任何内容。我也看到过一些例子是将输出导向Format-List;我尝试过了,但还是没有任何东西。我也尝试使用无效参数运行该命令,同样也没有任何反应。
我可以考虑使用另一个程序,但由于业务需求,必须下载支持的程序。

尝试使用以下命令:Get-FileHash .\myfile.txt -Algorithm SHA256,如果失败,则使用以下命令:$hash=Get-FileHash .\myfile.txt -Algorithm SHA256。 - Eric Walker
关于第一个建议,我尝试过了,但无论我提供什么参数都没有用。至于第二个建议,操作系统接受语法,但当我输出$hash时,里面什么也没有。 - Alan Frank
你的 $PSVersionTable.PSVersion 值是多少? - Eric Walker
主要版本号=3,次要版本号=0,构建号=-1,修订号=-1 - Alan Frank
你有没有其他使用相同平台的计算机进行交叉测试? - sodawillow
3个回答

9
我正在使用PowerShell 4.0,刚遇到了与Get-FileHash返回null输出的相同问题。我的问题的原因与OP不同,但我已经找到了解决方法,并且认为我应该发布我的发现,以供任何试图解决Get-FileHash返回null输出(或看似不正确的输出)问题的人参考。
只有当目标文件的路径包含方括号[]并且这些方括号包含零个字符或2个或多个字符时,才会出现此问题(对我而言)。
编辑:现在我知道为什么会出现这种情况。字符串被解释为正则表达式(RegEx),所以方括号[]具有它们的特殊RegEx含义。-LiteralPath告诉PowerShell将字符串解释为简单匹配(没有RegEx)。
考虑以下引用4个现有文本文件(假设)的路径:
C:\Test\My Text.txt
C:\Test\My [Text].txt
C:\Test\My [Te]xt.txt
C:\Test\My Text[].txt

以下命令会产生正常输出:
Get-FileHash "C:\Test\My Text.txt"

但是如果使用以下命令,将会得到空输出:

Get-FileHash "C:\Test\My [Text].txt"
Get-FileHash "C:\Test\My [Te]xt.txt"
Get-FileHash "C:\Test\My Text[].txt"

这可以通过使用-LiteralPath开关来解决。例如:
Get-FileHash -LiteralPath "C:\Test\My [Text].txt"

使用-LiteralPath开关时,变量会按正常方式展开。例如:

(Get-ChildItem C:\Test).FullName | ForEach {
Get-FileHash -LiteralPath $_
}

如果方括号之间只有一个字符,使用Get-FileHash时将忽略方括号。

考虑以下路径,它们引用3个现有的文本文件(假设每个文件都具有唯一的哈希值):

C:\Test\My Text.txt
C:\Test\My Tex[t].txt
C:\Test\My[ ]Text.txt

Get-FileHash以完全相同的方式解释以下三个命令(路径被解释为C:\Test\My Text.txt),因此每个命令具有完全相同的输出,尽管每个文件都具有其自己独特的哈希值:

Get-FileHash "C:\Test\My Text.txt"
Get-FileHash "C:\Test\My Tex[t].txt"
Get-FileHash "C:\Test\My[ ]Text.txt"

PS:我是一位非常新的程序员,请原谅我使用术语不当的地方。


好的指针,但请注意,使用(隐含的)-Path参数时,参数将被解释为通配符表达式,而不是正则表达式。 - mklement0

3
Get-FileHash需要Windows PowerShell 4.0。根据您的评论,您使用的是版本3,在Win2012(非R2)上默认使用该版本。请点击此处检查您的PS版本。 您可以将Win2012(非R2)上的PS更新至4.0版本或使用Win2012 R2。
如果您在版本3的系统上直接运行Get-FileHash,您应该会得到:
PS C:\> Get-FileHash
Get-FileHash : The term 'Get-FileHash' is not recognized as the name of a cmdlet, function, script file, or operable
program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At line:1 char:1
+ Get-FileHash
+ ~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (Get-FileHash:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

在低版本的PS中,您可以使用此函数。

Function Get-FileHashTSO([String] $FileName,$HashName = "SHA1") 
{
$FileStream = New-Object System.IO.FileStream($FileName,[System.IO.FileMode]::Open) 
$StringBuilder = New-Object System.Text.StringBuilder 
[System.Security.Cryptography.HashAlgorithm]::Create($HashName).ComputeHash($FileStream)|%{[Void]$StringBuilder.Append($_.ToString("x2"))} 
$FileStream.Close() 
$StringBuilder.ToString() 
}

将其存储为 .ps 文件(例如 Get-FileHashTSO.ps1),并像这样调用它

powershell -command "& { . C:\myScripts\Get-FileHashTSO.ps1 ; Get-FileHashTSO "C:\someLocation\someFile.iso" "SHA1" }"

0

我使用以下方法计算了驱动器上所有文件的哈希值,并将它们导出为 .csv 文件:

Get-ChildItem C: -Recurse |
    Get-FileHash |
    Export-Csv -Path C:\Users\yourname\Documents\Output\hashes.csv -NoTypeInformation
    Import-Csv -Path C:\Users\yourname\Documents\Output\hashes.csv

为什么它有效(我认为):

Get-ChildItem <--获取路径下的所有内容,在这种情况下是C:,而-Recurse则获取文件夹中的所有文件。如果需要,您可以添加限制。

Get-FileHash <--在你说要获取这些文件之后,你要计算哈希值

Export-Csv <--表示,我们将哈希值作为逗号分隔值文件发送出去,这非常有帮助,-Path表示将其放在这里,-NoTypeInformation只是从.csv文件顶部删除#TYPE行,PowerShell 6之前的版本需要这样做。

Import-Csv <--表示,将该数据导入到此-Path的文件中

确保在运行脚本之前在该位置创建了.csv文件。脚本不会为您创建容器。无需在运行之间清除.csv文件中的数据,它会自动清除。

我不是真正的程序员,因此解释可能有点冗长。希望能帮助其他人。没有Stack Overflow论坛,我不会想出来!谢谢大家!!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接