Automating the outlook scheduling assistant to find the perfect meeting day

Hi fellow experts.
**I have just now received a response in my german admin forum which looks just right. Will share it after testing**
Imagine the following scenario: I want to invite half the company (about 40 persons) to a meeting some day in october and I am trying to find the perfect day=the day when most people are available. I only know, it should be from 11-12 AM. Short of testing every day in outlook's scheduling assistant, is there maybe a powershell command for the exchange management shell, that I can run that will retrieve the day that has the lowest number of conflicts?
LVL 62
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

JohnBusiness Consultant (Owner)Commented:
Use a Doodle poll. Made for this
McKnifeAuthor Commented:
Right, but that is not within the scope of the question. We are not talking about alternatives to outlook but about a scripted way to use what is already there.
JohnBusiness Consultant (Owner)Commented:
Understand, but given the situation and description, it seemed an alternative was a reasonable approach.
Has Powershell sent you back into the Stone Age?

If managing Active Directory using Windows Powershell® is making you feel like you stepped back in time, you are not alone.  For nearly 20 years, AD admins around the world have used one tool for day-to-day AD management: Hyena. Discover why.

McKnifeAuthor Commented:
Not really. If I wanted to know this today, how would I make people use doodle "now"? Don't forget that many people are not even in the office, today (and might be on vacation). Our guys rely on their calendar heavily, so it's reasonable to stay within outlook/Exchange.
McKnifeAuthor Commented:
Thank you Amit, but for reasons given before, I need something that works right away, without having to wait for users to use it.
Alex GreenProject Systems EngineerCommented:

That work for you MK?

You need o365 for it though as a prerequisite, if not then give me a minute and I'll check again. Full breakdown of what it does there.

McKnifeAuthor Commented:
Alex, thanks, but findtime is not suitable and was suggested before.
Alex GreenProject Systems EngineerCommented:
The other users don't need to use findtime, just you :-)

I missed that one btw, but essentially just you need it
McKnifeAuthor Commented:
Please read my previous response as to why it is not suitable. It is not applicable anyway as we don't have O365, but Office 2016 Standard/ProPlus.
McKnifeAuthor Commented:
I have just now received a response in my german admin forum which looks just right. Will share it after testing.
Alex GreenProject Systems EngineerCommented:

Utilizing powershell I don't think is going to happen unfortunately, the main reason for this is the calendar commands available within powershell for exchange don't take the actual meetings into consideration. I mean you could make it run on all their machines to pull down dates.... But yeah, this is quite an interesting one.

Give me a bit and I'll see if I can't find something.
McKnifeAuthor Commented:
# FQDN of the Exchange Server
$EXCHANGESERVER = 'ex.domain.tld'
# Array of meeting attendants
$users = 'someuser@domain.tld','anotheruser@domain.tld'
# Begin of Meeting
$starttime = [datetime]'11:00:00'
# duration of Meeting in minutes
$duration = 60
# check how many days in advance
$daysinadvance = 30

if ($PSVersionTable.PSVersion.Major -lt 3){write-host "ERROR: Minimum Powershell Version 3.0 is required!" -F Yellow; return}

# Funktion zum Verbinden mit dem Exchange EWS Dienst
function ConnectTo-EWS {
        [parameter(mandatory=$false)][bool]$UseScriptCredentials = $true,
        [parameter(mandatory=$false)][ValidateScript({Test-Path $_})][string]$ewsdll = "$psscriptroot\Microsoft.Exchange.WebServices.dll",
        [parameter(mandatory=$false)][string]$mailbox = $null,

    # Allen Zertifikaten vertrauen
        Add-Type '
            using System.Net;
            using System.Security.Cryptography.X509Certificates;
            public class TrustAllCertsPolicy : ICertificatePolicy {
                public bool CheckValidationResult(
                    ServicePoint srvPoint, X509Certificate certificate,
                    WebRequest request, int certificateProblem) {
                    return true;
        # Trust all certs policy dem ServicePointManager zuweisen
        [System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy

    # EWS DLL laden
    Add-Type -Path $ewsdll

    # EWS-Service Objekt erstellen
    $ews = new-object Microsoft.Exchange.WebServices.Data.ExchangeService([Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2010)
    $ews.Url = "https://$server/ews/exchange.asmx"
    $ews.UseDefaultCredentials = $UseScriptCredentials
    if (!$UseScriptCredentials){
        $ews.Credentials = $Credential.GetNetworkCredential()
        $ews.ImpersonatedUserId = New-Object Microsoft.Exchange.WebServices.Data.ImpersonatedUserId([Microsoft.Exchange.WebServices.Data.ConnectingIdType]::SmtpAddress, $mailbox)
    return $ews

# Mit Service verbinden
$svc = ConnectTo-EWS -Server $EXCHANGESERVER
# collection für Teilnehmer erstellen
[Microsoft.Exchange.WebServices.Data.AttendeeInfo[]]$attendees = new-object "System.Collections.Generic.List[Microsoft.Exchange.WebServices.Data.AttendeeInfo]"
# Teilnehmer der Collection hinzufügen
$users | %{
    $a = new-object Microsoft.Exchange.WebServices.Data.AttendeeInfo
    $a.SmtpAddress = $_
    $a.AttendeeType = [Microsoft.Exchange.WebServices.Data.MeetingAttendeeType]::Required
    $attendees += $a
# Availability Options festlegen
[Microsoft.Exchange.WebServices.Data.AvailabilityOptions]$options = New-Object Microsoft.Exchange.WebServices.Data.AvailabilityOptions
$options.GoodSuggestionThreshold = 49
$options.MaximumNonWorkHoursSuggestionsPerDay = 0
$options.MaximumSuggestionsPerDay = 24
$options.MeetingDuration = $duration
$options.MinimumSuggestionQuality = [Microsoft.Exchange.WebServices.Data.SuggestionQuality]::Good
$options.DetailedSuggestionsWindow = New-Object Microsoft.Exchange.WebServices.Data.TimeWindow((get-date),(get-date).AddDays($daysinadvance))
$options.CurrentMeetingTime = $starttime
$options.RequestedFreeBusyView = [Microsoft.Exchange.WebServices.Data.FreeBusyViewType]::FreeBusy

# FreeBusy mit den Optionen abfragen
$result = $svc.GetUserAvailability($attendees,$options.DetailedSuggestionsWindow,[Microsoft.Exchange.WebServices.Data.AvailabilityData]::FreeBusyAndSuggestions,$options)
# Vorschläge ausfiltern
$suggestions = $result.Suggestions.TimeSuggestions | ?{($_.Quality -eq 'Excellent' -or (($_.Conflicts.FreeBusyStatus | ?{$_ -eq 'Free'}).Count -ge $users.Count-1)) -and $_.MeetingTime.toString('HHmm') -eq $starttime.toString('HHmm') -and $_.MeetingTime.DayOfWeek -in 1..5}  | sort MeetingTime | select MeetingTime,@{n='Conflicts';e={($_.Conflicts.FreeBusyStatus | ?{$_ -ne 'Free'}).Count}}
# und darstellen
$suggestions | ft -AutoSize

Open in new window

That is the solution. It requires the Microsoft.Exchange.WebServices.dll from (don't install it on your server as it destroys its performance - you just need the dll).

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
AmitIT ArchitectCommented:
Thanks for sharing the solution.
McKnifeAuthor Commented:
Welcome. To clarify it even more: the dll just needs to be in the same folder as this powershell script.
The script takes the days monday to friday into account, not weekends. I have not translated all script comments - if you need to, its german.
Senior IT System EngineerIT ProfessionalCommented:
thanks for sharing, is this for Exchange Server 2013 or can be executed against Exchange Online (Office 365) ?
McKnifeAuthor Commented:
As far as I know and understand, it can be used on on-premises Exchange 2013 and Exchange 2016. No experience with O365. You can try it, it will not hurt.
Senior IT System EngineerIT ProfessionalCommented:
Cool, many thanks for the clarification McKnife.
McKnifeAuthor Commented:
And I should have given credit to who really deserves it. A true grandmaster at scripting.
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today

From novice to tech pro — start learning today.