Sending Emails and checking if Outlook is already running

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…

Konstantin,
Welcome to the forum. :wave:t3:

Just out of curiousity - you’re trying to send an email to the user currently logged on to the computer, right?

Wouldn’t be way easier to show a balloon tip or a message box notifying the user that a reboot is recommended?

That’s right. :slightly_smiling_face:

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. :grimacing:

And correct me if I’m wrong, but a message box requires the script to run in the foreground, right?

I agree.

I disagree … at least if the computer runs longer than desired. :wink:

But actually that’s not mutually exclusive. The script can run in the background but the ballon tipp or the message box should appear on the desktop.

Does it really have to be once every hour? I’d expect it to be enough once or twice a day. :man_shrugging:t3:

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 :joy: , but that’s what I wanted to suggest anyway xD

This code is the problem:

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:

$outlook = [Runtime.Interopservices.Marshal]::GetActiveObject('Outlook.Application')
1 Like

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. :man_shrugging:t3:

And even if the user uses Outlook depending on the amount of emails coming in the message might still get overlooked.

Unfortunately it didn’t work, but thanks anyway :slight_smile:

Hmm, I will try that but I am still a noob in PowerShell, so it will take me some time to write the script :smiley:

Unfortunately, some things are not my decision, although I can see the point behind restarting after 3 days.

Every user here uses Outlook and always starts it first thing in the morning, that’s not the problem xD

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? :thinking: I only restart my working machine once or twice a month. And one time is always the monthly patch MSFT day. :man_shrugging:t3:

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? :joy: :man_shrugging:

This discussion does not belong here. But I’d doubt that a restart every 72 hours has this much of effect you (they) think it does.

Would the code look something like this? :thinking:

# 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… :man_shrugging:

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:

I’m - again - just the trainee and still new to PowerShell Scripts. :joy:

Okay thanks, I will check it out. :saluting_face:

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)

Does somebody know why it works in VScode??

Do you get an error when you run it in the “‘normal’ PowerShell”?

Could be your VSCode is set to run in Windows PowerShell 5.1 and you’re running PowerShell in your terminal?

As mentioned, there are better ways to do this.

Yes, it somehow isn’t able to get the running instance of Outlook

Tbh I don’t even know xD, I am new to all this.

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

Send-MailMessage -SmtpServer $smtpServer -From $from -To $to -Subject $subject -Body $body -Credential $credential -UseSsl

But if I do it like that I have to read a little more into the topic I guess.

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. :wink:

OK, so you should figure it out: It’s not that hard. :wink: You may simply output the automatic variable …

$PSVersionTable

Try to figure out when it shows and when it does not.

That’s always a great idea and very recommended. :wink: