How to show Windows 10 notification toast from VBA
Asked Answered
A

2

7

I'd like to know the easiest way to show notification toast in windows 10 from VBA.

I didn't found a good answer to this. I found a really simple way to create notifications from PowerShell here. But I can't get it to work from VBA because I didn't find a way to execute this in one line using WScript.Shell.

I tried several ways to accomplish that but i didn't succeed. Below you can find my last attempt:

Public Sub Notify_Test()

Dim WsShell     As Object: Set WsShell = CreateObject("WScript.Shell")
Dim strCommand  As String

strCommand = """powershell.exe"" ^ "
strCommand = strCommand & "[reflection.assembly]::loadwithpartialname(""System.Windows.Forms"")"
strCommand = strCommand & "; [reflection.assembly]::loadwithpartialname(""System.Drawing"")"
strCommand = strCommand & "; $notify = new-object system.windows.forms.notifyicon"
strCommand = strCommand & "; $notify.icon = [System.Drawing.SystemIcons]::Information"
strCommand = strCommand & "; $notify.visible = $true"
strCommand = strCommand & "; $notify.showballoontip(10,""New Chat!"",""You have received New Chat!"",[system.windows.forms.tooltipicon]::None)"

WsShell.Run strCommand

End Sub

I'd like to avoid writing a .ps1 file. Can someone please help me with this question?

Thank you in advance!

UPDATE:

Thanks to @Remko I was able to display the notification.

I did a function to make its use simpler:

Public Function Notify(ByVal title As String, ByVal msg As String, _
                    Optional ByVal notification_icon As String = "Info", _
                    Optional ByVal app As String = "excel", _
                    Optional ByVal duration As Integer = 10)
                    
'Parameters:
'    title (str):Notification title
'    msg (str):Notification message
'    notification_icon (str):Notification icon. Available options are: Info, Error and Warning
'    app (str):Process name of app you want to be display in the system tray icon
'    duration (int):Duration of notification in seconds

Const PSpath    As String = "powershell.exe"

Dim WsShell     As Object: Set WsShell = CreateObject("WScript.Shell")
Dim strCommand  As String

If notification_icon <> "Info" And notification_icon <> "Error" And notification_icon <> "Warning" Then
    notification_icon = "Info"
End If

strCommand = """" & PSpath & """ -Command " & Chr(34) & "& { "
strCommand = strCommand & "Add-Type -AssemblyName 'System.Windows.Forms'"
strCommand = strCommand & "; $notification = New-Object System.Windows.Forms.NotifyIcon"
strCommand = strCommand & "; $path = (Get-Process -id (get-process " & app & ").id).Path"
strCommand = strCommand & "; $notification.Icon = [System.Drawing.Icon]::ExtractAssociatedIcon($path)"
strCommand = strCommand & "; $notification.BalloonTipIcon  = [System.Windows.Forms.ToolTipIcon]::" & notification_icon & ""
strCommand = strCommand & "; $notification.BalloonTipText = '" & msg & "'"
strCommand = strCommand & "; $notification.BalloonTipTitle = '" & title & "'"
strCommand = strCommand & "; $notification.Visible = $true"
strCommand = strCommand & "; $notification.ShowBalloonTip(" & duration & ")"
strCommand = strCommand & " }" & Chr(34)

WsShell.Run strCommand, 0, False

End Function

Public Sub Notify_Examples()

Notify "Insert Title Here", "Insert Your Message Here"
Notify "Insert Title Here", "Insert Your Message Here", "Warning"
Notify "Insert Title Here", "Insert Your Message Here", "Error", "outlook"

End Sub

I'd like to make and extra observation. Nothing happens when leave the PSpath = "powershell.exe". I guess this is due to the fact my user is not an admin. I was able to bypass this by copying the powershell.exe to my documents and altering the PSpath to "C:\Users\my_user\Documents\powershell.exe". Maybe this is the case for you too...

Anhwei answered 11/5, 2021 at 18:53 Comment(1)
Visual Basic NotifyIcon for Taskbar NotificationDazzle
A
2

If you insist doing this with PowerShell the following code works:

Public Sub Notify_Test()

Dim WsShell     As Object: Set WsShell = CreateObject("WScript.Shell")
Dim strCommand  As String

strCommand = "powershell.exe -Command " & Chr(34) & "& { "
strCommand = strCommand & "[reflection.assembly]::loadwithpartialname('System.Windows.Forms')"
strCommand = strCommand & "; [reflection.assembly]::loadwithpartialname('System.Drawing')"
strCommand = strCommand & "; $notify = new-object system.windows.forms.notifyicon"
strCommand = strCommand & "; $notify.icon = [System.Drawing.SystemIcons]::Information"
strCommand = strCommand & "; $notify.visible = $true"
strCommand = strCommand & "; $notify.showballoontip(10,'New Chat!','You have received New Chat!',[system.windows.forms.tooltipicon]::None)"
strCommand = strCommand & " }" & Chr(34)
WsShell.Run strCommand

End Sub

It will of course briefly flash a console (powershell) window

Ascendant answered 11/5, 2021 at 21:4 Comment(3)
Thank you @Ascendant ! It worked. I don't insist in doing this with PowerShell, i just figure out it would be simpler like this. And if you know a better way to do this I actually would like to knowAnhwei
Note that in my case replacing WsShell.run with Shell strCommand, vbHide saved me of the annoying powershell window flashing on the screen.Claptrap
Also curious for a more VBA centric solution!Ambulatory
A
0

Based on @remko's answers I also added the ability to launch a command/URL when clicking the notification:

Public Sub showBalloonTipVBA(ByVal title As String, ByVal msg As String, ByVal click_url As String, ByVal duration_in_seconds As Integer)

    Dim WsShell     As Object: Set WsShell = CreateObject("WScript.Shell")
    Dim strCommand  As String
    
    strCommand = "powershell.exe -Command " & Chr(34) & "& { "
    strCommand = strCommand & "[reflection.assembly]::loadwithpartialname('System.Windows.Forms')"
    strCommand = strCommand & "; [reflection.assembly]::loadwithpartialname('System.Drawing')"
    strCommand = strCommand & "; $notify = new-object system.windows.forms.notifyicon"
    strCommand = strCommand & "; $notify.icon = [System.Drawing.SystemIcons]::Information"
    strCommand = strCommand & "; $notify.visible = $true"
    strCommand = strCommand & "; register-objectevent $notify BalloonTipClicked BalloonClicked_event -Action {cmd /c Start `\""`\"" `\""" & click_url & "`\""} | Out-Null"
    strCommand = strCommand & "; try { $notify.showballoontip(" & Str(duration_in_seconds) & "000,'" & title & "','" & msg & "',[system.windows.forms.tooltipicon]::None)"
    strCommand = strCommand & "; wait-event -timeout " & Str(duration_in_seconds) & " -sourceIdentifier BalloonClicked_event > $null } finally { $notify.Dispose() } "
    strCommand = strCommand & " }" & Chr(34)
    
    ' Debug.Print strCommand
    
    WsShell.Run strCommand, 0 ' Run without command line window

End Sub
Ambulatory answered 21/1 at 17:1 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.