Solved

powershell INF compare.

Posted on 2013-05-20
22
783 Views
Last Modified: 2013-06-14
I am trying to build a query that will go in a compare two inf files that may have different delimiters so that I can then create a table and display it by converting it to an HTML file.

Any ideas?  The files that I am trying to compare are created by secedit.exe when the local group policy is exported..

I am able to compare the files when its X = Y but when it starts going x=y,z thats where I get lost..

I found this function and maybe thought it could be made to work for my needs..
Function Get-IniContent
{
    <#
    .Synopsis
        Gets the content of an INI file
        
    .Description
        Gets the content of an INI file and returns it as a hashtable
        
    .Notes
        Author    : Oliver Lipkau <oliver@lipkau.net>
        Blog      : http://oliver.lipkau.net/blog/
        Date      : 2010/03/12
        Version   : 1.0
        
        #Requires -Version 2.0
        
    .Inputs
        System.String
        
    .Outputs
        System.Collections.Hashtable
        
    .Parameter FilePath
        Specifies the path to the input file.
        
    .Example
        $FileContent = Get-IniContent "C:\myinifile.ini"
        -----------
        Description
        Saves the content of the c:\myinifile.ini in a hashtable called $FileContent
    
    .Example
        $inifilepath | $FileContent = Get-IniContent
        -----------
        Description
        Gets the content of the ini file passed through the pipe into a hashtable called $FileContent
    
    .Example
        C:\PS>$FileContent = Get-IniContent "c:\settings.ini"
        C:\PS>$FileContent["Section"]["Key"]
        -----------
        Description
        Returns the key "Key" of the section "Section" from the C:\settings.ini file
        
    .Link
        Out-IniFile
    #>
    
    [CmdletBinding()]
    Param(
        [ValidateNotNullOrEmpty()]
        [ValidateScript({(Test-Path $_) -and ((Get-Item $_).Extension -eq ".inf")})]
        [Parameter(ValueFromPipeline=$True,Mandatory=$True)]
        [string]$FilePath
    )
    
    Begin
        {Write-Verbose "$($MyInvocation.MyCommand.Name):: Function started"}
        
    Process
    {
        Write-Verbose "$($MyInvocation.MyCommand.Name):: Processing file: $Filepath"
            
        $ini = @{}
        switch -regex -file $FilePath
        {
            "^\[(.+)\]$" # Section
            {
                $section = $matches[1]
                $ini[$section] = @{}
                $CommentCount = 0
            }
            "^(;.*)$" # Comment
            {
                if (!($section))
                {
                    $section = "No-Section"
                    $ini[$section] = @{}
                }
                $value = $matches[1]
                $CommentCount = $CommentCount + 1
                $name = "Comment" + $CommentCount
                $ini[$section][$name] = $value
            } 
            "(.+?)=(.*)" # Key
            {
                if (!($section))
                {
                    $section = "No-Section"
                    $ini[$section] = @{}
                }
                $name,$value = $matches[1..2]
                $ini[$section][$name] = $value
            }
        }
        Write-Verbose "$($MyInvocation.MyCommand.Name):: Finished Processing file: $path"
        Return $ini
    }
        
    End
        {Write-Verbose "$($MyInvocation.MyCommand.Name):: Function ended"}
}

Open in new window


regards,

Erica
GptTmpl.inf.txt
0
Comment
Question by:Diazer
  • 12
  • 7
  • 3
22 Comments
 
LVL 4

Expert Comment

by:bepsoccer1
ID: 39184907
So have you tried something like compare-object (Get-IniContent A.ini) (Get-IniContent B.ini)?
0
 

Author Comment

by:Diazer
ID: 39185025
bepsoccer1,

When I type that it does nothing..
With the above script I can get it to add the values to a hash table, sort them and see there values but when it comes to comparing them is when I get lost..

Regards,
Erica
0
 
LVL 4

Expert Comment

by:bepsoccer1
ID: 39185059
When you say it does nothing you mean it gives no output?  Generally that means they are the same.  I don't know enough about the Get-INIContent function here, but just for more info does compare-object (Get-IniContent A.ini) (Get-IniContent B.ini) -includeEqual produce any results?
0
Netscaler Common Configuration How To guides

If you use NetScaler you will want to see these guides. The NetScaler How To Guides show administrators how to get NetScaler up and configured by providing instructions for common scenarios and some not so common ones.

 

Author Comment

by:Diazer
ID: 39185284
I checked with windiff and they are not the same..  so I am at a loss.
0
 
LVL 4

Expert Comment

by:bepsoccer1
ID: 39185356
are you just trying to identify the differences?  If so, check out Beyond Compare, http://www.scootersoftware.com/download.php?c=kb_morerules
0
 

Author Comment

by:Diazer
ID: 39185393
I know that there are many utilities but what I am doing is going to compare the attached INF file as the base with a Unknown Inf file and then pipe the differences into an HTML file and this has to be done with little user internventions, I know that software exists out there but I also know that there has to be a way to put it data in an array or hashtable to compare it..
0
 
LVL 69

Expert Comment

by:Qlemo
ID: 39186013
The issue is that the hash table again contains hash tables. Compare-Object cannot compare that, it can't even compare hash tables, AFAIK. So we have to "flatten" that to something we can compare:
function flatten-hash ($hash)
{ foreach ($section in $hash.keys)
   { foreach ($key in $hash[$section].keys)
     { foreach ($value in $hash[$section][$key])
       {  New-Object PSObject -Property @{section = $section; key = $key; value = $value; String = "[$Section] $Key = $value" }
}}}}

$ini1 = flatten-hash (Get-IniContent GptTmpl.Inf)
$ini2 = flatten-hash (Get-IniContent GptReal.Inf)
Compare-Object -PassThru $ini1 $ini2 -Property String

Open in new window

That's not the best one can do, but should suffice to see differences.
0
 

Author Comment

by:Diazer
ID: 39186031
Qlemo,

Brilliant..  So how do I output that information to a HTML file?

Reason being is then I can do the Colorize and make things show up as the SideIndicator arrows just confuse the user.
0
 
LVL 69

Expert Comment

by:Qlemo
ID: 39186103
The result of the compare contains the complete object (because of -PassThru, plus the side indicator. A common transformation is to have one object on the left, the other on the right, depending on the side indicator. That table can then be converted into HTML.
Compare-Object -PassThru $ini1 $ini2 -Property String | % {
  if ($_.SideIndicator -eq "=>") { $obj = New-Object PSObject -Property @{LeftSection = $_.Section; LeftKey = $_.Key; LeftValue = $_.Value; RightSection = ""; RightKey = ""; RightValue = ""}}
  if ($_.SideIndicator -eq "<=") {
    if (!$obj) {
      $obj = New-Object PSObject -Property @{LeftSection = ""; LeftKey = ""; LeftValue = ""; RightSection = $_.Section; RightKey = $_.Key; RightValue = $_.Value }
    } else {
      $obj.RightSection, $obj.RightKey, $obj.RightValue = $_.Section, $_.Key, $_.Value
    }
    $obj
  }
} | select LeftSection, LeftKey, LeftValue, RightSection, RightKey, RightValue | ft

Open in new window

Again, that is not perfect, as it relies on the exact sequence as compare-object writes out differences. If you change one of the key names in GptReal.ini, you'll see.
0
 

Author Comment

by:Diazer
ID: 39187972
So the file would have to be exactiy the same as the other file sequence wise?

Do you know of a better method that would maybe put them in an array as the GptReal.inf is always going to be different computer to computer in some form or fasion.. I just want the most effective way of using SECedit.exe /export /cfg  GptReal.inf getting that inf that is created from the export and comparing to known security values..  I would have been able to convert it to a csv and saved myself some headaches but I don't know how to use the delimiters in a way to convert "MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Setup\RecoveryConsole\SecurityLevel=4,0" to a comma seperated table which would be even better honestly..  Go line by line thru the Inf and then convert it to look like "MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Setup\RecoveryConsole\SecurityLevel,4,0

I guess if I went in the document and replaced all the = with commas that would work would it not?  maybe I'm going about this the hard way.. LOL
0
 
LVL 69

Accepted Solution

by:
Qlemo earned 500 total points
ID: 39188259
If we use
$ini1 = flatten-hash (Get-IniContent GptTmpl.Inf) | sort String
$ini2 = flatten-hash (Get-IniContent GptReal.Inf) | sort String

Open in new window

(or instead sort for section, key, value, which does not make a difference) you should get a sorted list, and compare-object will try to do its best to sync both INFs.

If you want a tabular representation of your INFs, try with
$ini2 | format-table Section, Key, Value  # for Display
$ini2 | select Section, Key, Value | export-csv -NoType GptReal.CSV # for CSV file

Open in new window

or use convertto-* or ...
0
 

Author Closing Comment

by:Diazer
ID: 39188499
Thank you so much for your rapid response. I'm sure I will be calling on you for more questions.. :)
0
 

Author Comment

by:Diazer
ID: 39189159
I have been playing with the code but I still cant seem to get the tables to output into an HTML table..  I'm wanting a table that shows key and value.   So it could list all the key's that are in the GptTmpl.inf, The Values with the column name "Default" and another colomn "Actual" that shows the current setting even if it is empty to show "No Value"

So I guess it would look something like this

Keys                                  |     Default     |    Actual
MaximumPasswordAge  |         90         |       60

It just makes it easier to report the changes..
0
 

Author Comment

by:Diazer
ID: 39191516
Qlemo,

I manged to get the code to export to html but I am having some issues with the data not exporting over.. as you said the data has to line up.. I tried to use the sort feature but that seem to not make a differance.. Really I think that the code needs to be tweaked a little more and I am working on it but doing circles :( can you test with the file I attached and maybe export your GptTMPL.inf on your machine and do a compare.. Really I only need to display the table as I have above.

Thank you in advance
0
 
LVL 69

Expert Comment

by:Qlemo
ID: 39191775
We would need to perform exact matches, and some more logic, to get above format. Still thinking about how to do that ...
0
 
LVL 69

Expert Comment

by:Qlemo
ID: 39192684
Does this one work as a base for HTML reports for you?
Compare-Object -PassThru $ini1 $ini2 -Property String | % { $obj = $null } {
  if ($obj -and $obj.Section -eq $_.Section -and $obj.Key -eq $_.Key)
  {
    if ($_.SideIndicator -eq '<=') { $obj.Default = $_.Value } else { $obj.Value = $_.Value }
  } else {
    $obj
    $obj = New-Object PSObject -Property @{Section = $_.Section; Key = $_.Key; Default = $_.Value*($_.SideIndicator -eq '<='); Value = $_.Value*($_.SideIndicator -eq '=>') }
  }
} {$obj} 

Open in new window

0
 

Author Comment

by:Diazer
ID: 39192751
ok so that is looking better but it still does not line up the Key values and when it displays it they only shows the data that corrosponds to the key so I guess the Key values are not merging up and then displaying the values for each..

Would seeing the code help any?
0
 
LVL 69

Expert Comment

by:Qlemo
ID: 39193563
I see - compare-object is too stupid to provide differences in correct sequence. We have to sort that output, too.
Compare-Object -PassThru $ini1 $ini2 -Property String | sort String | % { $obj = $null } {
  if ($obj -and $obj.Section -eq $_.Section -and $obj.Key -eq $_.Key)
  {
    if ($_.SideIndicator -eq '<=') { $obj.Default = $_.Value } else { $obj.Value = $_.Value }
  } else {
    $obj
    $obj = New-Object PSObject -Property @{Section = $_.Section; Key = $_.Key; Default = $_.Value*($_.SideIndicator -eq '<='); Value = $_.Value*($_.SideIndicator -eq '=>') }
  }
} {$obj} 

Open in new window

This worked against my secedit export, which is totally different from your template, and so I'm confident it is what you need.
0
 

Author Comment

by:Diazer
ID: 39194832
do you know of any way to prevent this? maybe there is a way to merge the keys together?  


Key                                            Default                                        Value

 
AuditAccountLogon                         3

AuditAccountLogon                                                                           3

I'm looking into it as well as I'm sure its just another switch..  I know that we had it working the right way when importing the differnt CSV's
0
 
LVL 69

Expert Comment

by:Qlemo
ID: 39195001
Is it the same section? As long as both section and key are the same, you should only get a single entry. That worked great for me, as already said. Please check if there are no additional spaces in section or key or such (unlikely, but who knows?).
0
 

Author Comment

by:Diazer
ID: 39195696
It Works.  had spaces in the INf File..

Thank you so much :)
0
 

Author Comment

by:Diazer
ID: 39248254
Qlemo,

I am going to post another question and reference this one. as I am needing help with the hash table and I know you helped me before.  I want you to get credit for it.

Erica
0

Featured Post

Netscaler Common Configuration How To guides

If you use NetScaler you will want to see these guides. The NetScaler How To Guides show administrators how to get NetScaler up and configured by providing instructions for common scenarios and some not so common ones.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Microsoft Windows Server Update Service (WSUS) is free for everyone, but it lacks of some desirable features like send an e-mail to the administrator with the status of all computers on the WSUS server. This article is based on my PowerShell script …
Create and license users in Office 365 in bulk based on a CSV file. A step-by-step guide with PowerShell script examples.
Microsoft Active Directory, the widely used IT infrastructure, is known for its high risk of credential theft. The best way to test your Active Directory’s vulnerabilities to pass-the-ticket, pass-the-hash, privilege escalation, and malware attacks …
With Secure Portal Encryption, the recipient is sent a link to their email address directing them to the email laundry delivery page. From there, the recipient will be required to enter a user name and password to enter the page. Once the recipient …

832 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question