I am trying to get the source network address for an RDP connection to send an email when a user connects to the server. I have everything but the source address. My script is triggered by event 1149 in the RemoteConnectionManager Operational log. I only need to access either the event data or source address from the system.
$SmtpClient = new-object system.net.mail.smtpClient
$MailMessage = New-Object system.net.mail.mailmessage
$SmtpClient.Host = "mail.scomage.com"
$mailmessage.from = ("BWAQBW#BWAServer.com")
$mailmessage.To.add("support#scomage.com")
$mailmessage.Subject = “BWAQB RDP”
$mailmessage.Body = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name + “ logged into BWA QB Server”
$smtpclient.Send($mailmessage)
Final script after excellent help by Steven:
$LastEvent = Get-WinEvent -FilterHashtable `
#{ LogName = "Microsoft-Windows-TerminalServices-
RemoteConnectionManager/Operational"; Id = 1149} |
Select-Object *,
#{ Name = 'UserName'; Expression = `
{ if ($_.Properties[0].Value) { $_.Properties[0].Value } else { "Administrator" } } },
#{ Name = 'SourceIP'; Expression = { $_.Properties[2].Value } } |
Sort-Object TimeCreated |
Select-Object -Last 1
$MailParams =
#{
SmtpServer = "mail.scomage.com"
From = "BWAQBW#BWAServer.com"
To = "support#scomage.com"
Subject = "BWAQB RDP " + $LastEvent.UserName + " " + $LastEvent.SourceIP
Body = $LastEvent.UserName + " logged into BWA QB Server at " + `
$LastEvent.TimeCreated.ToString('g') + " From: " + $LastEvent.SourceIP
}
Send-MailMessage #MailParams
Script to send logon email:
$Event = Get-WinEvent -FilterHashTable #{
LogName='Security'; ID=4624; StartTime=$DateLess10; } |
Where-Object{$_.Properties[8].Value -eq 10 } |
Sort-Object TimeCreated |
Select-Object -Last 1
if( $Event.Properties[8].Value -eq 10 )
{
$MailParams =
#{
SmtpServer = "mail.scomage.com"
From = "BWAQBW#BWAServer.com"
To = "support#scomage.com"
Subject = "BWAQB Remote Login " + $Event.Properties[5].Value + " " + $Event.Properties[18].Value
Body = $Event.Properties[5].Value + " logged into BWA QB Server at " + `
$Event.TimeCreated.ToString('g') + " From: " + $Event.Properties[18].Value
}
Send-MailMessage #MailParams
}
Updated Based on Comments
Looks like the source address for the connection is recorded as the 3rd property in event 1149. Properties are an object array of type [System.Diagnostics.Eventing.Reader.EventProperty[]] which just means you have to access the sub-property .Value .
An example to get the last event:
$LastEvent =
Get-WinEvent -FilterHashtable #{ LogName = "Microsoft-Windows-TerminalServices-RemoteConnectionManager/Operational"; Id = 1149} |
Select-Object *,
#{ Name = 'UserName'; Expression = { $_.Properties[0].Value } },
#{ Name = 'SourceIP'; Expression = { $_.Properties[2].Value } } |
Sort-Object TimeCreated |
Select-object -Last 1
Since I'm not sure Get-WinEvent will guarantee chronological order the the Sort-Object cmdlet is used. So it should result in the the last 1149 event. However, it doesn't guarantee it will be for the user that was returned by System.Security.Principal.WindowsIdentity]::GetCurrent().Name. I don't know what kind of machine this is or under what circumstances the script will be run. For example if it's a multi-user system (implied by Terminal Server) I suspect there's an edge case where last event may not be for the current user.
So, I'm guessing that we should isolate the last event for that user. We can do that with one of these samples:
Option 1:
$NTUserName = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name
$UserName = $NTUserName.Split('\')[-1]
$Events =
Get-WinEvent -FilterHashtable #{ LogName = "Microsoft-Windows-TerminalServices-RemoteConnectionManager/Operational"; Id = 1149} |
Select-Object *,
#{ Name = 'UserName'; Expression = { $_.Properties[0].Value } },
#{ Name = 'SourceIP'; Expression = { $_.Properties[2].Value } } |
Group-Object -Property UserName -AsHashTable -AsString
$LastEvent = ($Events[$UserName] | Sort-Object TimeGenerated)[-1]
Option 2:
$NTUserName = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name
$UserName = $NTUserName.Split('\')[-1]
$LastEvent =
Get-WinEvent -FilterHashtable #{ LogName = "Microsoft-Windows-TerminalServices-RemoteConnectionManager/Operational"; Id = 1149} |
Select-Object *,
#{ Name = 'UserName'; Expression = { $_.Properties[0].Value } },
#{ Name = 'SourceIP'; Expression = { $_.Properties[2].Value } } |
Where-Object{ $_.UserName -eq $UserName } |
Sort-Object TimeCreated |
Select-Object -Last 1
In both cases $LastEvent should have the last 1149 event for the current user. The first option has less sorting, because it is only sorting events for the specific user. you can use $LastEvent.SourceIP for the email.
A secondary note: You don't need to use System.Net.Mail.SMTPClient. you can use Send-MailMessage combined with command splatting that might look like:
$MailParams =
#{
SmtpServer = "mail.scomage.com"
From = "BWAQBW#BWAServer.com"
To = "support#scomage.com"
Subject = "BWAQB RDP"
Body = $UserName + " logged into BWA QB Server at " + $LastEvent.TimeCreated.ToString('g') + " From: " + $LastEvent.SourceIP
}
Send-MailMessage #MailParams
Note: Above was also updated after your comments to take advantage of the newer revisions. Note: .ToString('g') results in date format like '6/30/2020 9:17 PM'
I'm not sure if the body or subject is exactly right, but you can work that out.
Related
I am trying to retrieve a list of User names from Event Viewer log data. The only selector that I saw available was UserID. I would like to convert that to what I see under General > User instead of a SID. I am a PowerShell beginner so I apologize in advance.
This is the script I am using right now. It works great but I would like to add a User name to the columns.
#Server list
$VDI = Get-Content "C:\Scripts\IM\AvayaList.csv"
#Query remote machines
Invoke-Command $VDI {
$Filter = #{
Logname = 'Citrix-VDA-CQI/Admin'
Level = 1,2,3
StartTime = [datetime]::Today.AddDays(-1)
}
Get-WinEvent -FilterHashtable $Filter
} | Select-Object MachineName,TimeCreated,Level,ID,Message | Out-GridView -Title "Results"
I saw this on another post but I am having a hard time integrating what I have with what I found.
Get-WinEvent -MaxEvents 1000 | foreach {
$sid = $_.userid;
if($sid -eq $null) { return; }
$objSID = New-Object System.Security.Principal.SecurityIdentifier($sid);
$objUser = $objSID.Translate([System.Security.Principal.NTAccount]);
Write-Host $objUser.Value;
}
I am using PowerShell v5.1.14393.3866
Thank you!
You could just write a little helper function to resolve the SIDs. Also, just as you used a variable for your filter hashtable, you can use a variable to store the desired properties to make the code easier to read.
Function Resolve-SID ($sid)
{
if($sid)
{
$objSID = New-Object System.Security.Principal.SecurityIdentifier($sid)
$objSID.Translate([System.Security.Principal.NTAccount]).value
}
else
{
'N/A'
}
}
$selectprops = "MachineName",
"TimeCreated",
"Level",
"ID",
"Message",
#{n="User";e={Resolve-SID $_.UserID}}
#Server list
$VDI = Get-Content "C:\Scripts\IM\AvayaList.csv"
#Query remote machines
Invoke-Command $VDI {
$Filter = #{
Logname = 'Citrix-VDA-CQI/Admin'
Level = 1,2,3
StartTime = [datetime]::Today.AddDays(-1)
}
Get-WinEvent -FilterHashtable $Filter
} | Select-Object $selectprops | Out-GridView -Title "Results"
$status = Get-VMReplication | Select-Object Name, State, Health, Mode, FrequencySec, PrimaryServer, ReplicaServer, ReplicaPort | ConvertTo-Html
$Company = ""
$ReplicationHealth = (Get-VMReplication)
function ReplicationHealthFailedTelegram {
$token = (Get-Content -Path C:\temp\telegrambot\token.txt)
$chatid = (Get-Content -Path C:\temp\telegrambot\chatid.txt)
$Message = "Replication Failed"
$Company = ""
$status = Get-VMReplication | Select-Object Name, State, Health, Mode, FrequencySec, PrimaryServer, ReplicaServer, ReplicaPort | ConvertTo-Html
& 'C:\Program Files\PowerShell\7\pwsh.exe' -Command { $token = (Get-Content -Path C:\temp\telegrambot\token.txt);$chatid = (Get-Content -Path C:\temp\telegrambot\chatid.txt); $status = Get-VMReplication | Select-Object Name, State, Health, Mode, FrequencySec, PrimaryServer, ReplicaServer, ReplicaPort | ConvertTo-Html;$Message = "Replication Failed";$Company = "Howard Matthews Partnership - Harrogate";Send-TelegramTextMessage -BotToken $token -ChatID $chatid -Message $Company $Message}
}
function EmailAlert {
$User = "alert#domain.co.uk"
$File = (Get-Content C:\Temp\pw.txt | ConvertTo-SecureString)
$MyCredential = New-Object -TypeName System.Management.Automation.PSCredential `
-ArgumentList $User, $File
$To = "domain.co.uk"
$from = "domain.co.uk"
$EmailSubject = "Hyper-V Replication Error $Company"
$smtp = "auth.smtp.1and1.co.uk"
$DefaultMessage="
<p>Dear Help,</p>
<p>Replication has failed for $Company </p>
<p>$status</p>
<p>The Robot Checker .<br><br>
</p>"
$MailMessage = #{
To = $To
From = $from
# BCC = $Bcc
Subject = $EmailSubject
Body = $DefaultMessage
priority = "High"
Smtpserver = $smtp
Credential = $MyCredential
ErrorAction = "SilentlyContinue"
}
Send-MailMessage #MailMessage -bodyashtml
}
if ($ReplicationHealth.health) {
"Critical","Warning"
EmailAlert
ReplicationHealthFailedTelegram
} else {
$null
}
The Email sends but it regardless if the status of the replication is normal, warning or critical. How would I go by adding the logic of getting to send me an email when that health status is Critical or Warning and not send me an email when it's normal.
Many Thanks!
This bit doesn't do what you think it should
if ($ReplicationHealth.health) {
"Critical","Warning"
EmailAlert
ReplicationHealthFailedTelegram
} else {
$null
}
With your if you are basically asking; "is $ReplicationHealth.Health a thing?" rather than checking for the value "of the thing", and the answer will always be yes in this case assuming nothing went wrong running Get-VMReplication.
A different example to demonstrate what I mean could be something like the following
if($(Get-ChildItem -Path "$env:windir\System32\WindowsPowerShell\v1.0\powershell.exe").Extension) { "Yup, .Extension is a thing" } else { "Nah, it's not!" }
if($(Get-ChildItem -Path "$env:windir\System32\WindowsPowerShell\v1.0\powershell.exe").Extension -eq ".exe") { "Yup, .Extension is a thing and its value is `'.exe`'" } else { "Nah, it's not!" }
In order to fix your if, you could try something like
if($ReplicationHealth.Health -eq "Critical" -or $ReplicationHealth.Health -eq "Warning") {
EmailAlert
ReplicationHealthFailedTelegram
}
The goal : get all logged in / logged out users from the system.
Those users who logged in / logged out by using remote desktop connection.
My script :
Param(
[array]$ServersToQuery = (hostname),
[datetime]$StartTime = "January 1, 1970"
)
foreach ($Server in $ServersToQuery) {
$LogFilter = #{
LogName = 'Microsoft-Windows-TerminalServices-LocalSessionManager/Operational'
ID = 21, 23, 24, 25
StartTime = $StartTime
}
$AllEntries = Get-WinEvent -FilterHashtable $LogFilter -ComputerName $Server
$AllEntries | Foreach {
$entry = [xml]$_.ToXml()
[array]$Output += New-Object PSObject -Property #{
TimeCreated = $_.TimeCreated
User = $entry.Event.UserData.EventXML.User
IPAddress = $entry.Event.UserData.EventXML.Address
EventID = $entry.Event.System.EventID
ServerName = $Server
}
}
}
$FilteredOutput += $Output | Select TimeCreated, User, ServerName, IPAddress, #{Name='Action';Expression={
if ($_.EventID -eq '21'){"logon"}
if ($_.EventID -eq '22'){"Shell start"}
if ($_.EventID -eq '23'){"logoff"}
if ($_.EventID -eq '24'){"disconnected"}
if ($_.EventID -eq '25'){"reconnection"}
}
}
$Date = (Get-Date -Format s) -replace ":", "."
$FilePath = "$env:USERPROFILE\Desktop\$Date`_RDP_Report.csv"
$FilteredOutput | Sort TimeCreated | Export-Csv $FilePath -NoTypeInformation
Write-host "Writing File: $FilePath" -ForegroundColor Cyan
Write-host "Done!" -ForegroundColor Cyan
#End
I really do not understand ps1 scripts. I've found this script but i want to use it for my purposes.
When i try to execute it with c# :
Scenario 1 :
string scriptText = "C:\\MyPath\\script.ps1";
try
{
Runspace runspace = RunspaceFactory.CreateRunspace();
// open it
runspace.Open();
// create a pipeline and feed it the script text
Pipeline pipeline = runspace.CreatePipeline();
pipeline.Commands.AddScript(scriptText);
Collection<PSObject> results = pipeline.Invoke();
It throws an error :
ps1 is not digitally signed.
Second scenario :
using (PowerShell PowerShellInstance = PowerShell.Create())
{
PowerShellInstance.AddScript(str_Path);
Collection<PSObject> PSOutput = PowerShellInstance.Invoke();
if (PowerShellInstance.Streams.Error.Count > 0)
{
// error records were written to the error stream.
// do something with the items found.
}
}
Streams are always empty. Actually it always count 0 rows.
Any idea/suggestion how to get this done ?
I used Write-Output instead of Write-Host into the end of the script without generating csv file. Credits to this.
I am having a bit of a tough time writing a script for exchange. I have an environment, that has a hybird environment. I am trying to make a power shell script to find all large distro groups and email the owners of the groups to clean them up. However, I am having issues with pulling the owner email and and name for the email portion of the script.
But, there are a few restrictions, I can't use AD powershell, exchange only. and I can't use the get-mailbox cmdlet.
add-pssnapin microsoft.exchange.management.powershell.e2010
set the scope of the search
Set-ADServerSettings -ViewEntireForest $true
$DistGroups = Get-DistributionGroup -ResultSize 2
ForEach ($Group in $DistGroups) {
#Get each group details
$MemberCount = (Get-DistributionGroupMember $Group).count
$GroupName = (Get-DistributionGroup $Group).DisplayName
$Owner = (Get-DistributionGroup $Group).ManagedBy
$OwnerEmail = Get-recipient -identity $Owner | select PrimarySmtpAddress
$OwnerFN = Get-Recipient -identity $Owner | Select FirstName
If ( $MemberCount > 50000) {
#define email stuff
$messageBody = "Hi, <b>$OwnerFN,</b><p>"
$messageBody += "We are auditing distribution groups in our environment and your group, $GroupName, was flagged as being
<font color=red>really large</font>. The current member count is <font color=red> $MemberCount</font>.<p>"
$messageBody += "Please take steps to update the group and clear out unnecessary or old group members… <p>"
$messageBody += "Thanks, <p>"
$messageBody += "The Exchange Admin Team"
#Send the mail
$email = New-Object System.Net.Mail.MailMessage
$email.From = "Email_Group_Admin_Report#Internal.Mail.company.com"
$email.To.Add("me#company.com")
#$email.To.Add("$OwnerEmail")
#$email.CC.Add("#company.com")
#$email.BCC.Add("admin#company.com")
$email.DeliveryNotificationOptions = [System.Net.Mail.DeliveryNotificationOptions]::OnSuccess
$email.IsBodyHtml = $True
$email.Priority = [System.Net.Mail.MailPriority]::High
$email.Subject = "Distribution Group Audit"
$email.Body = $messageBody | Out-String
$smtp = New-Object System.Net.Mail.SmtpClient
$smtp.Host = "mail.compnany.com"
$smtp.Send($email)
}
}
I am able to get the count, and the Distro name, I can't seem to get the managed by property or the other stuff, it spits out an entire list of primary emails and Firstnames and such... The managed by property doesn't seem to appear....
$OwnerEmail = Get-recipient -identity $Owner | select PrimarySmtpAddress
This will return an object, but when you send the email you're acting as if you have a string.
email.To.Add("$OwnerEmail")
Option A:
($OwnerEmail = Get-recipient -identity $Owner).PrimarySmtpAddress
email.To.Add($OwnerEmail)
Option B:
$OwnerEmail = Get-recipient -identity $Owner | select PrimarySmtpAddress
email.To.Add($OwnerEmail.PrimarySmtpAddress)
I had a tough time with the output formats, but I finally got it working as expected. Thought I would post the working script here... Maybe you will find it useful.
add-pssnapin microsoft.exchange.management.powershell.e2010
# Find all Distros
$DistGroups = Get-DistributionGroup -ResultSize unlimited
ForEach ($Group in $DistGroups) {
#Get each group details
if ($Group.managedby -ne $null) {
$t = $Group.Managedby
$t | foreach { $Owner = $_.Name }
}
else {
$Owner = "Unknown"
$DL_Name = $Group.displayname
}
$MemberCount = (Get-DistributionGroupMember $Group).count
if ($Owner -eq "Unknown") { echo "The owner is unknown!"
}
#set membercount catch here
elseIf ( $MemberCount -gt 2000) {
$OwnerEm = get-recipient $Owner | select PrimarySmtpAddress | ft -HideTableHeaders | out-string
#$OwnerEm = get-recipient me#company.com | select PrimarySmtpAddress | ft -HideTableHeaders | out-string
#define email stuff
$messageBody = "Hi, <b>$Owner,</b><p>"
$messageBody += "We are auditing distribution groups in our environment and your group, $DL_Name, was flagged as being <font color=red>really large</font>. The current member count is <font color=red> $MemberCount</font>.<p>"
$messageBody += "Please take steps to update the group and clear out unnecessary or old group members… <p>"
$messageBody += "Thanks, <p>"
$messageBody += "The Exchange Admin Team"
#Send the mail
$email = New-Object System.Net.Mail.MailMessage
$email.From = "Email_Group_Admin_Report#Internal.Mail.company.com"
#$email.To.Add("me#company.com")
$email.To.Add("$OwnerEm")
#$email.CC.Add("#company.com")
#$email.BCC.Add("admin#company.com")
$email.DeliveryNotificationOptions = [System.Net.Mail.DeliveryNotificationOptions]::OnSuccess
$email.IsBodyHtml = $True
$email.Priority = [System.Net.Mail.MailPriority]::High
#$attachment = "C:\myfile.txt"
#$email.Attachments.Add( $attachment )
$email.Subject = "Distribution Group Audit"
$email.Body = $messageBody | Out-String
$smtp = New-Object System.Net.Mail.SmtpClient
$smtp.Host = "mail.company.com"
$smtp.Send($email)
echo "the $DL_Name has a high member count. The member count is $MemberCount. The manager has been sent and email at $OwnerEm"
}
else {
echo "the $DL_Name seems fine! The member count is $MemberCount. The manager '$Owner' is doing great!"
}
}
I left the echo statements in so you can view the statuses via a console, or pipe them to a file.... or something...
So basically, what I have here is a script that will scan a CSV that it imports, and for every entry in the spreadsheet, except for people in the RANDOM.DOMAIN, it will find the managers email address and send an automated email to the manager telling them user XYZ is about to expire soon, and they need to do something about it.
If the managers email is unavailable for some reason, then it defaults to sending the email to me.
This script works well.
The problem I am running into is, I want to make it so only one email is sent to each manager, despite multiple users (or entries) from the spreadsheet, list them as the manager.
I.e. if Joe Bloggs has a manager Aaron T and Jane Doe has the manager Aaron T, then Aaron T will get two emails, one email for each user.
MY QUESTION:
Is there an easy way to only get it to send one email per manager, even if that manager has multiple users reporting to them that are about to expire?
$datai = Import-Csv "Soon-to-expire User Accounts22.csv" | select 'Display Name',Manager,'Domain Name','Account Expiry Time'
Connect-QADService -Service another.DC | Out-Null
$expiringUsers = #{}
foreach ($i in $datai) {
$dn = $i.'Display Name'
$dn1 = $i.'Domain Name'
$man = $i.'Manager'
$aet = $i.'Account Expiry Time'
$subject = "Account about to expire: $dn"
$getmail = get-qaduser "$man" -LdapFilter '(mail=*)' | select mail
$emailAD = $getmail.mail
if ($man -eq "-" -or $man -like 'CN=*' -or $getmail -eq $null -or $man -eq "") {
$man = "Aaron T"
$getmail = get-qaduser "$man" -LdapFilter '(mail=*)' | select mail
$emailAD = $getmail.mail
}
if ($expiringUsers.Contains($emailAD)) {
$expiringUsers[$emailAD]["dn"] += $dn += "`n"
$expiringUsers[$emailAD]["aet"] += $aet += "`n"
$expiringUsers[$emailAD]["man"] += $man += "`n"
} else {
$expiringUsers[$emailAD] = #{
#"dn1" = $dn1
#"aet" = $aet
#"man" = $man
# "dn" = #( $dn )
}
}
}
$expiringUsers | fc #as suggested
foreach ($emailAD in $expiringUsers.Keys) {
$dn = $expiringUsers[$emailAD]["dn"]
$dn1 = $expiringUsers[$emailAD]["dn1"]
$man = $expiringUsers[$emailAD]["man"]
$aet = $expiringUsers[$emailAD]["aet"]
$subject = "Account/s About to Expire!"
$content = #"
Hi,
$dn `n
$dn1 `n
$man `n
$aet `n
$emailAD `n
Technology Services
"#
Send-MailMessage -from "aaron#website.com" `
-To $emailAD `
-Subject $subject `
-Body $content `
-Priority high `
-smtpServer "relay.server"
#using this as a test instead of sending mass emais all the time
Write-Host $content
}
UPDATED with the new script as requested.... still having issues.
Is there an easy way to only get it to send one email per manager, even if that manager has multiple users reporting to them that are about to expire?
For this you need to defer e-mail processing. Collect the users in a hashtable, e.g. by manager e-mail address:
...
$expiringUsers = #{}
foreach ($i in $datai) {
If ($i.'Domain Name' -notmatch "RANDOM.DOMAIN") {
...
if ($expiringUsers.Contains($emailAD)) {
$expiringUsers[$emailAD]["dn"] += $dn
} else {
$expiringUsers[$emailAD] = #{
"dn1" = $dn1
"aet" = $aet
"man" = $man
"dn" = #( $dn )
}
}
}
}
and move the actual e-mail processing outside the loop:
foreach ($emailAD in $expiringUsers.Keys) {
$dn1 = $expiringUsers[$emailAD]["dn1"]
$man = $expiringUsers[$emailAD]["man"]
$aet = $expiringUsers[$emailAD]["aet"]
$subject = "Account about to expire: $($expiringUsers[$emailAD]["dn"])"
$content = #"
Hi,
...
Technology Services
"#
Send-MailMessage -from "Test Script - Powershell <email#test.com>" `
-To "$emailAD" `
-Subject $subject `
-Body $content `
-Priority high `
-smtpServer servername
Write-Host "Mail Sent to $man"
}
Note that for simplicity reasons the above code only records the expiry date of the first user. If you want the expiry date of each user recorded separately, you'll have to take additonal steps, e.g.
$expiringUsers[$emailAD]["expiry"] += #{
"name" = $dn;
"date" = $aet;
}
instead of
$expiringUsers[$emailAD]["dn"] += $dn
So I finally decided to revisit this script, after many, many months.
I'm get a little better at PowerShell and while I'm sure this isn't the most effective way to do it, this is something that works for me.
I've also changed the input method; it pulls the information directly from AD, instead of using a CSV file that used to be generated from an application called 'AD Manager Plus' (Hate it).
Remember, using Quest CMDlets here because we don't have a 2008 environment. (so using Get-QADUser instead of Get-ADuser)
FYI, I have only posted the code here which sorts out the data into separate tables - you can decide how you want to utilize those results. For our environment, I have it build an nice HTML table and body, then send it to the appropriate manager to deal with.
#user data input
$data = get-qaduser -SizeLimit 0 -includedproperties accountexpires | where {$_.AccountExpires -ne $null -and $_.AccountExpires -le ((Get-Date).AddDays(45)) }
#get a list of managers, unique.
$uniqueMan = $data | select Manager -Unique
#foreach manager from $uniqueman
Foreach ($manager in $uniqueman) {
#create the array variable / clear it out for the next manager.
$myarray = #()
#foreach User found in in $data query
Foreach ($user in $data) {
#Search the $user's query for people with the same manager as that of the $uniqueman list.
If ($user.Manager -eq $manager.Manager) {
#do what with the result.
#add the person to an array
$myarray += New-Object psobject -Property #{
Name = $user.'Name'
UserName = $user.'SAMAccountName'
AccountExpires = $user.'AccountExpires'
Manager = $user.Manager
}
}
#for testing, to output the results to an HTML file.
#$myarray | ConvertTo-Html | Out-File ("C:\test\" + $manager.Manager + ".html")
}
}