Automatisierte Abwesenheitsliste
Hallo zusammen, ich würde gerne automatisiert eine Abwesenheitsliste erstellen (Excel?), die ihre Informationen aus Outlook-Kalendern verschiedener Mitarbeiter bezieht. Es sollen aber nur Termine mit bestimmten Titeln wie z.B. Urlaub oder Tagung ausgelesen bzw. übertragen werden. Dass man Kalender händisch exportieren kann, auch in Excel, weiß ich, aber wie könnte ich dies automatisiert umsetzen? Wäre da Powershell eine Option?, gefunden habe ich aber noch nichts
Danke für eure Hilfe und ein schönes Wochenende
Danke für eure Hilfe und ein schönes Wochenende
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-ID: 2403349841
Url: https://administrator.de/contentid/2403349841
Ausgedruckt am: 22.11.2024 um 11:11 Uhr
4 Kommentare
Neuester Kommentar
Moin, on prem exchange oder online?
https://learn.microsoft.com/en-us/graph/api/resources/outofofficesetting ...
Ist noch in der beta über die Rest api.
Vg
https://learn.microsoft.com/en-us/graph/api/resources/outofofficesetting ...
Ist noch in der beta über die Rest api.
Vg
Servus.
Für Exchange Online (M365) hier die Variante. Ist etwas länger da die App-Impersonation gleich auch einmalig im AzureAD mit angelegt wird, so muss man sie nicht von Hand erstellen.
(Man beachte die benötigten Powershell-Module in der ersten Zeile und die anzupassenden Variablen)
Ergebnis ist dann eine CSV-Datei die so aussieht und die Out Of Office Zeiten für den aktuellen Tag auflistet.
Es werden nur Termine beachtet deren Status auf "Abwesend" gesetzt sind und das angegebenen Regular-Expression Pattern im Kopf des Skripts auf das Subject zutrifft.
Grüße Uwe
Für Exchange Online (M365) hier die Variante. Ist etwas länger da die App-Impersonation gleich auch einmalig im AzureAD mit angelegt wird, so muss man sie nicht von Hand erstellen.
(Man beachte die benötigten Powershell-Module in der ersten Zeile und die anzupassenden Variablen)
#Requires -Modules Microsoft.Graph.Applications,Microsoft.Graph.Identity.DirectoryManagement,Microsoft.Graph.Users,Microsoft.Graph.Users.Actions
<#
Export OUT-OF-OFFICE Information of all users for today as CSV. (M365)
#>
# VARIABLES #################################################
# TENANT FQDN
$TENANT = 'yourdomain.onmicrosoft.com'
# only respect appointments with the following subject regular expression match
$SUBJECTREGEX = 'Tagung|Urlaub|Dienstreise'
# Filepath for CSV-Export
$EXPORTLIST = ".\out-of-office.csv"
# created application impersonation credentials will be saved to and read from this filepath
# (by default it will be saved in the path of the script)
$AUTHCONFIG = "$PSSCRIPTROOT\auth.data"
# #################################################
# SCRIPT INTERNAL VARIABLES (DO NOT CHANGE!) ==
$SCRIPT:CLIENT_ID = ''
$SCRIPT:CLIENT_KEY = ''
# =============================================
$ErrorActionPreference = 'Stop'
# Function to create new M365 azure application credentials for app impersonation
function Create-M365AppImpersonation {
param (
[Parameter(mandatory=$false)]$appname = 'MyGraphUsersCalendarAccess'
)
write-host "Enter your AzureAD Admin-Credentials in the displayed dialogue and approve access to continue ..." -F Yellow
# connect to Microsoft Graph
$connection = Connect-MgGraph -Scopes Application.ReadWrite.All,Directory.ReadWrite.All,RoleManagement.ReadWrite.Directory,AppRoleAssignment.ReadWrite.All
# check if app with name exists
$app = Get-MgApplication -Filter "DisplayName eq '$appname'"
if (!$app){
# add allowed permissions
$resource = New-Object Microsoft.Graph.PowerShell.Models.MicrosoftGraphRequiredResourceAccess -Property @{
ResourceAppId = '00000003-0000-0000-c000-000000000000'
ResourceAccess = (@{Id='df021288-bdef-4463-88db-98f22de89214';Type = 'Role'},@{Id='8ba4a692-bc31-4128-9094-475872af8a53';Type = 'Role'})
}
# add new company application
$newapp = New-MgApplication -DisplayName $appname -RequiredResourceAccess $resource
# assign new password
$pass = Add-MgApplicationPassword -ApplicationId $newapp.Id
# create service principal for app
$sPrincipal = New-MgServicePrincipal -AppId $newApp.AppId -Tags @("WindowsAzureActiveDirectoryIntegratedApp")
# get objectid of service principle
$resApp = Get-MgServicePrincipal -All | ? appId -eq $newApp.RequiredResourceAccess[0].ResourceAppId
# set admin consent approval for access roles
$newApp.RequiredResourceAccess[0].ResourceAccess.id | %{
New-MgServicePrincipalAppRoleAssignment -PrincipalId $sPrincipal.Id -ServicePrincipalId $sPrincipal.Id -ResourceId $resApp.Id -AppRoleId $_ | out-null
}
$data = [pscustomobject]@{
APPNAME = $appname
CLIENT_ID = $newapp.AppId
CLIENT_KEY = $pass.SecretText
VALID_UNTIL=$pass.EndDateTime.toString('o')
}
# export auth data to file
$data | export-csv -Path $AUTHCONFIG -Delimiter ";" -NoTypeInformation -Encoding UTF8
$data
}else{
Write-Error -Message "AppImpersonation with name '$appname' already exists."
return
}
Disconnect-MGGraph | out-null
}
# check if app credentials are available
if (Test-Path $AUTHCONFIG){
# import config from file
$config = Import-CSV $AUTHCONFIG -Delimiter ";"
# check credential expiration
if ((get-date) -gt (get-date $config.VALID_UNTIL).AddDays(-14)){
# warn if app credentials expire in 14 days
Write-Warning -Message "You app credentials will expire in '$(((get-date $config.VALID_UNTIL)-(get-date)).TotalDays)' days! Please generate a new password for your app in Azure!"
}elseif((get-date) -gt (get-date $config.VALID_UNTIL)){
# app credential expired
Write-Error -Message "Your App-Impersonation-Password has expired on '$(get-date $config.VALID_UNTIL)'. Please create a new credential in Azure first, and update the credentials in the config file '$($AUTHCONFIG)'."
exit 1
}
# set credential variables
$SCRIPT:CLIENT_ID = $config.CLIENT_ID
$SCRIPT:CLIENT_KEY = $config.CLIENT_KEY
}else{
write-host "Creating app impersonation in Azure AD ..." -F Green
# create app impersonation in Azure (needs to be created once)
$app = Create-M365AppImpersonation
# set credential variables
$SCRIPT:CLIENT_ID = $app.CLIENT_ID
$SCRIPT:CLIENT_KEY = $app.CLIENT_KEY
}
# try to connect to Graph with App-Credentials
$maxtries = 60;$cnt = 0; $success = $false
do{
try{
# connect to MS Graph
Connect-MgGraph -TenantId $TENANT -ClientSecretCredential (new-Object PSCredential($SCRIPT:CLIENT_ID,(ConvertTo-SecureString $SCRIPT:CLIENT_KEY -AsPlainText -Force))) -NoWelcome
$success = $true
sleep 3
}catch{
write-host "Waiting until the App becomes available within in M365 ..." -F Cyan
sleep 2
$cnt++
if ($nct -ge $maxtries){
write-error -Message "Failed to connect to MS Graph! $($_.Exception.Message)"
exit 1
}
}
}until($success)
# get all users from directory
$users = Get-MGUser -All
# process all users
$result = foreach($user in $users){
$params = @{
Schedules = @($user.mail)
StartTime = @{
DateTime = (get-date).Date.tostring("s")
TimeZone = [System.TimeZoneInfo]::Local.Id
}
EndTime = @{
DateTime = (get-date).Date.AddDays(1).tostring("s")
TimeZone = [System.TimeZoneInfo]::Local.Id
}
AvailabilityViewInterval = 1440
}
$data = Get-MgUserDefaultCalendarSchedule -UserId $user.Id -BodyParameter $params
# filter out out of office schedules
[array]$oofschedule = $data.ScheduleItems | ?{$_.Status -eq 'oof' -and $_.Subject -match $SUBJECTREGEX}
# output custom object with information about out of office and times on the current day
$user | select DisplayName,Mail,@{n='OutOfOffice';e={($oofschedule.Count -gt 0)}},@{n='OOFTimes';e={($oofschedule | %{"$((get-date $_.start.dateTime).ToLocalTime().toString('t'))-$((get-date $_.end.dateTime).ToLocalTime().toString('t'))"}) -join ','}}
}
# finally export data to csv
$result | export-csv -LiteralPath $EXPORTLIST -Delimiter ";" -NoType -Encoding UTF8 -verbose
Ergebnis ist dann eine CSV-Datei die so aussieht und die Out Of Office Zeiten für den aktuellen Tag auflistet.
Es werden nur Termine beachtet deren Status auf "Abwesend" gesetzt sind und das angegebenen Regular-Expression Pattern im Kopf des Skripts auf das Subject zutrifft.
"DisplayName";"Mail";"OutOfOffice";"OOFTimes"
"Max Muster";"maxmuster@domain.onmicrosoft.com";"False";""
"Diana Musterfrau";"dianamusterfrau@domain.onmicrosoft.com";"True";"10:00-14:30,16:00-17:00"