Solved

foreach issue with Powershell Script, possibly needs a pause between each check.

Posted on 2013-01-07
18
1,068 Views
Last Modified: 2013-01-10
Hi Guys,

The below script has a problem with the Foreach section.
It works fine most of the time but about once a month it seems to use the wrong $statefile and informs me of a membership change.
It seems to use the statefile created for the Domain admins to compare against the other ones. Maybe I need to include a pause between each check to make sure Powershell has time to create a new statefile for each group check.


import-module activedirectory
$Email = "it@doesntmatter.com"
$SmtpServer = "server.doesntmatter.com"

foreach ($GroupName in "Domain Admins", "Administrators", "schema admins", "Enterprise Admins") {
  $StateFile = "C:\Docs\Group Check Files\Members - $GroupName.csv"
  $Members = Get-ADGroupMember $GroupName | Select-Object Name
  If (!(Test-Path $StateFile)) { $Members | Export-csv $StateFile -NoTypeInformation}

  $Changes = Compare-Object $Members $(Import-Csv $StateFile) -Property Name | Select-Object Name, @{n='State';e={ If ($_.SideIndicator -eq "=>") { "Removed" } Else { "Added" } }}

  If ($Changes) { Send-MailMessage -From $Email -To $Email -Subject "$GroupName membership change"  -BodyAsHtml -Body $($Changes | ConvertTo-Html | Out-String) -SmtpServer $SmtpServer }
0
Comment
Question by:thomasmulligan
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 9
  • 8
18 Comments
 
LVL 17

Expert Comment

by:Kent Dyer
ID: 38750695
Right after:

foreach ($GroupName in "Domain Admins", "Administrators", "schema admins", "Enterprise Admins")
{

Open in new window


It does not appear there is a closing tag "}"

HTH,

Kent
0
 
LVL 40

Expert Comment

by:Subsun
ID: 38750813
I hope the closing Curly Brace went missing while doing the copy paste.. :-)

In your script try printing the variables $Members and $(Import-Csv $StateFile) to screen and see if there is any difference..
0
 

Author Comment

by:thomasmulligan
ID: 38750871
the curly bracket is there I just missed it when copying to here.....if only the solution could be that easy.
0
What, When and Where - Security Threats from Q1

Join Corey Nachreiner, CTO, and Marc Laliberte, Information Security Threat Analyst, on July 26th as they explore their key findings from the first quarter of 2017.

 

Author Comment

by:thomasmulligan
ID: 38750929
I have just tried to run the script manually and it throws up the following errors:

Get-ADGroupMember : A referral was returned from the server
At line:3 char:31
+   $Members = Get-ADGroupMember <<<<  $GroupName | Select-Object Name
    + CategoryInfo          : NotSpecified: (Administrators:ADGroup) [Get-ADGroupMember], ADException
    + FullyQualifiedErrorId : A referral was returned from the server,Microsoft.ActiveDirectory.Management.Commands.Ge
   tADGroupMember

Get-ADGroupMember : A referral was returned from the server
At line:3 char:31
+   $Members = Get-ADGroupMember <<<<  $GroupName | Select-Object Name
    + CategoryInfo          : NotSpecified: (Enterprise Admins:ADGroup) [Get-ADGroupMember], ADException
    + FullyQualifiedErrorId : A referral was returned from the server,Microsoft.ActiveDirectory.Management.Commands.Ge
   tADGroupMember
0
 
LVL 40

Expert Comment

by:Subsun
ID: 38751013
I am not seeing any issue with the script. If it's reporting some changes then it should be valid.. However if you feel there is a issue then, as I said you need to print the the variables on screen (or include them in mail) and check.. Try the following script which will print both variables on screen.

import-module activedirectory
$Email = "it@doesntmatter.com"
$SmtpServer = "server.doesntmatter.com"

foreach ($GroupName in "Domain Admins", "Administrators", "schema admins", "Enterprise Admins") {
  $StateFile = "C:\Docs\Group Check Files\Members - $GroupName.csv"
  $Members = Get-ADGroupMember $GroupName | Select-Object Name
  If (!(Test-Path $StateFile)) { $Members | Export-csv $StateFile -NoTypeInformation}

Write-Host "Value of Var StateFile"
$(Import-Csv $StateFile)
Write-Host "Value of Var Members"
$Members

	$Changes = Compare-Object $Members $(Import-Csv $StateFile) -Property Name | Select-Object Name, @{n='State';e={ If ($_.SideIndicator -eq "=>") { "Removed" } Else { "Added" } }}

  If ($Changes) { Send-MailMessage -From $Email -To $Email -Subject "$GroupName membership change"  -BodyAsHtml -Body $($Changes | ConvertTo-Html | Out-String) -SmtpServer $SmtpServer }
}

Open in new window



And regarding the error, what if you run the following two lines in powershell?
import-module activedirectory
Get-ADGroupMember "Enterprise Admins" | Select-Object Name

Open in new window

0
 

Author Comment

by:thomasmulligan
ID: 38751042
I tried running Get-ADGroupMember for each group individually.
Domain Admins and Schema Admins run no problem and return the output as expected.

Enterprise Admins and Administrators both throw up the error:

Get-ADGroupMember : A referral was returned from the server
At line:1 char:18
+ Get-ADGroupMember <<<<  'enterprise admins'
    + CategoryInfo          : NotSpecified: (enterprise admins:ADGroup) [Get-ADGroupMember], ADException
    + FullyQualifiedErrorId : A referral was returned from the server,Microsoft.ActiveDirectory.Management.Commands.Ge
   tADGroupMember
0
 
LVL 40

Expert Comment

by:Subsun
ID: 38751102
It seems Get-ADGroupMember not able to read group members. By default, any user authenticated to the domain can view any group members, perhaps someone has modified permissions on the group object. Can you check the enterprise admins and Administrators group and see if you have necessary permission to view the group member?

Also are you able to view group member using ADUC?
0
 

Author Comment

by:thomasmulligan
ID: 38751152
i have just checked this and I can confirm that Authenticated Users have Read permissions to all of the groups.
Im also logged on to a DC and using the ADUC I can view the members of these groups but when I run the get-adgroupmember (while still on the same session) it gives the error.

Thanks for your quick responses on this.
0
 
LVL 40

Expert Comment

by:Subsun
ID: 38751224
That's strange.. I cannot think of an issue which would create this error other than a permission issue or a name mismatch of the group. Both seems invalid here.. :-(

Is this the same groups which you get change alert mail notification?
0
 

Author Comment

by:thomasmulligan
ID: 38751328
Yes, I get an Alert for Enterprise admins and Administrators.
The only reason it gives the alert is because it cant get the members.
0
 
LVL 40

Expert Comment

by:Subsun
ID: 38751355
yes.. that's the reason..
Do you have Quest Active directory cmdlets installed on any computer in domain?
0
 

Author Comment

by:thomasmulligan
ID: 38754225
No, I dont have the Quest AD cmdlets installed. Should I try it with those?
0
 
LVL 40

Expert Comment

by:Subsun
ID: 38754391
Run following commands and see if you get any result
Get-ADGroup -Filter {Name -Like "enterprise Admins"}
Get-ADGroup -Filter {Name -Like "Administrators"}

You can also try with Quest AD cmdlets..
http://www.quest.com/powershell/activeroles-server.aspx
0
 

Author Comment

by:thomasmulligan
ID: 38762435
Yes, Get-ADGroup finds both of these groups.
I just tried running the script again and it runs no problem.

Does anyone have any idea why this just stops working and wont get the membership of these groups, then starts working again when I haven't changed anything?
0
 

Author Comment

by:thomasmulligan
ID: 38762564
Can anyone tell me how to add in a condition that if it fails to find the group membership it wont send the normal alert, it will do something else.
0
 
LVL 40

Expert Comment

by:Subsun
ID: 38762594
I cannot think of any reason for why it's not working...
Can anyone tell me how to add in a condition that if it fails to find the group membership it wont send the normal alert, it will do something else.
You can check the value of $Members before sending alert.. Try this..If $Members is null then script wont send any alert..
import-module activedirectory
$Email = "it@doesntmatter.com"
$SmtpServer = "server.doesntmatter.com"

foreach ($GroupName in "Domain Admins", "Administrators", "schema admins", "Enterprise Admins") {
  $StateFile = "C:\Docs\Group Check Files\Members - $GroupName.csv"
  $Members = Get-ADGroupMember $GroupName | Select-Object Name
If (!(Test-Path $StateFile)) { $Members | Export-csv $StateFile -NoTypeInformation}
If ($Members){
$Changes = Compare-Object $Members $(Import-Csv $StateFile) -Property Name | Select-Object Name, @{n='State';e={ If ($_.SideIndicator -eq "=>") { "Removed" } Else { "Added" } }}

 If ($Changes) { Send-MailMessage -From $Email -To $Email -Subject "$GroupName membership change"  -BodyAsHtml -Body $($Changes | ConvertTo-Html | Out-String) -SmtpServer $SmtpServer }
 }
}

Open in new window

0
 
LVL 40

Accepted Solution

by:
Subsun earned 500 total points
ID: 38762606
If you want alert if it fails to find the group membership, then try..

import-module activedirectory
$Email = "it@doesntmatter.com"
$SmtpServer = "server.doesntmatter.com"

foreach ($GroupName in "Domain Admins", "Administrators", "schema admins", "Enterprise Admins") {
  $StateFile = "C:\Docs\Group Check Files\Members - $GroupName.csv"
  $Members = Get-ADGroupMember $GroupName | Select-Object Name
  If (!(Test-Path $StateFile)) { $Members | Export-csv $StateFile -NoTypeInformation}
  If ($Members){
  $Changes = Compare-Object $Members $(Import-Csv $StateFile) -Property Name | Select-Object Name, @{n='State';e={ If ($_.SideIndicator -eq "=>") { "Removed" } Else { "Added" } }}

 If ($Changes) { Send-MailMessage -From $Email -To $Email -Subject "$GroupName membership change"  -BodyAsHtml -Body $($Changes | ConvertTo-Html | Out-String) -SmtpServer $SmtpServer }
 }
 Else {Send-MailMessage -From $Email -To $Email -Subject "$GroupName membership read failed"  -Body "$GroupName membership read failed" -SmtpServer $SmtpServer}
}

Open in new window

0
 

Author Closing Comment

by:thomasmulligan
ID: 38762717
Thanks very much for your help with this.
0

Featured Post

IoT Devices - Fast, Cheap or Secure…Pick Two

The IoT market is growing at a rapid pace and manufacturers are under pressure to quickly provide new products. Can you be sure that your devices do what they're supposed to do, while still being secure?

Question has a verified solution.

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

A project that enables an administrator to perform actions within a user session context not just at the time of login but any time later on day(s) or week(s) later.
Auditing domain password hashes is a commonly overlooked but critical requirement to ensuring secure passwords practices are followed. Methods exist to extract hashes directly for a live domain however this article describes a process to extract u…
Exchange organizations may use the Journaling Agent of the Transport Service to archive messages going through Exchange. However, if the Transport Service is integrated with some email content management application (such as an antispam), the admini…
There's a multitude of different network monitoring solutions out there, and you're probably wondering what makes NetCrunch so special. It's completely agentless, but does let you create an agent, if you desire. It offers powerful scalability …

623 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