I have a script file that when ran from within ISE or from the powershell window it works fine. But when ran trough the task scheduler with "runas" the same account it only outputs half the data.
After some troubleshooting i have concluded that the part of the code that is not working is:
Get-ADOrganizationalUnit -SearchBase $OU -Filter {objectclass -eq "organizationalunit"} -SearchScope onelevel -Properties description |
% {
$mailbox = #( get-user -OrganizationalUnit $_.distinguishedName -resultsize unlimited |
? { $_.title -ne "xxx" -and $_.RecipientType -eq "usermailbox" -and $_.RecipientTypeDetails -ne "RoomMailbox" } )
if ($mailbox.count -gt 0) {
$name = $_.name
$mail_customer = $body
$mail_customer += "<h3>" + $name + "</h3>"
$mail_customer += $mailbox | get-MailboxStatistics |
select displayname, lastlogontime, #{ label = "Mailbox Size(MB)"; expression = {
if ($_.totalitemsize.value.toMB() -gt 25600) { "!!!" + $_.TotalItemSize.Value.ToMB() }
else { $_.TotalItemSize.Value.ToMB() }
} } | Sort-Object displayname | ConvertTo-Html -Fragment | Out-String
$count += $mailbox.count
$stattable += #{$name = $mailbox.count}
$mail_customer = $mail_customer | ForEach-Object { $_ -replace '!!!', '<font color="#FF0000">' }
if ( $_.description -ne $null ) {
$mailaddresses = $_.description.split(",")
Send-MailMessage `
-SmtpServer $SMTPserver `
-Encoding $encoding `
-From "$company <noreply#$companylower.se>" `
-To $mailaddresses `
-Subject "$company report - $name - $date" `
-BAH `
-Body $mail_customer
}
$mail += $mail_customer
$mailaddresses = "";
}
}
I get the email but it does not include the information that these lines should output, any ideas?
Script is called like this: powershell -file c:\temp\scriptname.ps1
This is a classic case of not running something elevated. Nothing in the code was wrong.
In Task Scheduler, make sure "Run with highest privileges" is ticked in for the task or it will not work.
Related
The below script to get the logon users and send as email was working great but only on the console output only.
I am trying to get the result as a table so the result in the console and the email body will be like:
Server, ConnectionType, User, ID, State
PRDSVR16, rdp-tcp#44, SVC-SQL, 4, Active
PRDSVR10, rdp-tcp#27, Admin.domain, 6, Disc
SVR25-VM,console,domain.admin,8,Active
Open in new window
This is the script:
$Today = Get-Date -Format 'F'
$SessionList = "`n`nRDP Session List - " + $Today + "`n`n"
$CurrentSN = 0
# Get a list of servers from Active Directory
write-progress -activity "Getting list of servers from Active Directory" -status "... please wait ..."
$Servers = (Get-ADComputer -Filter { Enabled -eq $True -and OperatingSystem -like "*Server*" } -Properties OperatingSystem -SearchBase "OU=Data Center,DC=Company,DC=com") |
Where-Object { Test-Connection $_.Name -Count 1 -Quiet } |
Select-Object -ExpandProperty Name
$NumberOfServers = $Servers.Count
# Iterate through the retrieved list to check RDP sessions on each machine
ForEach ($Server in $Servers)
{
Write-Host "Processing $Server ..." -ForegroundColor Yellow
Write-progress -activity "Checking RDP Sessions" -status "Querying $Server" -percentcomplete (($CurrentSN / $NumberOfServers) * 100)
try
{
$SessionList += qwinsta /server:$Server |
Select-Object -Skip 1 |
% {
[PSCustomObject] #{
Type = $_.Substring(1, 18).Trim()
User = $_.Substring(19, 20).Trim()
ID = $_.Substring(41, 5).Trim()
State = $_.Substring(48, 6).Trim()
}
} |
? { $_.Type -notin 'console', 'services', 'rdp-tcp' -and $_.User -ne $null -and $_.User -ne 65536 } |
% {
"`n$Server logged in by $($_.User) on $($_.Type), session id $($_.ID) $($_.state)"
}
}
catch
{
$SessionList += "`n Unable to query " + $Server
write-host "Unable to query $Server! `n $($Error[0].Exception)" -foregroundcolor Red
}
$CurrentSN++
}
# Send the output the screen.
$SessionList + "`n`n"
$sendMailArgs = #{
From = "$env:USERNAME#$env:userdnsdomain"
To = 'SOC#domain.com'
SmtpServer = 'SMTP.domain.com'
Priority = 'High'
Body = $SessionList | Select-Object #{ N = 'Server'; E = { $Server } },
#{ N = 'User'; E = { $_.User } },
#{ N = 'LogonType'; E = { $_.Type } },
#{ N = 'ID'; E = { $_.ID } },
#{ N = 'State'; E = { $_.State } }
Subject = "$($SessionList.Count) Logged On users from $($NumberOfServers) online servers as at $($Today)"
}
Send-MailMessage #sendMailArgs
Rendering collected information in different places is way easier if you keep strict separation between data and presentation (or formatting) of said data.
For the $SessionList for example, that means doing less than what you're currently trying to do inside the loop:
$ErrorList = #()
$SessionList = foreach($server in $servers){
try{
qwinsta /server:$Server |Select-Object -Skip 1 |ForEach-Object {
[PSCustomObject] #{
Server = $server
Type = $_.Substring(1, 18).Trim()
User = $_.Substring(19, 20).Trim()
ID = $_.Substring(41, 5).Trim()
State = $_.Substring(48, 6).Trim()
}
} |Where-Object { $_.Type -notin 'console', 'services', 'rdp-tcp' -and $_.User -ne $null -and $_.User -ne 65536 }
}
catch{
$ErrorList += [pscustomobject]#{
Server = $server
ErrorRecord = $_
}
}
}
Notice how I don't construct any strings - I just create the custom objects, filter them - and then leave them as-is.
Now it becomes much easier to format the data as desired for different output media:
# For console output, simply pipe to Format-Table
$SessionList |Format-Table
if($ErrorList.Count -gt 0){
Write-Warning "The following servers had errors, please inspect"
$ErrorList |Format-Table
}
# For email output we can use `ConvertTo-Html`
$Body = $SessionList |ConvertTo-Html -As Table -Fragment
if($ErrorList.Count -gt 0){
$ErrorTable = $ErrorList |ConvertTo-Html -As Table -Fragment
$Body = $Body,$ErrorTable -join '<br />'
}
$sendMailArgs = #{
# ...
Body = ConvertTo-Html -Body $Body -Title "Session list"
BodyAsHtml = $true
# ...
}
I want to determine all users from several Domains where the difference between Password expiration date and today date is less than 14 days. Later I want to write a notification mail to all users with powershell. How do I write the Content from Surname to a variable?
Here is my given Code:
$datacoll =#()
$domains = "domain1","domain2","domain3"
$expindays = 14
$today = Get-Date
foreach($domain in $domains){
$datacoll += Get-ADUser -Server $domain -filter {Enabled -eq $True -and PasswordNeverExpires -eq $False} `
–Properties “SamAccountName”,”mail”,"GivenName","Surname",”pwdLastSet”,”msDS-UserPasswordExpiryTimeComputed” | where{$_.mail -ne $null} |
Select-Object -Property “SamAccountName”,”mail”,"GivenName","Surname",#{Name=”Password Last Set”;`
Expression={[datetime]::FromFileTime($_.”pwdLastSet”)}}, #{Name=”Password Expiry Date”;`
Expression={[datetime]::FromFileTime($_.”msDS-UserPasswordExpiryTimeComputed”)}}
}
#iterate surname?
# foreach($user in $Surname){
# }
#datacoll output
$datacoll | Export-Csv "C:\pw.csv" -NoTypeInformation -Encoding utf8
What you can do is use DirectoryServices and DirectoryServices.AccountManagement which are part of the .NET framework
You can load .Net assemblies like this using system.reflection.assembly
[system.reflection.assembly]::LoadWithPartialName("System.DirectoryServices") | out-null
You then will create a domain context (Connection to AD) and a searcher object that will go through the domain looking for user objects.
I wrote a function to return users that match a range (How close to expiration date) and a Domain. It will then return a array of directory entries so you can get the information you prefer.
function Get-ADPasswordExpirationDates(){
param(
[Parameter(Mandatory=$True)]
[string]$Domain,
[int]$Range = 14
)
#Call .Net Active Directory Assembies
[system.reflection.assembly]::LoadWithPartialName("System.DirectoryServices") | out-null
[system.reflection.assembly]::LoadWithPartialName("System.DirectoryServices.AccountManagement") | out-null
#Get Domain Context
$Context = new-object System.DirectoryServices.AccountManagement.PrincipalContext(`
[System.DirectoryServices.AccountManagement.ContextType]::Domain,`
$domain
)
#Create Searcher Object looking for User Objects
$Search = new-object System.DirectoryServices.AccountManagement.PrincipalSearcher(`
new-object System.DirectoryServices.AccountManagement.UserPrincipal(`
$Context
)
)
#Arry Varable for holding return reply
$Reply = #()
#For Each User in search
foreach($Result in $Search.FindAll()){
#Turn Result into a Directory Entry
[System.DirectoryServices.DirectoryEntry] $Entry = $Result.GetUnderlyingObject()
#Get Expiration Date
$Expiration = $Entry.InvokeGet("PasswordExpirationDate")
#Create a Timespan from Todays date to Expiration date
$Timespan = $(New-TimeSpan -Start $(get-date) -End $Expiration).Days
#If days are less then $RANGE add Directory Entry to array
if($Timespan -lt $Range -and $Timespan -gt -1 ){
$Reply += $Entry
}
}
return $Reply
}
Here is a quick example of how to use it to get information form the directory object.
$AlmostExpiredUsers = Get-ADPasswordExpirationDates -domain MyAwesomeDomainName -Range 14
foreach($User in $AlmostExpiredUsers){
Write-Output "Username : $($user.SamAccountName)`r`nFull Name : $($user.Properties.name)`r`nEmail : $($user.Properties.mail)`r`nExpires : $($user.InvokeGet("PasswordExpirationDate"))`r`n`r`n"
}
I use this script to send email to user about there password expiration
$MaxPasswordAgeTimeSpan = (Get-ADDefaultDomainPasswordPolicy).MaxPasswordAge
Get-ADUser -Filter * -SearchBase "OU=Admin user,DC=test,DC=test" -properties PasswordLastSet,
PasswordExpired,
PasswordNeverExpires,
EmailAddress,
DisplayName,
GivenName,
SN |
foreach {
$UserName = $_.DisplayName
$SN = $_.SN
$Email = $_.EmailAddress
$today = Get-Date
$enc = New-Object System.Text.utf8encoding
$ExpiryDate = $_.PasswordLastSet + $maxPasswordAgeTimeSpan
$DaysLeft = ($ExpiryDate-$today).days
If ($DaysLeft -lt 7 -and $DaysLeft -gt 0)
{
Send-mailmessage -to $Email -from noreply#noreply.com -Subject "enter subject" -body "enter body here" -smtpserver x.x.x.x -BodyAsHtml -Encoding $enc
}
Here is a minimal solution. The 14 days timespan, you achieve with:
foreach($user in $datacoll){
$StartDate=(Get-Date).Date
$EndDate=([datetime] $user."Password Expiry Date").Date
$diff = (New-TimeSpan -Start $StartDate -End $EndDate).Days
$firstname = $user.GivenName
$surname = $user.Surname
#body content in variable for parameter in Send-MailMessage
$body = #"
Dear Sir or Madam,
Your Password will expire in $diff days,
please change your password.
Sincerely
IT
"#
}
Than you can check the $diff variable with if, else Statement and send mail to all users with:
if($diff -le 14){
Send-MailMessage -from "Helpdesk <helpdesk#noreply.com>" -to "$firstname $surname<$user.mail>" -subject "Password Expiration in $diff days" -smtp "smtpserver" -body $body
}
To check multiple Domain Controllers you can define multiple Domain Controller with:
$dcs = "domaincontroller1","domaincontroller2","domaincontroller3"
And inlcude a foreach Loop.
With the Option -Server you can Transfer the Parameter $i to achieve all users from all Domain Controllers.
Hint: You can only perform this script from your root Domain Controller.
foreach($i in $dcs){
$datacoll += Get-ADUser -Server $i -filter {Enabled -eq $True -and PasswordNeverExpires -eq $False -and mail -like '*'} `
–Properties “SamAccountName”,"GivenName","Surname",”mail”,”pwdLastSet”,”msDS-UserPasswordExpiryTimeComputed” |
Select-Object -Property “SamAccountName”,"GivenName","Surname",”mail”,#{Name=”Password Last Set”;`
Expression={[datetime]::FromFileTime($_.”pwdLastSet”)}}, #{Name=”Password Expiry Date”;`
Expression={[datetime]::FromFileTime($_.”msDS-UserPasswordExpiryTimeComputed”)}}
}
}
I am trying to pull a list of all users in my O365 Tenant and if they are licensed, the list of sublicenses they have been granted. The following code works great to list out my sublicenses:
$userlicensetest = get-msoluser -userprincipalname "steve.dorr#merrillcorp.com"
$userlicensetest.licenses[0].servicestatus
ServicePlan :: ProvisioningStatus
----------- :: ------------------
INTUNE_O365 :: PendingActivation
YAMMER_ENTERPRISE :: PendingInput
OFFICESUBSCRIPTION :: Success
So I tried to modify code I found online to include the sublicense information. Here is what I have built so far:
$ReportPath = "c:\users\userlist.csv"
Add-Content -value ("UserPrincipalName"+","+"IsLicensed"+","+ "Licenses”"+","+ "SubLicenses") -Path $ReportPath
$AllUsers = Get-MsolUser -All
foreach ($User in $AllUsers)
{
$UserPrincipalName = $User.UserPrincipalName
$IsLicensed = $User.IsLicensed
$Licenses = $User.Licenses.AccountSkuId
$SubLicenses = $User.Licenses[0].servicestatus
Add-Content -value ($UserPrincipalName+","+$IsLicensed+","+$Licenses+","+$SubLicenses) -Path $ReportPath
}
The problem is it is only pulling the header line from the sublicense query and not all the lines of detail. So the line for myself in the CSV looks like:
Steve.Dorr#MerrillCorp.com TRUE mymerrillcorp:ENTERPRISEPACK Microsoft.Online.Administration.ServiceStatus Microsoft.Online.Administration.ServiceStatus Microsoft.Online.Administration.ServiceStatus Microsoft.Online.Administration.ServiceStatus Microsoft.Online.Administration.ServiceStatus Microsoft.Online.Administration.ServiceStatus Microsoft.Online.Administration.ServiceStatus Microsoft.Online.Administration.ServiceStatus
Which does not give me the detail lines I needed.
How do I pull all the lines that Licenses[0].servicestatus generates into the CSV file? I don't care whether it flattens it out and goes across more columns, or takes up multiple lines in Excel.
Thanks.
So since I posted this question I have worked a little on it. I do not have a perfect solution that puts this into a nice neat CSV file, but I do have a routine which now drops all this information into a text file. Below is my code.
$MyCredentials = Get-Credential -Message "Enter Office 365 Email & Password"
Connect-MsolService -Credential $MyCredentials
$ReportFile = "C:\temp\O365Data.txt"
" " | Out-File $ReportFile #erases the file if it exists
$AllUsers = Get-MsolUser -All
foreach ($User in $AllUsers)
{
$UserPrincipalName = $User.UserPrincipalName
$IsLicensed = $User.IsLicensed
$Licenses = $User.Licenses.AccountSkuId
$SubLicenses = $User.Licenses[0].servicestatus
$OneLine = $UserPrincipalName + " " + $IsLicensed
$OneLine| Out-File $ReportFile -Append
if($User.Licenses[0].servicestatus) {$User.Licenses[0].servicestatus | Out-File $ReportFile -Append}
}
To create the report you'll need to create custom objects to hold the properties you are interested in.
The following will take into account all the different licenses that could be applied to a user and then generate a csv with one user listed per line.
# Connect to o365
$MyCredentials = Get-Credential -Message "Enter Office 365 Email & Password"
Connect-MsolService -Credential $MyCredentials
# Prepare result file
$ExportFile = ".\o365Output.csv"
Remove-Item $ExportFile
$Result = #()
# Query all Msol Users
$AllUsers = Get-MsolUser -All
foreach ($User in $AllUsers)
{
# Generate a new object for each user
$ReturnObject = [pscustomobject]#{
UserPrincipalName = $User.UserPrincipalName
IsLicensed = $User.IsLicensed
Licenses = [string]$User.Licenses.AccountSkuId
}
# In the event multiple licenses are found append properties for each license
foreach ($License in $User.Licenses)
{
if($($License.ServiceStatus.ServicePlan.ServiceName).count -eq 1)
{
$ReturnObject | Add-Member -MemberType NoteProperty -Name $License.ServiceStatus.ServicePlan.ServiceName -Value $License.ServiceStatus.ProvisioningStatus
}
else
{
for($i = 0; $i -lt $($License.ServiceStatus.ServicePlan.ServiceName).count; $i++)
{
$ReturnObject | Add-Member -MemberType NoteProperty -Name $License.ServiceStatus.ServicePlan.ServiceName[$i] -Value $License.ServiceStatus.ProvisioningStatus[$i]
}
}
}
$Result += $ReturnObject
}
# Combine properties from all returned objects
$Properties = $Result | ForEach-Object { Get-Member -InputObject $_ -MemberType NoteProperty | Select-Object -ExpandProperty Name } | Select-Object -Unique | Sort-Object
$Headers = #("UserPrincipalName")
$Headers += $Properties -notlike "UserPrincipalName"
# Export to csv
$Result | Select-Object $Headers | Export-Csv -NoTypeInformation $ExportFile
# Open csv
Invoke-Item $ExportFile
I am trying to create a script that will compare our AD against all the users in a CSV. Our HR department has the master database for all staff but when they make changes they rarely inform us so they now export all users from the HR database to a CSV.
I need to compare this against our AD and amend anyone that has been found to have changed or any new staff.
I have the below script but it just outputs all staff, I only want the staff that have changed or new staff that are not in AD to be emailed.
write-host "Using default CSV file or C:\scripts\csv\StaffChanges.csv"
$StaffCSVUPath = "C:\scripts\csv\StaffChanges.csv"
$logfile = "C:\scripts\logs\ADvsCMIS.csv"
if(test-path $logfile) {
remove-item $logfile -force
}
function Email {
#Send an email, called with recipient email address and message body
param(
[string] $emailaddress="",
[string] $bodymsg=""
)
$bodymsg += "<p>"
$bodymsg += Get-Content($logfile)
Send-MailMessage -To $emailaddress -From "email#domain.co.uk" -Subject "(AD-CMIS_errors) Errors found between Active Directory and CMIS" -Body $bodymsg -BodyAsHTML -SMTPServer "exchserver"
}
function CheckOutputFile {
#Called with folder\filename and type of file
param(
[string]$outputfilename = "",
[string]$type = ""
)
if(test-path($outputfilename)) {
} else {
write-host "Creating $outputfilename"
$msg = "Forename,Surname,Username,ID"
$msg | out-file($outputfilename)
}
}
#Snap-ins needed to use the commands within the script
if((Get-pssnapin -Name Microsoft.Exchange.Management.Powershell.E2010 -ErrorAction SilentlyContinue) -eq $null){Add-PSSnapin Microsoft.Exchange.Management.PowerShell.E2010}
if((Get-pssnapin -Name Quest.activeroles.admanagement -ErrorAction SilentlyContinue)-eq $null){Add-pssnapin Quest.activeroles.admanagement}
#import users from csv file
$users = (import-Csv $StaffCSVUpath)
$count=0
$countAD=0
Get-QADUser -searchroot "domain/Users/Staff" -SizeLimit 0 -includedproperties employeeid,displayname | ForEach-Object ($_.samaccountname) {
$found = 0
$countAD+=1
ForEach ($user in $users) {
$count+=1
$inital = $user.forename.substring(0,1)
$name = $user.forename+" "+$user.surname
$dispname = $inital+" "+$user.surname
if ($user.id -eq $_.employeeid) {
if ($user.surname -eq $_.lastname) {
if ($inital -eq $_.firstname) {
if ($name -eq $_.name) {
if ($dispname -eq $_.displayname) {
$found = 1
}
}
}
}
}
if ($found -eq 1){break}
}
if ($found -eq 0) {
if(($_.company -ne "testing") -band ($_.company -ne "service")) {
CheckOutputFile $logfile "LOG"
$msg = "<p>" + $_.firstname +" " + $_.lastname + " " + $_.samaccountname + " "+$_.employeeid +"<p>"
$msg | Out-File $logfile -append
}
}
}
if (test-path $logfile) {
#If there is anything to report
write-host "Emailing Log file to ict"
#Email file if $outputB exists
$email = "email#domain.co.uk"
$body = "Action Required: The users below do not exist within HR. Contact HR Data manager to resolve issue, delete users manually if required."
#email ict
Email $email $body
}
I don't use the Quest AD cmdlets, so my answer will be based on the built-in ones. Also, I'm going to assume that the (unique) employee ID for any given employee is not going to change and that there are no user accounts with an empty employeeId attribute.
First, prepare your data like this:
Import-Module ActiveDirectory
$hrUsers = #{}
Import-Csv 'C:\path\to\your.csv' |
select id, firstname, surname,
#{n='inital';e={$_.forename.substring(0,1)}},
#{n='name';e={$_.forename+" "+$_.surname}},
#{n='dispname';e={$_.forename.substring(0,1)+" "+$_.surname}} |
% { $hrUsers[$_.id] = $_ }
$adUsers = Get-ADUser -Filter * -Property employeeid |
? { 'testing', 'service' -notcontains $_.company }
This creates a hashtable mapping each employee ID to the object with the respective user's attributes (including the derivative attributes initial, name, and dispname) and a list of AD users (excluding service and test accounts).
With the above you can determine new users like this:
$employeeIDs = #($adUsers | select -Expand employeeId)
$hrUsers.Values | ? { $employeeIDs -notcontains $_.id }
obsolete accounts like this:
$adUsers | ? { $hrUsers.Keys -notcontains $_.employeeId }
and modified users like this:
$adUsers | ? {
$hrUsers[$_.employeeid].surname -ne $_.lastname -or
$hrUsers[$_.employeeid].inital -ne $_.firstname -or
$hrUsers[$_.employeeid].name -ne $_.name -or
$hrUsers[$_.employeeid].dispname -ne $_.displayname
}
I have managed to get it working by changing the search fields
if($user.firstname -eq $_.firstname)
if($user.surname -eq $_.sn)
if($user.ID -eq $_.employeeID)
This now checks AD against the CSV, emails any discrepancies and excludes any emails with the firstname "test" or "careers"
write-host "Using default CSV file or C:\scripts\csv\StaffChanges.csv"
$StaffCSVUPath = "C:\scripts\csv\StaffChanges.csv"
$logfile = "C:\scripts\logs\ADvsHR.csv"
if(test-path $logfile) {
remove-item $logfile -force
}
function Email {
#Send an email, called with recipient email address and message body
param(
[string] $emailaddress="",
[string] $bodymsg=""
)
$bodymsg += "<p>"
$bodymsg += Get-Content($logfile)
Send-MailMessage -To $emailaddress -From "email#domain.co.uk" -Subject "(AD-CMIS_errors) Errors found between Active Directory and CMIS" -Body $bodymsg -BodyAsHTML -SMTPServer "exchserver"
}
function CheckOutputFile {
#Called with folder\filename and type of file
param(
[string]$outputfilename = "",
[string]$type = ""
)
if(test-path($outputfilename)) {
} else {
write-host "Creating $outputfilename"
$msg = "Forename,Surname,Username,ID"
$msg | out-file($outputfilename)
}
}
#Snap-ins needed to use the commands within the script
if((Get-pssnapin -Name Microsoft.Exchange.Management.Powershell.E2010 -ErrorAction SilentlyContinue) -eq $null){Add-PSSnapin Microsoft.Exchange.Management.PowerShell.E2010}
if((Get-pssnapin -Name Quest.activeroles.admanagement -ErrorAction SilentlyContinue)-eq $null){Add-pssnapin Quest.activeroles.admanagement}
#import users from csv file
$users = (import-Csv $StaffCSVUpath)
$count=0
$countAD=0
Get-QADUser -searchroot "domain/Users/Staff" -SizeLimit 0 -includedproperties employeeid,displayname | ForEach-Object ($_.samaccountname) {
$found = 0
$countAD+=1
ForEach ($user in $users) {
$count+=1
if ($user.firstname -eq $_.firstname) {
if ($user.surname -eq $_.sn) {
if ($user.ID -eq $_.employeeID) {
$found = 1
}
}
}
if ($found -eq 1){break}
}
if ($found -eq 0) {
if(($_.firstname -ne "careers") -band ($_.firstname -ne "test")) {
CheckOutputFile $logfile "LOG"
$msg = "<p>" + $_.firstname +" " + $_.lastname + " "+$_.employeeid +"<p>"
$msg | Out-File $logfile -append
}
}
}
if (test-path $logfile) {
#If there is anything to report
write-host "Emailing Log file to ict"
#Email file if $outputB exists
$email = "email#domain.co.uk"
$body = "Action Required: The users below do not exist within HR. Contact HR Data manager to resolve issue, delete users manually if required."
#email ict
Email $email $body
}
i want to create a custom function to simplify the get-messagetrackinglog commandlet.
It's nothing complicated, but simplifies the query a little bit.
The function works correctly, but i want to convert the totalbytes to Kilobyte in the function, if desired.
function Get-ExchangeMessagetrackinglog {
.Synopsys
.Description
.Example
Get-ExchangeMessagetrackinglog -Recipient "user#tld.com" -Sender "sender#tld.com" -Begin "01/04/2014" -Ende "05/05/2014" | select Timestamp,Sender,Recipients,Messagesubject,#{label="Kilobytes";Expression={[int]($_.totalbytes/1kb)} }| ft -auto
param(
[String]$ExchangeConnector = "*",
[String]$Begin=(get-date).AddDays(-120),
[Datetime]$Ende=(get-date -uformat "%m/%d/%y %T"),
[String]$Recipient = "*",
[String]$Sender = "*",
[String]$EventID = "Receive",
[String]$Source = "SMTP"
)
Get-Exchangeserver | `
where { $_.isHubTransportServer -eq $True -or $_.isMailboxServer -eq $True } | `
get-messagetrackinglog -Start $Begin -End $Ende -ResultSize Unlimited | `
where-object { `
$_.recipients -like $Recipient -and `
$_.sender -like $Sender -and `
$_.EventID -eq $EventID -and `
$_.Source -like $Source -and `
$_.connectorID -like $ExchangeConnector}
}
My Question:
Is it possible to simplify the function call (.example) ?
I'm not familiar in creating custom objects, but it is possible to create an totalkilobytes object.
Thanks!
Rather than creating a new PSCustom object my answer amends your and returns a string return ("TotalKB: " + $totalKB) as your final total. I also moved the entire select Timestamp.. block into the body of main function.
function Get-ExchangeMessagetrackinglog {
.Synopsys
.Description
.Example
Get-ExchangeMessagetrackinglog -Recipient "user#tld.com" -Sender "sender#tld.com" -Begin "01/04/2014" -Ende "05/05/2014"
param(
[String]$ExchangeConnector = "*",
[String]$Begin=(get-date).AddDays(-120),
[Datetime]$Ende=(get-date -uformat "%m/%d/%y %T"),
[String]$Recipient = "*",
[String]$Sender = "*",
[String]$EventID = "Receive",
[String]$Source = "SMTP"
)
Get-Exchangeserver | `
where { $_.isHubTransportServer -eq $True -or $_.isMailboxServer -eq $True } | `
$results = get-messagetrackinglog -Start $Begin -End $Ende -ResultSize Unlimited | `
where-object { `
$_.recipients -like $Recipient -and `
$_.sender -like $Sender -and `
$_.EventID -eq $EventID -and `
$_.Source -like $Source -and `
$_.connectorID -like $ExchangeConnector}
$totalKB = 0
foreach($entry in $results) {
$totalKB += $entry.totalbytes
}
$totalKB = $totalKB/1kb
$results | select Timestamp,Sender,Recipients,Messagesubject,#{label="Kilobytes";Expression={[int]($_.totalbytes/1kb)} }| ft -auto
return ("TotalKB: " + $totalKB)
}
Let me know how you get on as it's untested.
What do you think about this?
function Get-ExchangeMessagetrackinglog {
param(
[String]$ExchangeConnector = "*",
[String]$Begin=(get-date).AddDays(-120),
[Datetime]$Ende=(get-date -uformat "%m/%d/%y %T"),
[String]$Recipient = "*",
[String]$Sender = "*",
[String]$EventID = "Receive",
[String]$Source = "SMTP"
)
#Get-Exchangeserver | where { $_.isHubTransportServer -eq $True -or $_.isMailboxServer -eq $True } |
$Return= get-messagetrackinglog -Start $Begin -End $Ende -ResultSize Unlimited | where-object { $_.recipients -like $Recipient -and $_.sender -like $Sender -and $_.EventID -eq $EventID -and $_.Source -like $Source -and $_.connectorID -like $ExchangeConnector}
foreach ($returnvalue in $return) { $Returnvalue | add-member -MemberType Noteproperty -Name TotalKB -Value ([math]::round($returnvalue.totalbytes/ 1kb,2 ))
$Returnvalue | add-member -MemberType Noteproperty -Name TotalMB -Value ([math]::round($returnvalue.totalbytes/ 1MB,2 ))
}
$return
}
Get-ExchangeMessagetrackinglog -Begin "01/05/2014" -Ende "05/05/2014" | select timestamp,totalkb,sender,recipients,messagesubject | sort totalkb | ft -auto