Hey everyone,
I am currently trying to write a script which sends an email, if the uptime of the device you are using is longer than 72h.
Before it sends an E-mail (in Outlook) it should check if Outlook is already running, and if not, create a new instance.
My problem is, it’s trying to create a new instance even Outlook is already running, and then it comes to errors.
I am new to PowerShell scripts, so I really need help here ^^
This is my Code:
# Ändern der Ausführungsrichtlinie auf "Bypass" (sollte eigentlich nicht gebraucht werden)
Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass
# Festlegen der maximalen Betriebszeit in Stunden und Tagen
$maxBetriebszeitInStunden = 0.0001
$maxBetriebszeitInTagen = 14
# Festlegen der geplanten Neustartzeit (z.B., 22:00 Uhr)
$geplanteNeustartzeit = Get-Date -Hour 22 -Minute 0 -Second 0
# Abrufen der aktuellen Betriebszeit des Computers
$betriebszeit = (Get-CimInstance Win32_OperatingSystem).LastBootUpTime
$jetzt = Get-Date
$betriebszeitInStunden = ($jetzt - $betriebszeit).TotalHours
$betriebszeitInTagen = ($jetzt - $betriebszeit).TotalDays
# Überprüfen, ob die Betriebszeit die maximale Dauer überschritten hat (72 Stunden)
if ($betriebszeitInStunden -ge $maxBetriebszeitInStunden) {
# Überprüfen, ob Outlook bereits geöffnet ist
$outlookProcess = Get-Process | Where-Object { $_.ProcessName -eq "OUTLOOK" }
# Überprüfen, ob Outlook bereits geöffnet ist
$outlookProcess = Get-Process -Name Outlook -ErrorAction SilentlyContinue
if ($null -ne $outlookProcess) {
# Outlook ist bereits geöffnet, verwenden Sie die vorhandene Instanz
$outlook = $outlookProcess | Select-Object -First 1
} else {
# Outlook ist nicht geöffnet, eine neue Instanz erstellen
$outlook = New-Object -ComObject Outlook.Application
}
# Erstellen einer neuen E-Mail
$mail = $outlook.CreateItem(0)
# E-Mail-Eigenschaften festlegen
$mail.Subject = "Warnung: Empfohlene Betriebszeit überschritten" -replace "ä", [char]0x00E4 -replace "ö", [char]0x00F6 -replace "ü", [char]0x00FC
$mail.Body = "Die Betriebszeit Ihres Geräts hat 72 Stunden (3 Tage) überschritten. Bitte planen Sie einen Neustart ein.
Nach 14 Tagen Betriebszeit wird das Gerät ohne Vorwarnung neu gestartet.
(Dies ist eine automatisierte Nachricht)"
$mail.To = $outlook.Session.CurrentUser.Address
# Ersetzen Sie die Umlaute durch ihre Unicode-Werte
$mail.Body = $mail.Body -replace "ä", [char]0x00E4
$mail.Body = $mail.Body -replace "ö", [char]0x00F6
$mail.Body = $mail.Body -replace "ü", [char]0x00FC
# E-Mail senden
$mail.Send()
# Outlook schließen, wenn es vor dem Senden der E-Mail nicht geöffnet war
Stop-Process -Name OUTLOOK -Force -ErrorAction SilentlyContinue
}
# Überprüfen, ob die aktuelle Zeit die geplante Neustartzeit ist und der Computer seit mindestens 14 Tagen läuft
if ($jetzt.Hour -eq $geplanteNeustartzeit.Hour -and $jetzt.Minute -eq $geplanteNeustartzeit.Minute -and $betriebszeitInTagen -ge $maxBetriebszeitInTagen) {
# Neustart des Computers ohne Vorwarnung
Restart-Computer -Force
}
(I reduced the maximum number of hours much lower for testing)
$maxBetriebszeitInStunden = 0.0001
It works when Outlook is closed, but I need it to also work when Outlook is running…
You’re right, it would be easier, I’ve already thought about that, but the script should run in the background and not annoy the user, since it runs via (I don’t know if you’re familiar with the software)Riversuite almost once every hour.
And correct me if I’m wrong, but a message box requires the script to run in the foreground, right?
Hmm, okay. When I tried it, with running it in the background, the message box did not appear, maybe it was because of Riversuite… I’ll try that again!
But if it won’t work, E-mail would be a good alternative.
I totally agree, unfortunately, that is not my decision , but that’s what I wanted to suggest anyway xD
if ($null -ne $outlookProcess) {
# Outlook ist bereits geöffnet, verwenden Sie die vorhandene Instanz
$outlook = $outlookProcess | Select-Object -First 1
} else {
# Outlook ist nicht geöffnet, eine neue Instanz erstellen
$outlook = New-Object -ComObject Outlook.Application
}
When Outlook is not running, you’re creating a new COM Object. However, when Outlook is running, all you’re doing is grabbing the first System.Diagnostics.Process object. That’s not the same as the COM object.
You could try grabbing the running instance of Outlook like this:
Can you just send an email to a SMTP relay? I know Send-MailMessage is deprecated, but there are several alternate methods. It just seems like that would be simpler than trying to grab Outlook and send a message from the user to the user…
It might be the wrong discussion - even the requirement to restart the computer every 72 hours is worth discussing - but I’d consider an email an inappropriate channel for this purpose. If the user does not use Outlook for a while the message will not be noticed.
And even if the user uses Outlook depending on the amount of emails coming in the message might still get overlooked.
I’d assume you’re the IT expert in your organisation. So even if you’re not the decision maker it’s your job to consult the decision makers about the disadvantages or possible side effects of their ideas and provide or recommend better solutions.
Why is this even a requirement? I only restart my working machine once or twice a month. And one time is always the monthly patch MSFT day.
I’m just the trainee (Azubi), they gave me the task and my trainer is currently on vacation. But of course I would suggest doing things differently, when he is back. xD
Things like Memory Cleanup, Installing Updates, Resource Release, Troubleshooting, Long-term Stability
I would guess that makes sense?
# Check if the operating time has exceeded the maximum duration (72 hours)
if ($betriebszeitInStunden -ge $maxBetriebszeitInStunden)
{
# Log-In informationen for the SMTP-Server
$smtpUsername = "YourSMTPusername"
$smtpPassword = "YourSMTPpassword"
# E-Mail Configuration
$smtpServer = "smtp.example.com"
$from = "sender@example.com"
$to = "receiver@example.com"
$subject = "Warnung: Betriebszeit überschritten"
$body = "Die Betriebszeit Ihres Geräts hat 72 Stunden überschritten. Bitte planen Sie einen Neustart ein. Nach 14 Tagen Betriebszeit wird das Gerät ohne Vorwarnung neu gestartet."
# Send the email with the specified login information
$securePassword = ConvertTo-SecureString $smtpPassword -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential ($smtpUsername, $securePassword)
Send-MailMessage -SmtpServer $smtpServer -From $from -To $to -Subject $subject -Body $body -Credential $credential -UseSsl
}
For the smtp-server information, I guess I have to wait for my trainer to come back from vacation…
That’s - again - a bad idea. Either the user should have the proper acess rights and it is not necessary to provide credentials or it should be possible to send the email anonymously. In a controlled / managed environment that’s a viable option.
To make your code easier redable you may read about splatting:
With your code, it works in VScode but when I try to run it in the ‘normal’ PowerShell it gives me still the error when Outlook is open…
I also added Add-Type -AssemblyName System.Web.Extensions
to the code, which I found on stackoverflow (no Idea what exactly it does, but it didn’t help xD)
Yeah, you’re right, I kinda gave up with the Outlook version. Probably will try it with Balloon tip messages, but these are kinda weird to me. Sometimes it’s not showing any message…
Or I will go with
If you post error messages you should post them as plain text as well and format them as code as well - NOT AS IMAGES. And since this is an English forum you should even translate them. The least members of this forum speak German.
OK, so you should figure it out: It’s not that hard. You may simply output the automatic variable …
$PSVersionTable
Try to figure out when it shows and when it does not.