Reputation: 119
I had previously asked a question about this script, but the portion I needed help with got fixed, so I decided to ask a new question.
I am working on a PS script that takes the hash of each file in a directory and a few specific files located elsewhere, combines them into a csv, and then compares them with a previously captured baseline. Then there is a for each loop in which each file with a differing hash is output to an XML file with info including algorithm, hash, filepath, and last modified date.
### 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
I received excellent help from user Mathieu Buisson, but I have encountered another error.
My understanding is that the loop would take each file that was found different, cast the fields I need, and then append them all to a file. The last line converts these to xml and outputs them.
My issue is the output. The baseline and difference files are created correctly, and the success/fail.txt files are generated and accurate. The problem is that the xml either comes up blank, or only lists files that didnt previously exist. To that extent, it has only ever listed a single file in the xml, even when PS console shows two or more.
What can I do to get a full list of changed files in XML?
If there is anymore information I need to provide, please let me know.
Thanks so much for any help!!
Upvotes: 1
Views: 207
Reputation: 1413
$HashCRQ = Get-FileHash $CRQLocation -Algorithm MD5
$HashCRQ | Export-Csv -append -Path $HashCompare -NoTypeInformation -Force
You are adding the hash of the file d:\Change Request.csv to $HashCompare.
$HashScript = Get-FileHash $ScriptLocation -Algorithm MD5
$HashScript | Export-Csv -append -Path $HashCompare -NoTypeInformation -Force
You are adding the hash of the file d:\FileChecker.ps1 to $Hashcompare
These 2 files are not located $FileDir, so I don't understand why you are adding them to $HashCompare because then, when you compare $HashCompare to $Hashstore, you are comparing the content of $FileDir with the content of $FileDir + 2 other files. I am assuming that $Hashtore contains the hashes for the contents of $FileDir, but I can only assume because the script doesn't tell how the content of $Hashstore has been created.
$HashNew | Export-Csv -Path $HashTemp -NoTypeInformation -Force
If there are differences, you send the hashes for the contents of $FileDir (without the 2 additional files mentioned above) to $Hashtemp. But the file $HashTemp is not used anywhere else in the script.
So, what do you want to compare ? $HashStore with the hashes of the current contents of $fileDir + $HashCRQ + $HashCRQ ? If so, $Diffs is correct as it is. Or $HashStore with the hashes of the current contents of $fileDir ? If so, $Diffs should be :
Compare-Object -ReferenceObject (Import-Csv $Hashstore) -DifferenceObject (Import-Csv $HashTemp)
Regarding the XML output, $DiffObj is created inside the Foreach loop so it is a representation of each individual different file, and it changes everytime we go through the loop. So $DiffObj is actually a single object, that's why ConvertTo-Xml will only ever show one object at most.
You need to do this :
Create a variable as an empty array , which will accumulate each iteration of $DiffObj :
$DiffObjCollection = @()
Note : You need to define this variable outside of the foreach loop, otherwise it will be reset as an empty array every time we go through the loop.
Then, we store each individual iteration of $DiffObj inside this "Collection variable" :
$DiffObjCollection += $DiffObj
Note: This needs to be at the end of the Foreach loop , but inside of it, to make sure we add $DiffObj to $DiffObjCollection every time we go through the loop.
Finally, after having gone through every different files, we can use our "collection variable" and convert this collection of objects to XML :
$DiffObjCollection | ConvertTo-Xml -As String -NoTypeInformation | Out-File $OutPut
Note: This needs to be outside of the Foreach loop and at the end of the script.
Upvotes: 2