Windows Vista Forums
Vista Forums Home Join Vista Forums Donate Vista Tutorials Tags

Welcome to Vista Forums we are your forum to discuss Windows Vista x64 and x86 systems. Whether you need help or just want to post an idea you have on Vista, this is the forum for you.
Register at Vista forums...the world biggest Windows Vista resource Join Vista Forums Now

Go Back   Vista Forums > Microsoft Technical Newsgroups > PowerShell

Working with arrays

Update your Vista Drivers Update Your Drivers Now!!
Closed Thread
 
Thread Tools Display Modes
Old 11-18-2007   #1 (permalink)
Jobbsy
Guest


 

Working with arrays

I have having the following problem:

I have an array say $events
i obtained from get-eventlog (which say returns a number of events matching
the criteria set)

when displayed it will give something like

{passwordlastset: 15\12\70 callerusername: administrator}

I am basically trying to write only where the passwordlastchanged criteria
match and the user did not change the password himself from similar code to
below:

foreach ($objuser in $AD)
{
foreach ($event in $events)
{
$P = $event.passwordlastset
$N = $event.callerusername
IF ($passwordlastsetobtainedfromADSI -eq $P) -and ($N -ine
$usersnameobtainedfromADSI)
{
write-host "$N" + " was the last person to change the password of " +
"$usersnameobtainedfromADSI"
}
}
}
The problem I have is it will hit the first person who meets the criteria
and write as expected but also the same info for each and every user
thereafter - any help would be much appreciated as I have tried a number of
things all to no avail
--
jobbsy@xxxxxx

My System SpecsSystem Spec
Old 11-18-2007   #2 (permalink)
Shay Levi
Guest


 

Re: Working with arrays

It's hard to say just from viewing the code sample. You can try to assign
the variables to $null or "" in each iteration.

BTW, -ine (case-insensitive comparison) is the same as -ne.
Also, if $N and $usersnameobtainedfromADSI are strings then you don't need
to concatenate the variables:

write-host "$N" + " was the last person to change the password of " + "$usersnameobtainedfromADSI"

You can simply write:

write-host "$N was the last person to change the password of $usersnameobtainedfromADSI"



-----
Shay Levi
$cript Fanatic
http://scriptolog.blogspot.com


Quote:

> I have having the following problem:
>
> I have an array say $events
> i obtained from get-eventlog (which say returns a number of events
> matching
> the criteria set)
> when displayed it will give something like
>
> {passwordlastset: 15\12\70 callerusername: administrator}
>
> I am basically trying to write only where the passwordlastchanged
> criteria match and the user did not change the password himself from
> similar code to below:
>
> foreach ($objuser in $AD)
> {
> foreach ($event in $events)
> {
> $P = $event.passwordlastset
> $N = $event.callerusername
> IF ($passwordlastsetobtainedfromADSI -eq $P) -and ($N -ine
> $usersnameobtainedfromADSI)
> {
> write-host "$N" + " was the last person to change the password of "
> +
> "$usersnameobtainedfromADSI"
> }
> }
> }
> The problem I have is it will hit the first person who meets the
> criteria and write as expected but also the same info for each and
> every user thereafter - any help would be much appreciated as I have
> tried a number of things all to no avail
>

My System SpecsSystem Spec
Old 11-18-2007   #3 (permalink)
Jobbsy
Guest


 

Re: Working with arrays

Thanks Shay there's nothing else I believe coming into the second loop that
would effect it - I hav tried with both $null and "" and the code works fine
until there is an earlier entry picked up - I test this by changing the
password of same user in quickish succesion and running against a certain
-newest no of eventlog entries knowing I will pick them both up - therefore
the earlier one shouldnn't match the passwordlastset adsi value, although it
would match -ne to username).

Yes thanks for the write-host and -ieq tip.




--
jobbsy@xxxxxx


"Shay Levi" wrote:
Quote:

> It's hard to say just from viewing the code sample. You can try to assign
> the variables to $null or "" in each iteration.
>
> BTW, -ine (case-insensitive comparison) is the same as -ne.
> Also, if $N and $usersnameobtainedfromADSI are strings then you don't need
> to concatenate the variables:
>
> write-host "$N" + " was the last person to change the password of " + "$usersnameobtainedfromADSI"
>
> You can simply write:
>
> write-host "$N was the last person to change the password of $usersnameobtainedfromADSI"
>
>
>
> -----
> Shay Levi
> $cript Fanatic
> http://scriptolog.blogspot.com
>
>
>
Quote:

> > I have having the following problem:
> >
> > I have an array say $events
> > i obtained from get-eventlog (which say returns a number of events
> > matching
> > the criteria set)
> > when displayed it will give something like
> >
> > {passwordlastset: 15\12\70 callerusername: administrator}
> >
> > I am basically trying to write only where the passwordlastchanged
> > criteria match and the user did not change the password himself from
> > similar code to below:
> >
> > foreach ($objuser in $AD)
> > {
> > foreach ($event in $events)
> > {
> > $P = $event.passwordlastset
> > $N = $event.callerusername
> > IF ($passwordlastsetobtainedfromADSI -eq $P) -and ($N -ine
> > $usersnameobtainedfromADSI)
> > {
> > write-host "$N" + " was the last person to change the password of "
> > +
> > "$usersnameobtainedfromADSI"
> > }
> > }
> > }
> > The problem I have is it will hit the first person who meets the
> > criteria and write as expected but also the same info for each and
> > every user thereafter - any help would be much appreciated as I have
> > tried a number of things all to no avail
> >
>
>
>
My System SpecsSystem Spec
Old 11-18-2007   #4 (permalink)
Shay Levi
Guest


 

Re: Working with arrays

What are the types of $N, $P, etc? (e.g $N.gettype())


Doe's the same happens when you run:

$N=@{name="CallerUserName";expression={$_.callerusername}}
$P=@{name="PasswordLastSet";expression={$_.passwordlastset}}
$ADSIUser =@{name="ADSIUserName";expression={$usersnameobtainedfromADSI}}

$events | select $N,$P,$ADSIUser | format-table -auto


-----
Shay Levi
$cript Fanatic
http://scriptolog.blogspot.com


Quote:

> Thanks Shay there's nothing else I believe coming into the second loop
> that would effect it - I hav tried with both $null and "" and the code
> works fine until there is an earlier entry picked up - I test this by
> changing the password of same user in quickish succesion and running
> against a certain -newest no of eventlog entries knowing I will pick
> them both up - therefore the earlier one shouldnn't match the
> passwordlastset adsi value, although it would match -ne to username).
>
> Yes thanks for the write-host and -ieq tip.
>
> "Shay Levi" wrote:
>
Quote:

>> It's hard to say just from viewing the code sample. You can try to
>> assign the variables to $null or "" in each iteration.
>>
>> BTW, -ine (case-insensitive comparison) is the same as -ne. Also, if
>> $N and $usersnameobtainedfromADSI are strings then you don't need to
>> concatenate the variables:
>>
>> write-host "$N" + " was the last person to change the password of " +
>> "$usersnameobtainedfromADSI"
>>
>> You can simply write:
>>
>> write-host "$N was the last person to change the password of
>> $usersnameobtainedfromADSI"
>>
>> -----
>> Shay Levi
>> $cript Fanatic
>> http://scriptolog.blogspot.com
Quote:

>>> I have having the following problem:
>>>
>>> I have an array say $events
>>> i obtained from get-eventlog (which say returns a number of events
>>> matching
>>> the criteria set)
>>> when displayed it will give something like
>>> {passwordlastset: 15\12\70 callerusername: administrator}
>>>
>>> I am basically trying to write only where the passwordlastchanged
>>> criteria match and the user did not change the password himself from
>>> similar code to below:
>>>
>>> foreach ($objuser in $AD)
>>> {
>>> foreach ($event in $events)
>>> {
>>> $P = $event.passwordlastset
>>> $N = $event.callerusername
>>> IF ($passwordlastsetobtainedfromADSI -eq $P) -and ($N -ine
>>> $usersnameobtainedfromADSI)
>>> {
>>> write-host "$N" + " was the last person to change the password of "
>>> +
>>> "$usersnameobtainedfromADSI"
>>> }
>>> }
>>> }
>>> The problem I have is it will hit the first person who meets the
>>> criteria and write as expected but also the same info for each and
>>> every user thereafter - any help would be much appreciated as I have
>>> tried a number of things all to no avail

My System SpecsSystem Spec
Old 11-19-2007   #5 (permalink)
Jobbsy
Guest


 

Re: Working with arrays

Thanks for your help Shay I was able to figure it out (I needed the 5thField
outside of the events loop from my finished code below - you were right
without seeing all the code you could not have troubleshooted that - but
appreciated your input - I'm sure this is not the most professional code ever
but it works! - Thanks again


#INITIALISATION SECTION
#----------------------

#Clear the Windows command console screen
Clear-Host

#CONSTANTS SECTION
#-----------------

$strDate = get-date -uformat "%Y-%m-%d"
$CSVFilePath = 'c:\Documents and Settings\All
Users\Desktop\SwapClearITD_users_'+$strDate+'.csv'

#Delete previous file if exists
$RetVal = Test-Path 'c:\Documents and Settings\All Users\Desktop\' |
where-object {$_.name -like "*.CSV"}
If ($RetVal = 'True')
{
Remove-Item 'c:\Documents and Settings\All Users\Desktop\*.CSV'
}

#Creates new dated file and specifies header for CSV.
$strOutputString = "User,Member Of Group,Account Created,Password last
changed"
$strOutputString | out-file -Width 2147483647 -filepath $CSVFilePath
-encoding ascii

#Retrieve Events for Administrator Password Changes

[regex]$regEx = ('\:\s+')
$events = @()
get-eventlog Security -newest 2000 |
where {$_.eventID -eq '642'} |
% {
$obj = new-object psObject
switch -regex ($_.message.split("`n")) {
'^\s*Password Last Set\:' {
add-member NoteProperty -name PasswordLastSet `
-value $($regEx.split($_)[1]).trim() -in $obj
}
'^\s*Caller User Name\:' {
add-member NoteProperty -name CallerUserName `
-value $($regEx.split($_)[1]).trim() -in $obj
}
}
$events += $obj
}



#FUNCTIONS & FILTERS SECTION
#----------------------------



#MAIN PROCESSING SECTION
#-----------------------

$Dom = 'LDAP://OU=test,DC=vmware,DC=vm'
$Root = New-Object DirectoryServices.DirectoryEntry $Dom
$i=0

# Create a selector and start searching from the Root of AD
$selector = New-Object DirectoryServices.DirectorySearcher
$selector.SearchRoot = $root
$selector.pagesize = 1000
$adobj= $selector.findall() |`
where {$_.properties.objectcategory -match "CN=Person"}


foreach ($person in $adobj) {
$prop=$person.properties
$i++

$1stField = "$($prop.name)" + ","


# $2nd Field - Member Of
#---------------------------------------------------------
IF ("$($prop.memberof)" -match "CN=*") {
#Remove the "CN=, OU=TEST," etc & just keep name of group at front of DN
$s = "$($prop.memberof)"
$firstdivofDN,$seconddivofDN,$thirddivofDN =
([regex]'=(.+?),').matches($s) | foreach {$_.Groups[1].Value}
$2ndField = "$firstdivofDN" + ","
} ELSE {
$2ndField = "****NOT A MEMBER OF A GROUP****" + ","
}
# $3rd Field - date When account was created
#------------------------------------------
$AC = $($prop.whencreated)
$AccountCreated = "{00:dd}/{00:MM}/{0000:yyyy} {0:hh}:{0:mm}:{0:ss}" -f($AC)

$3rdField = "$AccountCreated" + ","

# $4th Field - Password Last Set
#----------------------------------------------------------
#Convert the large Integer format into a readable date

$LI = [datetime]::FromFileTimeUTC( $($prop.pwdlastset[0]) )
$PWLSet = "{00:dd}/{00:MM}/{0000:yyyy} {0:hh}:{0:mm}:{0:ss}" -f ($LI)

$4thField = "$PWLSet" + ","

# $5th Field - Was Administrator last person to change Password?
#--------------------------------------------------------------

$5thField = ""

IF ("$AccountCreated" -match "$PWLSet") {
$5thField = "****PASSWORD NOT CHANGED SINCE ACCOUNT SETUP****" + ","
} ELSE {
Foreach($event in $events) { # from constants section at start

$E = $event.PasswordLastSet

$N = $event.CallerUserName

IF (("$E" -match "$PWLSet") -and ("$N" -ne "$($prop.name)")) {
$5thField = "****PASSWORD last Changed by " + "$N" + "****" + ","
}
}
}


$strOutputString = "$1stField" + "$2ndField" + "$3rdField" + "$4thField" +
"$5thField"

$strOutputString | out-file -filepath $CSVFilePath -encoding ascii -append

}




--
jobbsy@xxxxxx


"Shay Levi" wrote:
Quote:

> What are the types of $N, $P, etc? (e.g $N.gettype())
>
>
> Doe's the same happens when you run:
>
> $N=@{name="CallerUserName";expression={$_.callerusername}}
> $P=@{name="PasswordLastSet";expression={$_.passwordlastset}}
> $ADSIUser =@{name="ADSIUserName";expression={$usersnameobtainedfromADSI}}
>
> $events | select $N,$P,$ADSIUser | format-table -auto
>
>
> -----
> Shay Levi
> $cript Fanatic
> http://scriptolog.blogspot.com
>
>
>
Quote:

> > Thanks Shay there's nothing else I believe coming into the second loop
> > that would effect it - I hav tried with both $null and "" and the code
> > works fine until there is an earlier entry picked up - I test this by
> > changing the password of same user in quickish succesion and running
> > against a certain -newest no of eventlog entries knowing I will pick
> > them both up - therefore the earlier one shouldnn't match the
> > passwordlastset adsi value, although it would match -ne to username).
> >
> > Yes thanks for the write-host and -ieq tip.
> >
> > "Shay Levi" wrote:
> >
Quote:

> >> It's hard to say just from viewing the code sample. You can try to
> >> assign the variables to $null or "" in each iteration.
> >>
> >> BTW, -ine (case-insensitive comparison) is the same as -ne. Also, if
> >> $N and $usersnameobtainedfromADSI are strings then you don't need to
> >> concatenate the variables:
> >>
> >> write-host "$N" + " was the last person to change the password of " +
> >> "$usersnameobtainedfromADSI"
> >>
> >> You can simply write:
> >>
> >> write-host "$N was the last person to change the password of
> >> $usersnameobtainedfromADSI"
> >>
> >> -----
> >> Shay Levi
> >> $cript Fanatic
> >> http://scriptolog.blogspot.com
> >>> I have having the following problem:
> >>>
> >>> I have an array say $events
> >>> i obtained from get-eventlog (which say returns a number of events
> >>> matching
> >>> the criteria set)
> >>> when displayed it will give something like
> >>> {passwordlastset: 15\12\70 callerusername: administrator}
> >>>
> >>> I am basically trying to write only where the passwordlastchanged
> >>> criteria match and the user did not change the password himself from
> >>> similar code to below:
> >>>
> >>> foreach ($objuser in $AD)
> >>> {
> >>> foreach ($event in $events)
> >>> {
> >>> $P = $event.passwordlastset
> >>> $N = $event.callerusername
> >>> IF ($passwordlastsetobtainedfromADSI -eq $P) -and ($N -ine
> >>> $usersnameobtainedfromADSI)
> >>> {
> >>> write-host "$N" + " was the last person to change the password of "
> >>> +
> >>> "$usersnameobtainedfromADSI"
> >>> }
> >>> }
> >>> }
> >>> The problem I have is it will hit the first person who meets the
> >>> criteria and write as expected but also the same info for each and
> >>> every user thereafter - any help would be much appreciated as I have
> >>> tried a number of things all to no avail
>
>
>
My System SpecsSystem Spec
Old 11-19-2007   #6 (permalink)
Shay Levi
Guest


 

Re: Working with arrays

Hi Jobbsy,

Glad you could resolve it :-)

Generally, I would avoid keeping/running files from any desktop, the path
is too deep any you may encounter permission errors.

1. You can embed $strDate inside double quotes string and it will expand
its value.
$CSVFilePath = "C:\Documents and Settings\All Users\Desktop\SwapClearITD_users_$strDate.csv"

2. Test-Path determines whether all elements of a path exist. It checks for
one file/directory based on leaf/container value of -pathType parameter.
It doesn't check for ALL (*.CSV) files. If you want to delete all CSV
files before starting use 'get-childitem -filter *.csv | remove-item -force'

To test for a file existence use:
test-path -path c:\scripts\$strDate.csv -pathType leaf

For directory:
test-path -path c:\scripts -pathType Container

Execute 'get-help test-path -full' to get full available help

3. You can format dates easily with the -format operator, its much more concise
then $AccountCreated assignment:
PS > get-date -f "dd/MM/yyyy hh:mm:ss"
19/11/2007 11:36:08

The same can be applied when you retrieve events from a log file:
PS > $e= get-eventlog application -new 1
PS> $e.TimeWritten -f "dd/MM/yyyy hh:mm:ss"
19/11/2007 11:36:08

4. '$AC = $($prop.whencreated)' is the same as '$AC = $prop.whencreated'.
Generally, You use the $($prop.member) subexpression expansion notation
when you need to expand the variable inside of a string.

You can't write this:
PS > write-host "PowerShell current culture is: $Host.CurrentCulture"
PowerShell current culture is: System.Management.Automation.Internal.Host.InternalHost.CurrentCulture

This works:
PS > write-host "Working directory path is $($Host.CurrentCulture)"
PowerShell current culture is: he-IL




HTH

-----
Shay Levi
$cript Fanatic
http://scriptolog.blogspot.com


Quote:

> Thanks for your help Shay I was able to figure it out (I needed the
> 5thField outside of the events loop from my finished code below - you
> were right without seeing all the code you could not have
> troubleshooted that - but appreciated your input - I'm sure this is
> not the most professional code ever but it works! - Thanks again
>
> #INITIALISATION SECTION
> #----------------------
> #Clear the Windows command console screen
> Clear-Host
> #CONSTANTS SECTION
> #-----------------
> $strDate = get-date -uformat "%Y-%m-%d"
> $CSVFilePath = 'c:\Documents and Settings\All
> Users\Desktop\SwapClearITD_users_'+$strDate+'.csv'
> #Delete previous file if exists
> $RetVal = Test-Path 'c:\Documents and Settings\All Users\Desktop\' |
> where-object {$_.name -like "*.CSV"}
> If ($RetVal = 'True')
> {
> Remove-Item 'c:\Documents and Settings\All Users\Desktop\*.CSV'
> }
> #Creates new dated file and specifies header for CSV.
> $strOutputString = "User,Member Of Group,Account Created,Password last
> changed"
> $strOutputString | out-file -Width 2147483647 -filepath $CSVFilePath
> -encoding ascii
> #Retrieve Events for Administrator Password Changes
>
> [regex]$regEx = ('\:\s+')
> $events = @()
> get-eventlog Security -newest 2000 |
> where {$_.eventID -eq '642'} |
> % {
> $obj = new-object psObject
> switch -regex ($_.message.split("`n")) {
> '^\s*Password Last Set\:' {
> add-member NoteProperty -name PasswordLastSet `
> -value $($regEx.split($_)[1]).trim() -in $obj
> }
> '^\s*Caller User Name\:' {
> add-member NoteProperty -name CallerUserName `
> -value $($regEx.split($_)[1]).trim() -in $obj
> }
> }
> $events += $obj
> }
> #FUNCTIONS & FILTERS SECTION
> #----------------------------
> #MAIN PROCESSING SECTION
> #-----------------------
> $Dom = 'LDAP://OU=test,DC=vmware,DC=vm'
> $Root = New-Object DirectoryServices.DirectoryEntry $Dom
> $i=0
> # Create a selector and start searching from the Root of AD
> $selector = New-Object DirectoryServices.DirectorySearcher
> $selector.SearchRoot = $root
> $selector.pagesize = 1000
> $adobj= $selector.findall() |`
> where {$_.properties.objectcategory -match "CN=Person"}
> foreach ($person in $adobj) {
> $prop=$person.properties
> $i++
> $1stField = "$($prop.name)" + ","
>
> # $2nd Field - Member Of
> #---------------------------------------------------------
> IF ("$($prop.memberof)" -match "CN=*") {
> #Remove the "CN=, OU=TEST," etc & just keep name of group at front of
> DN
> $s = "$($prop.memberof)"
> $firstdivofDN,$seconddivofDN,$thirddivofDN =
> ([regex]'=(.+?),').matches($s) | foreach {$_.Groups[1].Value}
> $2ndField = "$firstdivofDN" + ","
> } ELSE {
> $2ndField = "****NOT A MEMBER OF A GROUP****" + ","
> }
> # $3rd Field - date When account was created
> #------------------------------------------
> $AC = $($prop.whencreated)
> $AccountCreated = "{00:dd}/{00:MM}/{0000:yyyy} {0:hh}:{0:mm}:{0:ss}"
> -f($AC)
> $3rdField = "$AccountCreated" + ","
>
> # $4th Field - Password Last Set
> #---------------------------------------------------------- #Convert
> the large Integer format into a readable date
>
> $LI = [datetime]::FromFileTimeUTC( $($prop.pwdlastset[0]) )
> $PWLSet = "{00:dd}/{00:MM}/{0000:yyyy} {0:hh}:{0:mm}:{0:ss}" -f
> ($LI)
> $4thField = "$PWLSet" + ","
>
> # $5th Field - Was Administrator last person to change Password?
> #--------------------------------------------------------------
>
> $5thField = ""
>
> IF ("$AccountCreated" -match "$PWLSet") {
> $5thField = "****PASSWORD NOT CHANGED SINCE ACCOUNT SETUP****" +
> ","
> } ELSE {
> Foreach($event in $events) { # from constants section at start
> $E = $event.PasswordLastSet
>
> $N = $event.CallerUserName
>
> IF (("$E" -match "$PWLSet") -and ("$N" -ne "$($prop.name)")) {
> $5thField = "****PASSWORD last Changed by " + "$N" + "****" +
> ","
> }
> }
> }
> $strOutputString = "$1stField" + "$2ndField" + "$3rdField" +
> "$4thField" + "$5thField"
>
> $strOutputString | out-file -filepath $CSVFilePath -encoding ascii
> -append
>
> }
>
> "Shay Levi" wrote:
>
Quote:

>> What are the types of $N, $P, etc? (e.g $N.gettype())
>>
>> Doe's the same happens when you run:
>>
>> $N=@{name="CallerUserName";expression={$_.callerusername}}
>> $P=@{name="PasswordLastSet";expression={$_.passwordlastset}}
>> $ADSIUser
>> =@{name="ADSIUserName";expression={$usersnameobtainedfromADSI}}
>>
>> $events | select $N,$P,$ADSIUser | format-table -auto
>>
>> -----
>> Shay Levi
>> $cript Fanatic
>> http://scriptolog.blogspot.com
Quote:

>>> Thanks Shay there's nothing else I believe coming into the second
>>> loop that would effect it - I hav tried with both $null and "" and
>>> the code works fine until there is an earlier entry picked up - I
>>> test this by changing the password of same user in quickish
>>> succesion and running against a certain -newest no of eventlog
>>> entries knowing I will pick them both up - therefore the earlier one
>>> shouldnn't match the passwordlastset adsi value, although it would
>>> match -ne to username).
>>>
>>> Yes thanks for the write-host and -ieq tip.
>>>
>>> "Shay Levi" wrote:
>>>
>>>> It's hard to say just from viewing the code sample. You can try to
>>>> assign the variables to $null or "" in each iteration.
>>>>
>>>> BTW, -ine (case-insensitive comparison) is the same as -ne. Also,
>>>> if $N and $usersnameobtainedfromADSI are strings then you don't
>>>> need to concatenate the variables:
>>>>
>>>> write-host "$N" + " was the last person to change the password of "
>>>> + "$usersnameobtainedfromADSI"
>>>>
>>>> You can simply write:
>>>>
>>>> write-host "$N was the last person to change the password of
>>>> $usersnameobtainedfromADSI"
>>>>
>>>> -----
>>>> Shay Levi
>>>> $cript Fanatic
>>>> http://scriptolog.blogspot.com
>>>>> I have having the following problem:
>>>>>
>>>>> I have an array say $events
>>>>> i obtained from get-eventlog (which say returns a number of events
>>>>> matching
>>>>> the criteria set)
>>>>> when displayed it will give something like
>>>>> {passwordlastset: 15\12\70 callerusername: administrator}
>>>>> I am basically trying to write only where the passwordlastchanged
>>>>> criteria match and the user did not change the password himself
>>>>> from similar code to below:
>>>>>
>>>>> foreach ($objuser in $AD)
>>>>> {
>>>>> foreach ($event in $events)
>>>>> {
>>>>> $P = $event.passwordlastset
>>>>> $N = $event.callerusername
>>>>> IF ($passwordlastsetobtainedfromADSI -eq $P) -and ($N -ine
>>>>> $usersnameobtainedfromADSI)
>>>>> {
>>>>> write-host "$N" + " was the last person to change the password of
>>>>> "
>>>>> +
>>>>> "$usersnameobtainedfromADSI"
>>>>> }
>>>>> }
>>>>> }
>>>>> The problem I have is it will hit the first person who meets the
>>>>> criteria and write as expected but also the same info for each and
>>>>> every user thereafter - any help would be much appreciated as I
>>>>> have
>>>>> tried a number of things all to no avail

My System SpecsSystem Spec
Old 11-19-2007   #7 (permalink)
Jobbsy
Guest


 

Re: Working with arrays

Thanks Shay I will sit down and go through your tips and certainly take them
onboard

My next challenge is to interrogate 2 DCs in a Domain - this script runs
happily against one dc in a test domain - also as the security event log is
liable to being overwritten I will have to save the csv files and loop
through a number of historical ones to make sure info is accurate - I reckon
it will probably be easier to combine the two output files after running on
each DC - all this will be scheduled to run daily - that should test my
knowledge!


--
jobbsy@xxxxxx


"Shay Levi" wrote:
Quote:

> Hi Jobbsy,
>
> Glad you could resolve it :-)
>
> Generally, I would avoid keeping/running files from any desktop, the path
> is too deep any you may encounter permission errors.
>
> 1. You can embed $strDate inside double quotes string and it will expand
> its value.
> $CSVFilePath = "C:\Documents and Settings\All Users\Desktop\SwapClearITD_users_$strDate.csv"
>
> 2. Test-Path determines whether all elements of a path exist. It checks for
> one file/directory based on leaf/container value of -pathType parameter.
> It doesn't check for ALL (*.CSV) files. If you want to delete all CSV
> files before starting use 'get-childitem -filter *.csv | remove-item -force'
>
> To test for a file existence use:
> test-path -path c:\scripts\$strDate.csv -pathType leaf
>
> For directory:
> test-path -path c:\scripts -pathType Container
>
> Execute 'get-help test-path -full' to get full available help
>
> 3. You can format dates easily with the -format operator, its much more concise
> then $AccountCreated assignment:
> PS > get-date -f "dd/MM/yyyy hh:mm:ss"
> 19/11/2007 11:36:08
>
> The same can be applied when you retrieve events from a log file:
> PS > $e= get-eventlog application -new 1
> PS> $e.TimeWritten -f "dd/MM/yyyy hh:mm:ss"
> 19/11/2007 11:36:08
>
> 4. '$AC = $($prop.whencreated)' is the same as '$AC = $prop.whencreated'.
> Generally, You use the $($prop.member) subexpression expansion notation
> when you need to expand the variable inside of a string.
>
> You can't write this:
> PS > write-host "PowerShell current culture is: $Host.CurrentCulture"
> PowerShell current culture is: System.Management.Automation.Internal.Host.InternalHost.CurrentCulture
>
> This works:
> PS > write-host "Working directory path is $($Host.CurrentCulture)"
> PowerShell current culture is: he-IL
>
>
>
>
> HTH
>
> -----
> Shay Levi
> $cript Fanatic
> http://scriptolog.blogspot.com
>
>
>
Quote:

> > Thanks for your help Shay I was able to figure it out (I needed the
> > 5thField outside of the events loop from my finished code below - you
> > were right without seeing all the code you could not have
> > troubleshooted that - but appreciated your input - I'm sure this is
> > not the most professional code ever but it works! - Thanks again
> >
> > #INITIALISATION SECTION
> > #----------------------
> > #Clear the Windows command console screen
> > Clear-Host
> > #CONSTANTS SECTION
> > #-----------------
> > $strDate = get-date -uformat "%Y-%m-%d"
> > $CSVFilePath = 'c:\Documents and Settings\All
> > Users\Desktop\SwapClearITD_users_'+$strDate+'.csv'
> > #Delete previous file if exists
> > $RetVal = Test-Path 'c:\Documents and Settings\All Users\Desktop\' |
> > where-object {$_.name -like "*.CSV"}
> > If ($RetVal = 'True')
> > {
> > Remove-Item 'c:\Documents and Settings\All Users\Desktop\*.CSV'
> > }
> > #Creates new dated file and specifies header for CSV.
> > $strOutputString = "User,Member Of Group,Account Created,Password last
> > changed"
> > $strOutputString | out-file -Width 2147483647 -filepath $CSVFilePath
> > -encoding ascii
> > #Retrieve Events for Administrator Password Changes
> >
> > [regex]$regEx = ('\:\s+')
> > $events = @()
> > get-eventlog Security -newest 2000 |
> > where {$_.eventID -eq '642'} |
> > % {
> > $obj = new-object psObject
> > switch -regex ($_.message.split("`n")) {
> > '^\s*Password Last Set\:' {
> > add-member NoteProperty -name PasswordLastSet `
> > -value $($regEx.split($_)[1]).trim() -in $obj
> > }
> > '^\s*Caller User Name\:' {
> > add-member NoteProperty -name CallerUserName `
> > -value $($regEx.split($_)[1]).trim() -in $obj
> > }
> > }
> > $events += $obj
> > }
> > #FUNCTIONS & FILTERS SECTION
> > #----------------------------
> > #MAIN PROCESSING SECTION
> > #-----------------------
> > $Dom = 'LDAP://OU=test,DC=vmware,DC=vm'
> > $Root = New-Object DirectoryServices.DirectoryEntry $Dom
> > $i=0
> > # Create a selector and start searching from the Root of AD
> > $selector = New-Object DirectoryServices.DirectorySearcher
> > $selector.SearchRoot = $root
> > $selector.pagesize = 1000
> > $adobj= $selector.findall() |`
> > where {$_.properties.objectcategory -match "CN=Person"}
> > foreach ($person in $adobj) {
> > $prop=$person.properties
> > $i++
> > $1stField = "$($prop.name)" + ","
> >
> > # $2nd Field - Member Of
> > #---------------------------------------------------------
> > IF ("$($prop.memberof)" -match "CN=*") {
> > #Remove the "CN=, OU=TEST," etc & just keep name of group at front of
> > DN
> > $s = "$($prop.memberof)"
> > $firstdivofDN,$seconddivofDN,$thirddivofDN =
> > ([regex]'=(.+?),').matches($s) | foreach {$_.Groups[1].Value}
> > $2ndField = "$firstdivofDN" + ","
> > } ELSE {
> > $2ndField = "****NOT A MEMBER OF A GROUP****" + ","
> > }
> > # $3rd Field - date When account was created
> > #------------------------------------------
> > $AC = $($prop.whencreated)
> > $AccountCreated = "{00:dd}/{00:MM}/{0000:yyyy} {0:hh}:{0:mm}:{0:ss}"
> > -f($AC)
> > $3rdField = "$AccountCreated" + ","
> >
> > # $4th Field - Password Last Set
> > #---------------------------------------------------------- #Convert
> > the large Integer format into a readable date
> >
> > $LI = [datetime]::FromFileTimeUTC( $($prop.pwdlastset[0]) )
> > $PWLSet = "{00:dd}/{00:MM}/{0000:yyyy} {0:hh}:{0:mm}:{0:ss}" -f
> > ($LI)
> > $4thField = "$PWLSet" + ","
> >
> > # $5th Field - Was Administrator last person to change Password?
> > #--------------------------------------------------------------
> >
> > $5thField = ""
> >
> > IF ("$AccountCreated" -match "$PWLSet") {
> > $5thField = "****PASSWORD NOT CHANGED SINCE ACCOUNT SETUP****" +
> > ","
> > } ELSE {
> > Foreach($event in $events) { # from constants section at start
> > $E = $event.PasswordLastSet
> >
> > $N = $event.CallerUserName
> >
> > IF (("$E" -match "$PWLSet") -and ("$N" -ne "$($prop.name)")) {
> > $5thField = "****PASSWORD last Changed by " + "$N" + "****" +
> > ","
> > }
> > }
> > }
> > $strOutputString = "$1stField" + "$2ndField" + "$3rdField" +
> > "$4thField" + "$5thField"
> >
> > $strOutputString | out-file -filepath $CSVFilePath -encoding ascii
> > -append
> >
> > }
> >
> > "Shay Levi" wrote:
> >
Quote:

> >> What are the types of $N, $P, etc? (e.g $N.gettype())
> >>
> >> Doe's the same happens when you run:
> >>
> >> $N=@{name="CallerUserName";expression={$_.callerusername}}
> >> $P=@{name="PasswordLastSet";expression={$_.passwordlastset}}
> >> $ADSIUser
> >> =@{name="ADSIUserName";expression={$usersnameobtainedfromADSI}}
> >>
> >> $events | select $N,$P,$ADSIUser | format-table -auto
> >>
> >> -----
> >> Shay Levi
> >> $cript Fanatic
> >> http://scriptolog.blogspot.com
> >>> Thanks Shay there's nothing else I believe coming into the second
> >>> loop that would effect it - I hav tried with both $null and "" and
> >>> the code works fine until there is an earlier entry picked up - I
> >>> test this by changing the password of same user in quickish
> >>> succesion and running against a certain -newest no of eventlog
> >>> entries knowing I will pick them both up - therefore the earlier one
> >>> shouldnn't match the passwordlastset adsi value, although it would
> >>> match -ne to username).
> >>>
> >>> Yes thanks for the write-host and -ieq tip.
> >>>
> >>> "Shay Levi" wrote:
> >>>
> >>>> It's hard to say just from viewing the code sample. You can try to
> >>>> assign the variables to $null or "" in each iteration.
> >>>>
> >>>> BTW, -ine (case-insensitive comparison) is the same as -ne. Also,
> >>>> if $N and $usersnameobtainedfromADSI are strings then you don't
> >>>> need to concatenate the variables:
> >>>>
> >>>> write-host "$N" + " was the last person to change the password of "
> >>>> + "$usersnameobtainedfromADSI"
> >>>>
> >>>> You can simply write:
> >>>>
> >>>> write-host "$N was the last person to change the password of
> >>>> $usersnameobtainedfromADSI"
> >>>>
> >>>> -----
> >>>> Shay Levi
> >>>> $cript Fanatic
> >>>> http://scriptolog.blogspot.com
> >>>>> I have having the following problem:
> >>>>>
> >>>>> I have an array say $events
> >>>>> i obtained from get-eventlog (which say returns a number of events
> >>>>> matching
> >>>>> the criteria set)
> >>>>> when displayed it will give something like
> >>>>> {passwordlastset: 15\12\70 callerusername: administrator}
> >>>>> I am basically trying to write only where the passwordlastchanged
> >>>>> criteria match and the user did not change the password himself
> >>>>> from similar code to below:
> >>>>>
> >>>>> foreach ($objuser in $AD)
> >>>>> {
> >>>>> foreach ($event in $events)
> >>>>> {
> >>>>> $P = $event.passwordlastset
> >>>>> $N = $event.callerusername
> >>>>> IF ($passwordlastsetobtainedfromADSI -eq $P) -and ($N -ine
> >>>>> $usersnameobtainedfromADSI)
> >>>>> {
> >>>>> write-host "$N" + " was the last person to change the password of
> >>>>> "
> >>>>> +
> >>>>> "$usersnameobtainedfromADSI"
> >>>>> }
> >>>>> }
> >>>>> }
> >>>>> The problem I have is it will hit the first person who meets the
> >>>>> criteria and write as expected but also the same info for each and
> >>>>> every user thereafter - any help would be much appreciated as I
> >>>>> have
> >>>>> tried a number of things all to no avail
>
>
>
My System SpecsSystem Spec
Closed Thread

Thread Tools
Display Modes



Similar Threads
Thread Thread Starter Forum Replies Last Post
Arrays Jason Massie PowerShell 10 05-14-2008 07:37 AM
Arrays in Powershell Daren Daigle PowerShell 2 12-03-2007 07:37 AM
Multidimensional arrays Jacob