Powershell:For Each Loop和XML输出的麻烦

时间:2014-08-21 20:40:58

标签: xml hash powershell-v4.0

我之前曾询问过有关此脚本的问题,但我需要帮助的部分已修复,所以我决定提出一个新问题。

我正在开发一个PS脚本,它将目录中的每个文件的哈希值和位于其他位置的一些特定文件组合在一起,将它们组合成一个csv,然后将它们与先前捕获的基线进行比较。然后每个循环都有一个循环,其中每个具有不同散列的文件都输出到XML文件,其中包含算法,散列,文件路径和最后修改日期等信息。

### This PowerShell 4.0 script compares the MD5 hash of each file in    ###
### a directory in it's current state and compares it with a baseline   ###
### copy taken previously. If no baseline exists, a new one is created. ###
### ***The first time this script is run, a false-positive report       ###

# Variables
$DateTime = Get-Date -format M.d.yyyy.hh.mm.ss
$Hashstore = "d:\Baseline.txt"
$HashCompare = "d:\Difference_$DateTime.txt"
$HashTemp = "d:\hashtemp_$DateTime.txt"
$FileDir = "d:\scripts\"
$CRQLocation = "d:\Change Request.csv"
$ScriptLocation = "d:\FileChecker.ps1"
$OutPut = "d:\Results_$DateTime.xml"

# Check if Baseline.txt Exists
If (Test-Path $Hashstore)
    # // File exists
    {
}
Else {
     # // File does not exist - Should never happen!
     $RefreshHash = dir $FileDir -Recurse | Get-FileHash -Algorithm MD5
     $RefreshScript = Get-FileHash $ScriptLocation -Algorithm MD5
     $RefreshCRQ = Get-FileHash $CRQLocation -Algorithm MD5

}

## Generate new Compare Hash.txt
$HashNew = dir $FileDir -Recurse | Get-FileHash -Algorithm MD5
$HashNew | Export-Csv -Path $HashCompare -NoTypeInformation -Force

#Get hash of this script
$HashScript = Get-FileHash $ScriptLocation -Algorithm MD5
$HashScript | Export-Csv -append -Path $HashCompare -NoTypeInformation -Force

#Get hash of CRQ Log
$HashCRQ = Get-FileHash $CRQLocation -Algorithm MD5
$HashCRQ | Export-Csv -append -Path $HashCompare -NoTypeInformation -Force

# Get Hash of baseline.txt
$HashBaseline = Get-FileHash -Path $Hashstore -Algorithm MD5

# Get Hash of hashcompare.txt
$HashDiff = Get-FileHash -Path $HashCompare -Algorithm MD5

# If changed, output hash to storage, and flag changes
If ($HashBaseline.hash -eq $HashDiff.hash) {
    Add-Content -Path D:\success.$DateTime.txt -Value " Source Files ARE EQUAL </p>"
}
Else {
    Add-Content -Path D:\failure.$DateTime.txt -Value "Source Files NOT EQUAL </p>"
    $HashNew | Export-Csv -Path $HashTemp -NoTypeInformation -Force

    # Storing a collection of differences in $Diffs
    $Diffs = Compare-Object -ReferenceObject (Import-Csv $Hashstore) -DifferenceObject (Import-Csv $HashCompare)

    Foreach ($Diff in $Diffs) {
        $DiffHashInfo = $Diff | Select-Object -ExpandProperty InputObject
        $DiffFileInfo =  Get-ChildItem -Path $DiffHashInfo.Path

        # Creating a list of properties for the information you need
        $DiffObjProperties = [ordered]@{'Algorithm'=$DiffHashInfo.Algorithm
                               'Hash'=$DiffHashInfo.Hash
                               'File Path'=$DiffFileInfo.FullName
                               'Last edit time'=$DiffFileInfo.LastWriteTime
                               }

        # Building a custom object from the list of properties in $DiffObjProperties
        $DiffObj = New-Object -TypeName psobject -Property $DiffObjProperties
        $DiffObj
    }
}
$DiffObj | ConvertTo-Xml -As String -NoTypeInformation | Out-File $OutPut

我收到了用户Mathieu Buisson的出色帮助,但我遇到了另一个错误。

我的理解是循环会将每个发现不同的文件,转换为我需要的字段,然后将它们全部附加到文件中。最后一行将这些转换为xml并输出它们。

我的问题是输出。正确创建基线和差异文件,生成成功/失败.txt文件并准确无误。问题是xml要么是空白的,要么只列出以前不存在的文件。在这种程度上,它只在xml中列出了一个文件,即使PS控制台显示两个或更多。

如何获取XML中已更改文件的完整列表?

如果我需要提供更多信息,请告诉我。

非常感谢任何帮助!!

1 个答案:

答案 0 :(得分:1)

$HashCRQ = Get-FileHash $CRQLocation -Algorithm MD5
$HashCRQ | Export-Csv -append -Path $HashCompare -NoTypeInformation -Force

您正在将文件d:\ Change Request.csv的哈希添加到$ HashCompare。

$HashScript = Get-FileHash $ScriptLocation -Algorithm MD5
$HashScript | Export-Csv -append -Path $HashCompare -NoTypeInformation -Force

您正在将文件d:\ FileChecker.ps1的哈希添加到$ Hashcompare

这2个文件不是$ FileDir,所以我不明白你为什么要将它们添加到$ HashCompare,因为当你将$ HashCompare与$ Hashstore进行比较时,你将$ FileDir的内容与$ FileDir + 2个其他文件的内容。 我假设$ Hashtore包含$ FileDir内容的哈希值,但我只能假设因为脚本没有说明$ Hashstore的内容是如何创建的。

$HashNew | Export-Csv -Path $HashTemp -NoTypeInformation -Force

如果存在差异,则将$ FileDir的内容的散列(没有上面提到的2个附加文件)发送到$ Hashtemp。 但是文件$ HashTemp不会在脚本中的任何其他地方使用。

那么,你想要比较什么? $ HashStore与当前内容的哈希值$ fileDir + $ HashCRQ + $ HashCRQ? 如果是这样,$ Diffs就是正确的。 或$ HashStore与$ fileDir的当前内容的哈希? 如果是这样,$ Diffs应该是:

Compare-Object -ReferenceObject (Import-Csv $Hashstore) -DifferenceObject (Import-Csv $HashTemp)

关于XML输出,在Foreach循环内部创建了$ DiffObj,因此它是每个单独的不同文件的表示,并且每次循环时它都会更改。 所以$ DiffObj实际上是一个单独的对象,这就是为什么ConvertTo-Xml最多只会显示一个对象。

你需要这样做:

将变量创建为空数组,这将累积$ DiffObj的每次迭代:

$DiffObjCollection = @()

注意:您需要在foreach循环之外定义此变量,否则每次循环时它都将重置为空数组。

然后,我们将$ DiffObj的每个迭代存储在这个&#34; Collection变量&#34; :

$DiffObjCollection += $DiffObj

注意:这需要在Foreach循环结束时,但在其中,确保每次循环时都将$ DiffObj添加到$ DiffObjCollection。

最后,在浏览完每个不同的文件后,我们可以使用我们的&#34;集合变量&#34;并将此对象集合转换为XML:

$DiffObjCollection | ConvertTo-Xml -As String -NoTypeInformation | Out-File $OutPut

注意:这需要在Foreach循环之外和脚本的末尾。