1

EDITED:

Text1.txt:
123.456.789.189:12345
222.222.222.444:56789
451.200.111.321:55555
333.333.333.111:11223

I want to compare ID with IP that weren't registered.

ERROR:

Exception calling "Add" with "2" argument(s): "Item has already been added. Key in dictionary: '123.456.789.189:12345'  Key being added: '123.456.789.189:12345'" +     $nameHash.Add( $data3[4], $data3[3] )

I think this error is due to the existence of duplicates.

How do I solve an issue with duplicates in Hash Table?

My function to calculate time takes in a startdate and an end date.

Function calTimeDiff( $StartDate, $EndDate ) 
{
    "which is = " + (NEW-TIMESPAN –Start $StartDate –End $EndDate).Hours + " hours, " + 
    (NEW-TIMESPAN –Start $StartDate –End $EndDate).Minutes + " minutes, " + 
    (NEW-TIMESPAN –Start $StartDate –End $EndDate).Seconds + " seconds, " + 
    "diff = " + (NEW-TIMESPAN –Start $StartDate –End $EndDate).TotalSeconds + " sec"
}

$lines1 = Get-Content "C:\Temp\Text1.txt" | Select-Object -Unique
$lines2 = Get-Content "C:\Temp\Text2.txt" | Select-Object -Unique

ForEach( $line2 in $lines2 )
{    
    $list = ( $date, $time, $client, $clientIP )
    $list = $line2.Split( "" )
    ForEach( $line1 in $lines1 )
    {
        $disconnectIP = $line1

        If( $disconnectIP -match $list[3] )
        {  
           $date = $list[0]
           $time = $list[1]
           $client = $list[2]
           $clientIP = $list[3] 

           If( $client -eq "serviceClient" )
           {
                $start = $date + " " + $time
           }

           If( $client -eq "Unregistered" )
           {
                $end = $date + " " + $time
           }

           calTimeDiff $start $end 
        }        
    }
}    
3
  • 1
    you mean two clients with the same ip? it depends on your needs (you could determine both differences, only the first or only the last one)... Also - did you tried anything yet? Commented Aug 31, 2015 at 8:21
  • 1
    Could you be more clear about what is in the file and what is not? And what exactly is your problem? Maybe add some sample code.. Commented Aug 31, 2015 at 8:44
  • Calculating time differences in Powershell is much simpler if you operate on objects rather than convert everything to text and then operate on text. You haven't described what your inputs look like. Are they objects or are they text? Commented Aug 31, 2015 at 11:57

1 Answer 1

2

How about something along these lines? I think it's basically behaving the way you were asking for (although you might want to tweak the display-span function a bit...)

#requires -Version 3
function parse-log 
{
    param(
        [string]$line
    )

    $data = $line.split(' ')
    $dateString = '{0} {1}' -f $data[0], $data[1]
    $timeStamp = Get-Date -Date $dateString
    [pscustomobject]@{
        TimeStamp = $timeStamp
        Client    = $data[2]
        IPAddress = $data[3]
    }
}

function display-span
{
    param(
        $logSpan
    )

    '{0} ({1}) ==> {2}' -f $logSpan.IPAddress, $nameHash.Get_Item( $logSpan.IPAddress), $logSpan.Start
    '{0} ({1}) ==> {2}' -f $logSpan.IPAddress, $nameHash.Get_Item( $logSpan.IPAddress), $logSpan.End
    'Start = {0}, End = {1}, diff = {2}' -f $logSpan.Start, $logSpan.End, $logSpan.TimeSpan
    ''
}

$ipStateHash = @{}
$nameHash = @{}
$logArray = @()

$lines1 = Get-Content -Path '.\Text1.txt'
$lines2 = Get-Content -Path '.\Text2.txt'
$lines3 = Get-Content -Path '.\Text3.txt'

# Build Name Hash
foreach( $line3 in $lines3 )
{
    $data3 = $line3.Split( ' ' )
    $nameHash.Add( $data3[4], $data3[3] )
}

foreach( $line2 in $lines2 ) 
{
    $entry = parse-log -line $line2
    switch( $entry.Client ) {
        'serviceClient' 
        {
            if( $lines1 -contains $entry.IPAddress ) 
            { 
                if( $ipStateHash.ContainsKey( $entry.IPAddress ) -eq $false ) 
                {
                    $ipStateHash.Add( $entry.IPAddress, $entry.TimeStamp )
                }
            }
        }
        'Unregistered' 
        {
            if( $ipStateHash.ContainsKey( $entry.IPAddress ) -eq $true ) 
            {
                $start = $ipStateHash.Get_Item( $entry.IPAddress )
                $ipStateHash.Remove( $entry.IPAddress )
                $timespan = $entry.TimeStamp - $start

                $logArray += [pscustomobject]@{
                    IPAddress = $entry.IPAddress
                    Start     = $start
                    End       = $entry.TimeStamp
                    TimeSpan  = $timespan
                }
            }
        }
    }
}

$logArray | ForEach-Object -Process {
    display-span -logSpan $_ 
}

"IPs that weren't Unregistered:"
$ipStateHash.GetEnumerator() | Sort-Object -Property TimeStamp | ForEach-Object -Process {
    '{0} ==> {1}' -f $nameHash.Get_Item( $_.Key ), $_.Value 
}

Using your updated data files from above, the script outputs:

123.456.789.189:12345 (BOB) ==> 7/29/2015 6:00:13 AM
123.456.789.189:12345 (BOB) ==> 7/29/2015 6:00:19 AM
Start = 7/29/2015 6:00:13 AM, End = 7/29/2015 6:00:19 AM, diff = 00:00:06

222.222.222.444:56789 (ALICE) ==> 7/29/2015 6:00:18 AM
222.222.222.444:56789 (ALICE) ==> 7/29/2015 6:00:22 AM
Start = 7/29/2015 6:00:18 AM, End = 7/29/2015 6:00:22 AM, diff = 00:00:04

451.200.111.321:55555 (TOM) ==> 7/29/2015 6:20:03 AM
451.200.111.321:55555 (TOM) ==> 7/29/2015 6:21:19 AM
Start = 7/29/2015 6:20:03 AM, End = 7/29/2015 6:21:19 AM, diff = 00:01:16

IPs that weren't Unregistered:
BOB ==> 7/29/2015 6:01:00 AM
Sign up to request clarification or add additional context in comments.

11 Comments

What if I have more IP in Text1.txt? Does it loop through all of them?
It's built an array of IPs from Text1.txt. The -contains checks to see if the IP we pull from Text2.txt is a member of that array, so there's no reason to loop through Text1.txt... I didn't bother checking with the "Unregistered" clause, since if it's not in the file, it couldn't have made it in the hash table from the "serviceClient" clause.
I just copied/pasted your text1/text2 files that you have up there and it still works for me. I'll update my answer with the new output.
Added some code to dump out the $ipStateHash hash, which contains all of the serviceClients that weren't Unregistered.
So I have another Text3.txt that I want to compare with the $ipStateHash. Instead of displaying the IP, it will display the name. How can I replace the IP with the name? Please see EDITED code.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.