dr.mabuse
Goto Top

Brauche Powershell- oder Programmierexperten für ein Problem

Moin an die Gemeinde,

ich verzweifle face-wink
Ich versuche jetzt seit 2 Wochen ein Problem zu lösen und bekomme es nicht hin und brauche nun Eure Hilfe.

Was liegt an?
Wir als Admins sollen auf einmal die Abwesenheitsmail der User einstellen, wenn diese Krank sind oder einfach zu paddelig face-wink
Unsere Sicherheitsrichtlinien unterbinden dass wir OWA aktivieren "dürfen". Das bedeutet über ECP funktioniert es eben nicht mehr.

Was möchte ich?
Ich möchte KEIN weiteres Produkt für das Problem kaufen.
Ich möchte eine Powershell GUI schreiben, die ich später in eine Exe wandeln kann und dann der Personalabteilung zur Verfügung stelle. Ich muss aber zugeben, dass ich mit Powershell erst vor drei Wochen angefangen habe. Den Script stelle ich gerne hier zur Verfügung. Dieser funktioniert an sich auch schon super. (siehe Code unten)

Jetzt kommt leider mein ABER

Ich komme nicht mit der HTML Umgebung innerhalb der Textbausteine klar die mir vom Exchange überliefert werden. Bisher hatte ich ein RichTextBox-Steuerelemente benutzt und die HTML Zeichen mit einem Replace versehen. Funktioniert aber nicht wirklich gut. Bis hin, dass der gesamte Text beim User gelöscht wird.

Da Powershell meines Wissens nach kein HTML Editor integriert hat, müsste ich über ein HTML Dokument gehen.

Hier wollte ich HtmlAgilityPack.dll mit einem relativen Pfad zum Script nutzen

Mit den Angaben :

# Pfad zur HtmlAgilityPack.dll, relativ zum Skript
$scriptPath = Split-Path -Parent $MyInvocation.MyCommand.Definition
$dllPath = Join-Path -Path $scriptPath -ChildPath "HtmlAgilityPack.dll"  

# Laden der HtmlAgilityPack.dll
Add-Type -Path $dllPath
(...)
$btnShowAutoReply.Add_Click({
    $selectedUserName = $lstUsers.SelectedItem
    $selectedUserObject = $userTable[$selectedUserName]
    if ($selectedUserObject -ne $null) {
        # Erstelle eine Remote-PowerShell-Sitzung mit dem Exchange-Server
        $session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://Exchange-Server/PowerShell/ -Credential $credential
        Import-PSSession $session

        $autoReply = Get-MailboxAutoReplyConfiguration -Identity $selectedUserObject.SamAccountName

        # Laden Sie den HTML-Code in das HtmlDocument-Objekt und extrahieren Sie den Textinhalt
        $htmlDoc.LoadHtml($autoReply.InternalMessage)
        $internalRichTextBox.Text = $htmlDoc.DocumentNode.InnerText

        $htmlDoc.LoadHtml($autoReply.ExternalMessage)
        $externalRichTextBox.Text = $htmlDoc.DocumentNode.InnerText

        # Beende die Remote-PowerShell-Sitzung
        Remove-PSSession $session
    } else {
        [System.Windows.Forms.MessageBox]::Show("Kein Benutzer ausgewählt.")  
    }
})
(...)
Brachte aber kein Erfolg. Es bleibt sogar bei den gleichen Problemen, wie bei der Richtext Variante

Jetzt brauche ich einen oder mehrere gute Ideen wie ich den letzten fehlenden Schritt hinbekomme.
Irgendwie muss es doch möglich sein einen HTML Editor einzubinden oder jegliche andere Idee die zum Erfolg führen kann.

administrator - geschäftlich

Was macht mein Script?
Hier eine Zusammenfassung:
-- Passwortabfrage für einen Exchange Service User
-- Es lädt die .NET-Erweiterungen für die GUI.
-- Es erstellt ein Hauptfenster mit dem Titel “AD-Benutzersuche”.
-- Es fügt ein Textfeld hinzu für die Benutzersuche
-- Es fügt eine ListBox hinzu, in der die gefundenen Benutzer angezeigt werden.
-- Es fügt eine Schaltfläche hinzu, die, wenn sie angeklickt wird, die Benutzer sucht,
die den eingegebenen Buchstaben entsprechen, und sie in der ListBox anzeigt.
-- Es fügt zwei RichTextBox-Steuerelemente hinzu, in denen die internen und externen automatischen Antworten des
ausgewählten Benutzers angezeigt und bearbeitet werden können.
-- Es fügt zwei RadioButtons hinzu, mit denen der AutoReply-Status ausgewählt werden kann.
-- Es fügt eine CheckBox hinzu, mit der das Start- und Enddatum der automatischen Antworten festgelegt werden kann.
-- Es fügt zwei DateTimePicker-Steuerelemente hinzu, in denen das Start- und Enddatum der automatischen Antworten angezeigt und geändert werden kann.
-- Es fügt eine Schaltfläche hinzu, die, wenn sie angeklickt wird, die automatischen Antworten des ausgewählten Benutzers anzeigt.
-- Es fügt eine Schaltfläche hinzu, die, wenn sie angeklickt wird, die Änderungen an den automatischen Antworten speichert.

CODE mit RichTextBox
# Laden der .NET-Erweiterungen für die GUI
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")  
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")  

# Kennwortabfrage für den Nutzer
$securePassword = Read-Host -Prompt "Geben Sie Ihr Passwort ein" -AsSecureString  
$credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList "ServiceUser", $securePassword  

# Hier wird das Hauptfenster definiert
$objForm = New-Object System.Windows.Forms.Form
$objForm.Text = "AD-Benutzersuche"  
$objForm.Size = New-Object System.Drawing.Size(1000, 600)
$objForm.StartPosition = "CenterScreen"  
$objForm.BackColor = "DarkGray"  

# Hier wird ein Textfeld erstellt für die Eingabe von Buchstaben zur Usersuche
$txtSearch = New-Object System.Windows.Forms.TextBox
$txtSearch.Location = New-Object System.Drawing.Point(20, 20)
$txtSearch.Size = New-Object System.Drawing.Size(200, 20)
$txtSearch.Font = New-Object System.Drawing.Font("Arial", 16, [System.Drawing.FontStyle]::Regular)  
$objForm.Controls.Add($txtSearch)

# Hier wird eine ListBox erstellt zur Anzeige der gefundenen User
$lstUsers = New-Object System.Windows.Forms.ListBox
$lstUsers.Location = New-Object System.Drawing.Point(20, 80)
$lstUsers.Size = New-Object System.Drawing.Size(200, 200)
$objForm.Controls.Add($lstUsers)

# Erstellt eine Hashtable zur Speicherung der Benutzerinformationen
$userTable = @{}

# Button zum Suchen (mit exclude für deaktivierte User und ADM. User)
$btnSearch = New-Object System.Windows.Forms.Button
$btnSearch.Location = New-Object System.Drawing.Point(230, 20)
$btnSearch.Size = New-Object System.Drawing.Size(100, 30)
$btnSearch.Text = "Suchen"  
$btnSearch.Add_Click({
    $searchTerm = $txtSearch.Text
    $filter = "Surname -like '$searchTerm*'"  
    $users = Get-ADUser -Filter $filter -Properties GivenName, Surname, EmailAddress, SamAccountName, Enabled
    $lstUsers.Items.Clear()
    foreach ($user in $users) {
        if ($user.Enabled -eq $true -and $user.SamAccountName -notlike "adm.*") {  
            $userName = "$($user.GivenName) $($user.Surname) - $($user.SamAccountName)"  
            $lstUsers.Items.Add($userName)
            $userTable[$userName] = $user
        }
    }
})
$objForm.Controls.Add($btnSearch)
$objForm.AcceptButton = $btnSearch

# Erstelle ein Label für das interne Textfeld
$internalLabel = New-Object System.Windows.Forms.Label
$internalLabel.Location = New-Object System.Drawing.Point(350, 40)
$internalLabel.Size = New-Object System.Drawing.Size(600, 20)
$internalLabel.Text = "Interner Abwesenheitstext"  
$objForm.Controls.Add($internalLabel)

# Erstelle RichTextBox-Steuerelemente zur Anzeige und Bearbeitung der internen und externen automatischen Antworten
$internalRichTextBox = New-Object System.Windows.Forms.RichTextBox
$internalRichTextBox.Location = New-Object System.Drawing.Point(350, 60)
$internalRichTextBox.Size = New-Object System.Drawing.Size(600, 200)
$objForm.Controls.Add($internalRichTextBox)

# Erstelle ein Label für das externe Textfeld
$externalLabel = New-Object System.Windows.Forms.Label
$externalLabel.Location = New-Object System.Drawing.Point(350, 290)
$externalLabel.Size = New-Object System.Drawing.Size(600, 20)
$externalLabel.Text = "Externer Abwesenheitstext"  
$objForm.Controls.Add($externalLabel)

$externalRichTextBox = New-Object System.Windows.Forms.RichTextBox
$externalRichTextBox.Location = New-Object System.Drawing.Point(350, 310)
$externalRichTextBox.Size = New-Object System.Drawing.Size(600, 200)
$objForm.Controls.Add($externalRichTextBox)

# Erstelle RadioButtons zur Auswahl des AutoReply-Status
$rbNoAutoReply = New-Object System.Windows.Forms.RadioButton
$rbNoAutoReply.Location = New-Object System.Drawing.Point(20, 300)
$rbNoAutoReply.Size = New-Object System.Drawing.Size(260, 20)
$rbNoAutoReply.Text = "Keine automatische Antwort senden"  
$objForm.Controls.Add($rbNoAutoReply)

$rbAutoReply = New-Object System.Windows.Forms.RadioButton
$rbAutoReply.Location = New-Object System.Drawing.Point(20, 320)
$rbAutoReply.Size = New-Object System.Drawing.Size(260, 20)
$rbAutoReply.Text = "Automatische Antworten senden"  
$objForm.Controls.Add($rbAutoReply)

# Erstelle eine CheckBox zur Auswahl des Start- und Enddatums der automatischen Antworten
$cbSetDates = New-Object System.Windows.Forms.CheckBox
$cbSetDates.Location = New-Object System.Drawing.Point(20, 360)
$cbSetDates.Size = New-Object System.Drawing.Size(260, 20)
$cbSetDates.Text = "Start- und Enddatum festlegen"  
$objForm.Controls.Add($cbSetDates)

# Erstelle DateTimePicker-Steuerelemente zur Anzeige und Änderung des Start- und Enddatums der automatischen Antworten
$dpStartDate = New-Object System.Windows.Forms.DateTimePicker
$dpStartDate.Location = New-Object System.Drawing.Point(20, 390)
$dpStartDate.Size = New-Object System.Drawing.Size(260, 20)
$objForm.Controls.Add($dpStartDate)

$dpEndDate = New-Object System.Windows.Forms.DateTimePicker
$dpEndDate.Location = New-Object System.Drawing.Point(20, 410)
$dpEndDate.Size = New-Object System.Drawing.Size(260, 20)
$objForm.Controls.Add($dpEndDate)

# Erstelle eine Schaltfläche zum Anzeigen der automatischen Antworten
$btnShowAutoReply = New-Object System.Windows.Forms.Button
$btnShowAutoReply.Location = New-Object System.Drawing.Point(230, 80)
$btnShowAutoReply.Size = New-Object System.Drawing.Size(100, 40)
$btnShowAutoReply.Text = "User auswählen"  
$btnShowAutoReply.Add_Click({
    $selectedUserName = $lstUsers.SelectedItem
    $selectedUserObject = $userTable[$selectedUserName]
    if ($selectedUserObject -ne $null) {
        # Erstelle eine Remote-PowerShell-Sitzung mit dem Exchange-Server
        $session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://Exchange-Server/PowerShell/ -Credential $credential
        Import-PSSession $session

        $autoReply = Get-MailboxAutoReplyConfiguration -Identity $selectedUserObject.SamAccountName
        $internalRichTextBox.Text = [System.Text.RegularExpressions.Regex]::Replace($autoReply.InternalMessage, "<[^>]+?>", "")  
        $externalRichTextBox.Text = [System.Text.RegularExpressions.Regex]::Replace($autoReply.ExternalMessage, "<[^>]+?>", "")  
        $rbNoAutoReply.Checked = $autoReply.AutoReplyState -eq "Disabled"  
        $rbAutoReply.Checked = $autoReply.AutoReplyState -eq "Enabled"  
        $dpStartDate.Value = $autoReply.StartTime
        $dpEndDate.Value = $autoReply.EndTime

        # Beende die Remote-PowerShell-Sitzung
        Remove-PSSession $session
    } else {
        [System.Windows.Forms.MessageBox]::Show("Kein Benutzer ausgewählt.")  
    }
})
$objForm.Controls.Add($btnShowAutoReply)

# Erstelle eine Schaltfläche zum Speichern der Änderungen
$btnSaveChanges = New-Object System.Windows.Forms.Button
$btnSaveChanges.Location = New-Object System.Drawing.Point(20, 480)
$btnSaveChanges.Size = New-Object System.Drawing.Size(100, 30)
$btnSaveChanges.Text = "Speichern"  

$btnSaveChanges.Add_Click({
    $selectedUserName = $lstUsers.SelectedItem
    $selectedUserObject = $userTable[$selectedUserName]
    if ($selectedUserObject -ne $null) {
        # Erstelle eine Remote-PowerShell-Sitzung mit dem Exchange-Server
        $session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://Exchange-Server/PowerShell/ -Credential $credential
        Import-PSSession $session
        
        # Speichere die Änderungen an den automatischen Antworten
        $autoReplyState = if ($rbAutoReply.Checked) { if ($cbSetDates.Checked) { "Scheduled" } else { "Enabled" } } else { "Disabled" }  
        if ($cbSetDates.Checked) {
            $startTime = $dpStartDate.Value
            $endTime = $dpEndDate.Value
            Set-MailboxAutoReplyConfiguration -Identity $selectedUserObject.SamAccountName -InternalMessage $internalRichTextBox.Text -ExternalMessage $externalRichTextBox.Text -AutoReplyState $autoReplyState -StartTime $startTime -EndTime $endTime
        } else {
            Set-MailboxAutoReplyConfiguration -Identity $selectedUserObject.SamAccountName -InternalMessage $internalRichTextBox.Text -ExternalMessage $externalRichTextBox.Text -AutoReplyState $autoReplyState
        }

        # Beende die Remote-PowerShell-Sitzung
        Remove-PSSession $session
    } else {
        [System.Windows.Forms.MessageBox]::Show("Kein Benutzer ausgewählt.")  
    }
})

$objForm.Controls.Add($btnSaveChanges)

# Erstelle einen 'Cancel'-Button  
$btnCancel = New-Object System.Windows.Forms.Button
$btnCancel.Location = New-Object System.Drawing.Point(180, 480)
$btnCancel.Size = New-Object System.Drawing.Size(100, 30)
$btnCancel.Text = "Cancel"  
$btnCancel.Add_Click({
    # Beende alle PowerShell-Sessions
    Get-PSSession | Remove-PSSession
    # Schließe das Fenster
    $objForm.Close()
})
$objForm.Controls.Add($btnCancel)



# Zeige das Hauptfenster an
[void] $objForm.ShowDialog()

Content-Key: 31481143920

Url: https://administrator.de/contentid/31481143920

Printed on: June 16, 2024 at 16:06 o'clock

Member: Boomercringe
Boomercringe May 02, 2024 at 10:05:25 (UTC)
Goto Top
Servus,

ich bin extrem skeptisch, dass es dafür keinen einfacheren Weg gäbe. Das klingt perfekt nach Schwachsinn die sich irgend eine "Führungskraft" ausgedacht hat. Du bist sicher dass der hier beschriebene Weg über ECP nicht funktioniert?

https://4sysops.com/archives/configure-automatic-reply-message-in-exchan ...
Member: Dr.Mabuse
Dr.Mabuse May 02, 2024 updated at 10:59:57 (UTC)
Goto Top
Nicht falsch verstehen, natürlich kann in ich über ECP rein, die Funktion Outlook im Web auf aktivieren, dann im schlimmsten Fall 30 Minuten warten und wie üblich über ECP die Abwesenheit eintragen und danach wieder Outlook im Web deaktivieren.
1) es funktioniert schon über ECP, ist aber umständlich und inzwischen intern verboten OWA anzuschalten.
2) Ich will das als Admin überhaupt nicht machen, das ist Aufgabe der Personalabteilung.
3) Der Datenschutz hat ja schon mit dem Kopf geschüttelt, was da wieder mal intern bei uns los ist face-smile face-smile face-smile

Mag umständlich sein jetzt eine PS zu schreiben, aber das Script kann man später auch noch für andere Dinge nutzen und nur umschreiben.

Für uns als Admin würde es mir nichts ausmachen, wenn der Text voller Html Zeichen ist, das stört uns nicht. Aber das kannst ja keinem User antun, geschweige denn den Usern aus der Personalabteilung, nachher fehlt noch Geld bei deinem Lohn face-wink
$EmailBody = @"  
<html>
<Kopf>
 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">  
</Kopf>
<body style="font-family: Calibri;" >  
Sehr geehrte Damen und Herren,<br/><br/>
Vielen Dank für Ihre Nachricht.<br/><br/>
Ich werde am ttmmjjjj wieder im Büro sein. Ihre E-Mail wird nicht weitergeleitet.<br/><br/>
Bitte kontaktieren Sie xyz@durag.com, wenn es sich um eine dringende Angelegenheit handelt.<br/><br/>
Mit freundlichen Grüßen<br/><br/>
$($\_. Name)
</body></html>
"@  
Member: Boomercringe
Boomercringe May 02, 2024 updated at 11:34:04 (UTC)
Goto Top
https://www.codetwo.com/exchange-rules-pro/how-it-works

Damit solltest du der Personalabteilung einen Zugang einrichten können, der sich nur auf das Setzen von automatischen Antworten beschränkt, und das Problem wäre gelöst

Autoresponder management - another example of a task-oriented, limited-access role. You can use this role, for example, to give your human resources department access to rules with the Auto respond action. This may be useful when an employee is absent for some reason, and an auto reply should be set for this person's account, but you do not want to set it directly on the Exchange server. By assigning your HR people to this role, you enable them to set automatic responses themselves, without bothering you or your IT staff.
Member: Dr.Mabuse
Dr.Mabuse May 02, 2024 at 12:17:09 (UTC)
Goto Top
https://www.codetwo.com/exchange-rules-pro/how-it-works
Damit solltest du der Personalabteilung einen Zugang einrichten können, der sich nur auf das Setzen von automatischen Antworten beschränkt, und das Problem wäre gelöst

Oh... Entschuldige... Ich werde meine Anfrage noch etwas Konkretisieren müssen face-wink
Ich möchte kein weiteres Produkt kaufen.
Ich suche tatsächlich eine Lösung in der Powershell
Member: Delta9
Delta9 May 02, 2024 updated at 12:33:37 (UTC)
Goto Top
Du hast ja neben dem Problem der Formatierung noch das der Berechtigungen.
Unter welchem User soll den die Exe laufen, mit welchen Berechtigungen?

PS. 2 Wochen mit dem Kram beschäftigen ist bestimmt nicht günster als ein Produkt welches das als fertiges, funktionierendes Feature hat... face-smile
Member: Dr.Mabuse
Dr.Mabuse May 02, 2024 at 12:53:05 (UTC)
Goto Top
Du hast ja neben dem Problem der Formatierung noch das der Berechtigungen.
Unter welchem User soll den die Exe laufen, mit welchen Berechtigungen?

Nein, ein Berechtigungsproblem habe ich nicht. das Script bekommt einen ServiceUser mitgeliefert
und der/die User aus dem HR bekommen dass Kennwort dazu. Das Kennwort wird entsprechend im Script abgefragt. Aber *.exe ist ja erst Schritt zwei bzw. drei. Wenn ich das Formatierungsproblem gelöst habe, ist der Rest eher nen Klacks face-wink Bin ja schließlich ohne Programmierkenntnisse auch schon soweit gekommen.

PS. 2 Wochen mit dem Kram beschäftigen ist bestimmt nicht günster als ein Produkt welches das
als fertiges, funktionierendes Feature hat... face-smile

Hmmm... habe mal eben geschaut, Anschaffungskosten für eine Thirdparty so ca. 4000 Euro
Jährliche Service-Kosten , so ca. 750 Euro.

Ich gebe Dir recht, wenn ich noch länger brauchen würde, aber ich mache das nebenbei, wenn das Telefon mal still steht. Also entstehen keine Extrakosten... Außer wenn nen Erbsenzähler vorbei kommt face-wink face-wink
Member: Delta9
Delta9 May 02, 2024 updated at 13:07:34 (UTC)
Goto Top
Zitat von @Dr.Mabuse:

Du hast ja neben dem Problem der Formatierung noch das der Berechtigungen.
Unter welchem User soll den die Exe laufen, mit welchen Berechtigungen?

Nein, ein Berechtigungsproblem habe ich nicht. das Script bekommt einen ServiceUser mitgeliefert
und der/die User aus dem HR bekommen dass Kennwort dazu. Das Kennwort wird entsprechend im Script abgefragt. Aber *.exe ist ja erst Schritt zwei bzw. drei. Wenn ich das Formatierungsproblem gelöst habe, ist der Rest eher nen Klacks face-wink Bin ja schließlich ohne Programmierkenntnisse auch schon soweit gekommen.

Nocheinmal: Doch du hast ein Berechtigungsproblem:

Ein bekannter Serviceuser mit bekanntem Passwort und Berechtigung für Powershell auf einem Exchange, Berechtigungen auf die Postfächer für den User.. Aber Hauptsache ECP / OWA verboten.
Member: Dr.Mabuse
Dr.Mabuse May 02, 2024 at 13:23:12 (UTC)
Goto Top
Ein bekannter Serviceuser mit bekanntem Passwort und Berechtigung für Powershell auf einem Exchange, Berechtigungen auf die Postfächer für den User.. Aber Hauptsache ECP / OWA verboten.

OK... Wenn Du meinst...

Wenn Du jetzt, immerhin scheinst Du ja Ahnung zu haben, anstatt ein weiteres Probleme aufzuwerfen, eine Lösung für mein Formatierungsproblem hast, wäre ich Dir sogar sehr dankbar. Nebenschauplätze zu dem oben genannten Thema sind für mich hier nicht Zielführen und eher OffTopic.

Aber Du kannst gerne ne PM senden, ich lerne gerne noch etwas dazu, dann unterhalten wir uns gerne mal über Admin Tiering, SiSyPHuS Project, gehärtete Pfade und Systeme, über internen und externen Verkehr usw..
Member: Delta9
Delta9 May 02, 2024 at 14:20:56 (UTC)
Goto Top
Meiner Meinung nach sollten die Nebenschauplätze vor einer Umsetzung geklärt werden. Bringt ja nicht viel wenn ~ 4 € pro User Pro Jahr gespart werden und im Gegenzug der Exchange "offen" ist.

Bitte erkläre mir mal wie du die "Exe" absichern und den Zugriff auf die RemotePowershell nur auf die OOO Nachricht eingrenzen willst.

Ganz nebenbei wirfst du damit diese schönen o.g. Schlagworte über den Haufen.
Member: ThePinky777
ThePinky777 May 02, 2024 updated at 15:09:35 (UTC)
Goto Top
also da der Textbaustein immer gleich sein wird oder ?
kannst du den als HTML mit HMTL Zeichen ja Powershell Intern speichern.

Personalabteilung bekommt nur Felder zum ausfüllen wie Name oder Datumsfelder.
und wenn die das gemacht haben, machst einen Replace auf die Variable die den HTML Zeichentext enthält....

Also z.B.

$VaraibleHTMLtext = "Sehr geehrte Damen und Herren und HTML Steuerzeichen wie neue Zeile etc... ich bin bis zum XXXENDDATUMXXX nicht erreichbar....."
Das ganze halt mit HTML Code gespickt, wie du es brauchst also <br> usw...

Nun hat die Personalabteilung z.B. 1-3 Textvarianten zur Auswahl die vielleicht ohne HTML angezeigt werden aber den gleichen Text haben, damit sie sehen was sie einstellen.

Dann frägst du das ENDDATUM ab was die HR ABteilung eintippen musst und machst dann am ende

$VaraibleHTMLtext = $VaraibleHTMLtext.replace('XXXENDDATUMXXX ','$EingabeEndDatumDurchHRvariable')

Dann hast du den Text in der passenden Form
und tust ihn verwenden.

Kannst natürlich X-beliebeige Variablen und Replaces machen wie du es halst brauchst.

Hoffe ist so halbwegs klar was ich meine, bin auch kein ober Powershell Pro aber in vbs script hab ich sowas schon oft so gelöst....

Also bedeutet Vaiablen abfragen von Personal abteilung und diese in einen fertigen Text der entsprechende Platzhalter aufweist replacen und dann hast du den Text für den Abwesenheits assistent, den du nun nur noch einschiessen musst ohne auf die Formatierung zu achten. Weil die Formatierung ist ja im "Rohling" face-smile

ich hab das so weit getrieben das ich die Siganturen in eine SQL Datenbank gespeichert hatte, und ausgelesen habe dann... aber war nur meine eigene... hab in nem trantüten unternehmen gearbeitet wo man 1000 mal erinnerungs emails schreiben musste, hab das mit ner Datenbank gelöst wo die Original Emails drin war und Erinnerungsschreiben das ich noch auf ne Antwort warte als Text und nochmal Signarur unten dran. das auf ne PHP webseite projeziert, und dann konnte ich alle meine themen durch paar mausklicks refreshen (also Emails schicken) und wieder weiter schlafen .... face-smile und in der datenbank wurde gespeichert wann ich das letzte mal ne erinnerung geschickt habe... 1 mal die woche durchklicken und gut...
Member: Dr.Mabuse
Dr.Mabuse May 02, 2024 at 15:19:20 (UTC)
Goto Top
Na das ist doch mal ein Ansatz, werde mich morgen mal dran machen das umzusetzen.
Manchmal sind es einfach die kleinen Dinge im Leben, die ein große Wirkung haben.
Ich finde die Idee gut.
Ich melde mich die Tage wieder um Erfolg oder weitere Nachfragen zu melden face-smile

Erstmal Danke
Member: Boomercringe
Boomercringe May 02, 2024 at 16:32:31 (UTC)
Goto Top
Oh... Entschuldige... Ich werde meine Anfrage noch etwas Konkretisieren müssen
Ich möchte kein weiteres Produkt kaufen.
Ich suche tatsächlich eine Lösung in der Powershell

Oh...mein Fehler. Du bekommst das bestimmt hin! Viel Erfolg!!!
Member: colinardo
Solution colinardo May 03, 2024 updated at 17:13:45 (UTC)
Goto Top
Servus @Dr.Mabuse,
hier ein Beispiel für einen rudimentären HTML Editor mittels WPF den du dir nach Belieben erweitern kannst:

function Edit-HTML {
    param(
        [Parameter(mandatory=$false,ValueFromPipeline=$true)][string]$html = ""  
    )
    begin{
        Add-Type -A Presentationframework
        Add-Type -A System.Windows.Forms
        Add-Type -A System.Drawing
        Add-Type -A Microsoft.VisualBasic
    }
    process{
        [string]$xaml = @"  
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Name="Window" Title="Simple HTML Editor" ResizeMode="CanResizeWithGrip" WindowStartupLocation = "CenterScreen" ShowInTaskbar = "True" Background = "lightgray" Width="700" Height="600">  
    <Grid x:Name="GlobalGrid">  
        <Grid.RowDefinitions>
            <RowDefinition Height="30" />  
            <RowDefinition Height="*" />  
        </Grid.RowDefinitions>
        <ToolBarTray Grid.Row="0" IsLocked="False">  
            <ToolBar x:Name="tBarMain" Band="1" Height="30" BandIndex="1">  
                <ComboBox x:Name="comboFont" Width="120" Margin="0,0,10,0" HorizontalContentAlignment="Left" />  
                <ComboBox x:Name="comboFontSize" Width="40" Margin="0,0,10,0" HorizontalContentAlignment="Center" SelectedIndex="2" />  
                <Button x:Name="btnBold" Content="B" Width="24" Height="24" Margin="0,0,10,0" FontWeight="Bold" />  
                <Button x:Name="btnItalic" Content="I" Width="24" Height="24" Margin="0,0,10,0" FontWeight="Bold" FontStyle="Italic" />  
                <Button x:Name="btnUnderline" Content="U" Width="24" Height="24" Margin="0,0,10,0" FontWeight="Bold" />  
                <Button x:Name="btnFontColor" Width="24" Height="24" Margin="0,0,10,0" ToolTip="Show HTML-Code">  
                    <Image x:Name="imgFontColor"/>  
                </Button>
                <Button x:Name="btnBackColor" Width="30" Margin="0,0,10,0">  
                    <Image x:Name="imgBackColor" />  
                </Button>
                <Button x:Name="btnLink" Width="24" Height="24" Margin="0,0,10,0">  
                    <Image x:Name="imgLink" />  
                </Button>
                <Button x:Name="btnImage" Width="24" Height="24" Margin="0,0,10,0">  
                    <Image x:Name="imgImage" />  
                </Button>
                <Button x:Name="btnOL" Width="24" Height="24" Margin="0,0,10,0">  
                    <Image x:Name="imgOL" />  
                </Button>
                <Button x:Name="btnUL" Width="24" Height="24" Margin="0,0,10,0">  
                    <Image x:Name="imgUL" />  
                </Button>
            </ToolBar>
            <ToolBar x:Name="tBarFinal" Band="1" BandIndex="2">  
                <Button x:Name="btnGetHtml" Width="24" Height="24" Margin="0,0,10,0">  
                    <Image x:Name="imgGetHtml" />  
                </Button>
                <Button x:Name="btnFinished" Content="Finished" Width="100" Margin="0,0,10,0" BorderThickness="1" BorderBrush="Gray" />  
            </ToolBar>
        </ToolBarTray>
        <WebBrowser x:Name="webBrowser" Source="about:blank" Margin="10" Grid.Row="2"/>  
    </Grid>
</Window>
"@  
        # Markup laden 
        $window = [Windows.Markup.XamlReader]::Parse($xaml)

        # Web-Browser Control referenzieren
        $browser = $window.FindName('webBrowser')  

        # Font selection
        $comboFont = $window.FindName('comboFont')  
        [System.Drawing.FontFamily]::Families.Name | %{[void]$comboFont.Items.Add($_)}
        $comboFont.add_DropDownClosed({
            if($this.SelectedIndex -ne -1){
                $doc.execCommand("FontName",$false,$this.SelectedItem.toString())  
            }
        })

        # Fontsize Dropdown
        $comboFontSize = $window.FindName('comboFontSize')  
        1..7 | %{[void]$comboFontSize.Items.Add($_)}
        $comboFontSize.add_DropDownClosed({
            $doc.execCommand("FontSize",$false,$this.SelectedItem)  
        })

        # Button für das Fettschrift
        $btnBold = $window.FindName('btnBold')  
        $btnBold.add_Click({
            $doc.execCommand("Bold",$false,0)  
        })

        # Button für das Unterstreichen
        $btnUnderline = $window.FindName('btnUnderline')  
        $btnUnderline.add_Click({
            $doc.execCommand("Underline",$false,0)  
        })

        # Button für Kursivschrift
        $btnItalic = $window.FindName('btnItalic')  
        $btnItalic.add_Click({
            $doc.execCommand("Italic",$false,0)  
        })

        # Button für HTML Link
        $btnLink = $window.FindName('btnLink')  
        $imgLink = $window.FindName('imgLink')  
        $bi = New-Object System.Windows.Media.Imaging.BitmapImage
        $bi.BeginInit()
        $bi.StreamSource = New-Object System.IO.MemoryStream (,[Convert]::FromBase64String('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'))  
        $bi.EndInit()
        $imgLink.Source = $bi
        $btnLink.add_Click({
            $url = [Microsoft.VisualBasic.Interaction]::InputBox("Enter the URL for the selected Text:","Insert Link")  
            $range = $doc.selection.createRange()
            $range.pasteHTML("<a href=`"$url`" target=_blank>$($range.htmlText)</a>")  
        })

        # Button für Bild
        $btnImage = $window.FindName('btnImage')  
        $imgImage = $window.FindName('imgImage')  
        $bi = New-Object System.Windows.Media.Imaging.BitmapImage
        $bi.BeginInit()
        $bi.StreamSource = New-Object System.IO.MemoryStream (,[Convert]::FromBase64String('iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAABQElEQVQ4jaWRMUsDQRCFv71dy3SCpY12ItqIhdqkEuQId8TKSvSwTiPWVvoDRIOVNuLCFYII/gYFwdLGQoiQwtLmbsZmAzEmJpoHW8wM75s3LIwpA5AkybmqLvzJaMxTnuc7DkBVq0DLGPM8illVV4IH10W8Lsvy0Vq7BdzkeX47CJAkyYmqrgNE3YMoii5VNVPVqyzLJkZJ43rqFjBtjGk3m80CII7jirX22DnX8N5/9gK+JXDOxcAmsAZo6B0Be2VZ7g9N4L1vA75T12q1JVXNAFS1Ua/XT73377+dQJqmiyJyAbwB84ANo0pRFIfA7kBAHMczInIPTAJzfRJvp2l6pqr9Adbag7Dxo9+9ACKyaoz5CVDVDeABaA4yB02JyHIH0p2gGt5QBfMr9Hzjf+QC8U5EZv9ijKLoZdzlAHwBaI1wTy3fbNYAAAAASUVORK5CYII='))  
        $bi.EndInit()
        $imgImage.Source = $bi
        $btnImage.add_Click({
            $range = $doc.selection.createRange()
            if([System.Windows.Forms.MessageBox]::Show("Do you want to embed the image as Base64?","Embed as Base64",4,32) -eq 'Yes'){  
                $dlg = New-Object System.Windows.Forms.OpenFileDialog -P @{Multiselect = $false}
                $dlg.Filter = "Bilder|*.png"  
                if($dlg.ShowDialog() -eq 'OK'){  
                    $src = "data:image/png;base64,$([Convert]::ToBase64String([io.File]::ReadAllBytes($dlg.FileName)))"  
                }
            }else{
                $src = [Microsoft.VisualBasic.Interaction]::InputBox("Enter the URL for the image","Insert image")  
            }
            $range.pasteHTML("<img src=`"$src`" />")  
        })

        # Button um geordnete Liste einzufügen
        $btnOL = $window.FindName('btnOL')  
        $imgOL = $window.FindName('imgOL')  
        $bi = New-Object System.Windows.Media.Imaging.BitmapImage
        $bi.BeginInit()
        $bi.StreamSource = New-Object System.IO.MemoryStream (,[Convert]::FromBase64String('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'))  
        $bi.EndInit()
        $imgOL.Source = $bi
        $btnOL.add_Click({
            $doc.execCommand("InsertOrderedList",$false,0)  
        })

        # Button um ungeordnete Liste einzufügen
        $btnUL = $window.FindName('btnUL')  
        $imgUL = $window.FindName('imgUL')  
        $bi = New-Object System.Windows.Media.Imaging.BitmapImage
        $bi.BeginInit()
        $bi.StreamSource = New-Object System.IO.MemoryStream (,[Convert]::FromBase64String('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'))  
        $bi.EndInit()
        $imgUL.Source = $bi
        $btnUL.add_Click({
            $doc.execCommand("InsertUnorderedList",$false,0)  
        })

        # Button um das HTML abzufragen
        $btnGetHtml = $window.FindName('btnGetHtml')  
        $imgGetHtml = $window.FindName('imgGetHtml')  
        $bi = New-Object System.Windows.Media.Imaging.BitmapImage
        $bi.BeginInit()
        $bi.StreamSource = New-Object System.IO.MemoryStream (,[Convert]::FromBase64String('iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABWUlEQVRYw2NgGAUDDSZMmBAIxC8nTZr0n1g8ceLEXGo6AGS5GbHqoY54AcTeVHEAyEBS1U+ePNkIRPf39xsMiANANDAa/IGh97y3t1d6QBwAdUQRkH9uypQpPAPigP///zMCQ2EG0CGbV61axUwvB7wAWmgB48+cOZMVyN8FFJ9EFweA4h6aCzCyJ10cQHVzBpUDgMHLDuRPASasD6SUjGTgjyB7QPahOAAquB7oAHEaF//iQHs2AvFkFAeAfE5ry5EdAbIPPQT+44pTGB9X6ocW0Q4gNohGFscb/aQ6AB8fiA9A2QcGzAHAeG2gmgPwFTTY+LCgH7AowJVmRh2AKyqxOeDjtGnTxOhRDgDbEBJA+95jKwk30rIwArUh+vr6JEFtCCCegFEXgIpHOtQF70GW19fXs41Wx+B+AbB5bU6J5cDgtAK1ksjV7E9qzwgLBrUTfUf7meQAAJititk2lfZEAAAAAElFTkSuQmCC'))  
        $bi.EndInit()
        $imgGetHtml.Source = $bi
        $btnGetHtml.add_Click({
            [System.Windows.Forms.MessageBox]::Show($doc.body.innerHTML,"HTML-Source")  
        })


        # Button für die Textfarbe
        $btnFontColor = $window.FindName('btnFontColor')  
        $imgFontColor = $window.FindName('imgFontColor')  
        $bi = New-Object System.Windows.Media.Imaging.BitmapImage
        $bi.BeginInit()
        $bi.StreamSource = New-Object System.IO.MemoryStream (,[Convert]::FromBase64String('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'))  
        $bi.EndInit()
        $imgFontColor.Source = $bi

        $btnFontColor.add_Click({
            $cDialog = New-Object System.Windows.Forms.ColorDialog -P @{AllowFullOpen = $true;FullOpen = $true}
            if($cDialog.ShowDialog() -eq 'OK'){  
                $doc.execCommand("ForeColor",$false,("#{0:X2}{1:X2}{2:X2}" -f ($cDialog.Color.R,$cDialog.Color.G,$cDialog.Color.B)))  
            }
        })

        # Button für die Hintergrundfarbe
        $btnBackColor = $window.FindName('btnBackColor')  
        $imgBackColor = $window.FindName('imgBackColor')  
        $bi = New-Object System.Windows.Media.Imaging.BitmapImage
        $bi.BeginInit()
        $bi.StreamSource = New-Object System.IO.MemoryStream (,[Convert]::FromBase64String('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'))  
        $bi.EndInit()
        $imgBackColor.Source = $bi

        $btnBackColor.add_Click({
            $cDialog = New-Object System.Windows.Forms.ColorDialog -P @{AllowFullOpen = $true;FullOpen = $true}
            if($cDialog.ShowDialog() -eq 'OK'){  
                $doc.execCommand("BackColor",$false,("#{0:X2}{1:X2}{2:X2}" -f ($cDialog.Color.R,$cDialog.Color.G,$cDialog.Color.B)))  
            }
        })

        # Button für Kursivschrift
        $btnFinished = $window.FindName('btnFinished')  
        $btnFinished.add_Click({
            $window.Close()
        })

        # HTMLDocument des Browsers abfragen
        $doc = $browser.Document

        # HTML Dokument schreiben
        $doc.IHTMLDocument2_write($html)

        # Dokument in den Edit-Modus versetzen
        $doc.designMode = 'On'  
        $browser.Refresh()

        # WPF ausführen 
        [void]$window.Dispatcher.InvokeAsync({[void]$window.ShowDialog()}).Wait()
        # return html
        return $doc.body.innerHTML
    }
}


$html = @'  
<body>
    <style>
        body {font-family: sans-serif;}
    </style>
    Donec <strong>commodo</strong> eget felis sed vehicula. Suspendisse pretium ultrices quam in iaculis. Aliquam a vulputate nisl. Etiam quam nunc, dictum ac nulla vel, posuere hendrerit metus. Quisque ante lacus, adipiscing id elit vel, ornare consectetur nisi. Etiam pretium, sapien vitae lobortis tempor, nibh justo cursus orci, non dapibus magna sapien quis enim. Phasellus rutrum elit justo, id pellentesque magna tempus dapibus. Etiam sed augue eros. Cras nec varius eros. Aenean sodales tincidunt dolor. Nunc ac metus tristique, porttitor justo eu, luctus diam. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Ut egestas libero quis velit volutpat, at scelerisque mauris porttitor.
</body>
'@  

Edit-Html -html $html

screenshot

Grüße Uwe
Member: Dr.Mabuse
Dr.Mabuse May 07, 2024 at 05:48:21 (UTC)
Goto Top
Zitat von @colinardo:

Servus @Dr.Mabuse,
hier ein Beispiel für einen rudimentären HTML Editor mittels WPF den du dir nach Belieben erweitern kannst:

Moin Uwe,
vielen Dank für den Code. Da ich, wie schon geschrieben, kein Programmierer bin und erst seit drei, vier Wochen mich mit dem Thema beschäftige, musste ich erstmal rausfinden, was das für ein Code ist, bevor ich den bei mir teste face-wink Nach genauerer Untersuchung habe ich den nun übernommen und werde mal versuchen, den Code für mich bzw. für meine Zwecke umzubauen. Da es doch sehr viel Code für ein bzw. zwei "Textfelder" ist, muss ich mal schauen ob ich es in ein Modul verpacke.

Also anders ausgedrückt, bitte an alle und an Uwe, ich brauche ein wenig Zeit um das umzubauen face-smile
Aber es sieht nach meiner gesuchten Lösung aus.

Erstmal Danke face-wink
Member: Dr.Mabuse
Dr.Mabuse May 08, 2024 at 09:10:23 (UTC)
Goto Top
Moin zusammen und vielen Dank an alle, aber ich gebe mein Projekt auf.

Für ein nicht Programmierer wie mich, stoße ich jetzt doch an meine Grenzen. "Leider"
Mit der Powershell komme ich nach den paar Wochen zwar gut klar , aber wenn es um weitere Programmierung (in diesem Fall C#) geht, um das zu erreichen was ich benötige ist für mich hier Schluss.

Die beiden hier genannten Ansätze sind schon nicht schlecht, aber dann doch für mich nicht umsetzbar.
Powershell ist da dann doch an dieser Stelle nicht flexibel genug.
Ich verstehe nicht wie MS die Powershell "pushen" möchte, wenn sie selber dann Funktionen nutzen, die die PS nicht abdeckt. Es wäre doch für MS ein leichtes über Forms ein Html-Editor statt der Richtextbox einzublenden. Naja, egal.

Hier eben meine Erkenntnisse::
-- In PowerShell ist es nicht direkt möglich, einen HTML-Editor in ein Windows.Forms-Fenster einzubetten.
-- Nur über HTML ist eine Abwesenheitsnotiz „sauber“ anzuzeigen und auch wieder an den Exchange zurückzugeben.
-- Die System.Windows.Forms.WebBrowser-Klasse, die in PowerShell verfügbar ist, unterstützt das Editieren von HTML-Inhalten nicht direkt

Und der von Uwe zur Verfügung gestellte Editor ist "nice" - nochmals danke dafür, den werde ich sicher hier und dort noch einsetzen wollen - aber der Aufwand darin Schalter und Knöpfe und, und und... zu integrieren, übersteigt mein Zeitkontigent und auch mein Programmierwissen.

Also werden wir Admins wohl erstmal die Änderungen der Abwesenheitsmail weiter über den oben genannten Umweg durchführen müssen. Schade eigentlich face-wink
Member: colinardo
colinardo May 08, 2024 updated at 09:35:33 (UTC)
Goto Top
Powershell ist da dann doch an dieser Stelle nicht flexibel genug.
Für einen Anfänger mag das so scheinen, ist aber definitiv nicht der Fall, kann ich aus jahrelanger Erfahrung mit der PowerShell berichten 🙂. Mit dem .NET Framework steht dir ein Fundus an Funktionen bereits die in der Windows Welt eigentlich unübertroffen ist sofern man Bordmittel nutzen möchte.

Ich hatte dir den Editor extra als Funktion bereitgestellt der du das HTML der Abwesenheitsbenachrichtigung als Parameter übergeben kannst, du hättest also nur die zwei Edit-Felder aus deiner Form durch zwei Buttons ersetzen müssen die meine Funktion mit dem HTML-Code als Parameter aufgerufen hätten. Der Rückgabewert der Funktion lieferte ja immer den geänderten HTML-Code zurück welchen du dann wieder in deiner Form hättest zurückschreiben können.
Dazu braucht man also auch kein extra Modul anlegen, beides kann im selben Skript problemlos koexistieren
Ich hatte dir hier extra keinen Fix und Fertig geliefert da ich dir den Spaß mit der PowerShell nicht nehmen wollte, denn nur durch eigene Erfahrung sammelt man Wissen das auch nachhaltig in Erinnerung bleibt. Copy n' Paste bringt einen da nicht viel weiter.

Naja, die Erfahrung kommt halt nicht über Nacht, etwas Durchhaltevermögen ist hier wie bei jeder Programmiersprache immer angebracht 😉. Dafür das du dich erst so kurz damit beschäftigt war das Ergebnis doch absolut i.O..

Hier eben meine Erkenntnisse::
-- In PowerShell ist es nicht direkt möglich, einen HTML-Editor in ein Windows.Forms-Fenster einzubetten.
Nativ gibt es kein Control, unmöglich ist es aber nicht wenn man sie ein eigenes entwickelt oder das eines Drittanbieters nutzt.

-- Die System.Windows.Forms.WebBrowser-Klasse, die in PowerShell verfügbar ist, unterstützt das Editieren von HTML-Inhalten nicht direkt
Richtig, die WPF Variante von oben jedoch schon.

Ansonsten weiterhin alles Gute und schönen Feiertag.

Bitte den Beitrag dann noch als gelöst markieren, Merci.

Grüße Uwe
Member: Dr.Mabuse
Solution Dr.Mabuse May 21, 2024 updated at 10:43:07 (UTC)
Goto Top
Nur noch zur Information. Ich habe jetzt tatsächlich einen fertigen Skript geschrieben.
Zwei Punkte allerdings gibt es, die ich in der Anforderung geändert habe.
  • Das Skript (bzw. die *.exe) ist nur für die Admins, da es zu unsicher wäre den PC des Users (nicht dem User) entsprechende Rechte zu geben
  • Es war ein Fehler zu denken, dass die Abwesenheitsmail "Bilder einbetten" kann. Das habe ich zu spät gelesen, dass das von MS nicht unterstützt wird.

Ich habe es dann doch noch mit Windows-Board-Mitteln hinbekommen eine bzw. zwei HTML Box zu schaffen, die die Daten Richtig anzeigt und auch richtig wieder zurück schreibt. Alles andere waren dann nur noch Probleme mit der Fokussierung der Entertaste und die Anzeige eines Fortschrittsbalken, da der Sessionaufbau zum Exchange schon mal ein paar Sekunden dauert.

Meine Kollegen sind jedenfalls total Glücklich über den Skript und nutzen den Skript schon täglich. Somit hat sich der Aufwand tatsächlich gelohnt.

Wer Interesse daran hat, darf mir gerne eine PM schreiben face-wink