Jump to content

Recommended Posts

Posted

Hello everyone,

While exploring different ways to create a lightweight and flexible notification system, I realized that the IUserNotification interface is one of the least resource-hungry, especially if you're looking to implement a discreet and low-impact reminder system.

I'm sharing here a small demonstration of this approach.

The code below displays a customizable system notification with a title, message, icon, and optional system sound.
It’s flexible and dynamic, and can easily be adapted for uses like reminders, subtle alerts, and more.

🔧 It uses:

  • the COM object IUserNotification

  • system icons extracted from shell32.dll

  • a custom interface via AutoItObject

📌 This is just another way to do it — not necessarily better, but a useful option if you want to avoid heavy UDFs or external libraries for a simple need.

 

#AutoIt3Wrapper_AU3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6
#include "AutoItObject.au3"
#include <WinAPIIcons.au3>
#include <WinAPIShellEx.au3>

; Initialization
_AutoItObject_Startup()

#cs
; Constants for SetBalloonInfo
Global Const $NIIF_NONE = 0x00000000
Global Const $NIIF_INFO = 0x00000001
Global Const $NIIF_WARNING = 0x00000002
Global Const $NIIF_ERROR = 0x00000003
Global Const $NIIF_USER = 0x00000004
Global Const $NIIF_NOSOUND = 0x00000010
Global Const $NIIF_RESPECT_QUIET_TIME = 0x00000080
#ce

; COM structure and interfaces
Global Const $tagIUserNotification = _
        "QueryInterface long(ptr;ptr*);" & _
        "AddRef ulong();" & _
        "Release ulong();" & _
        "SetBalloonInfo long(wstr;wstr;dword);" & _
        "SetBalloonRetry long(dword;dword;uint);" & _
        "SetIconInfo long(ptr;wstr);" & _
        "Show long(ptr;dword);" & _
        "PlaySound long(wstr);"

; Function to create and display the notification
Func CreateSystemNotification($sTitle, $sMessage, $iTimeout = 2000, $iIconIndex = Default, $sSound = "")
    Local $hIcon = 0, $pUserNotif = 0, $oNotif = 0
    ; Create COM instance
    Local $CLSID_IUserNotification = _AutoItObject_CLSIDFromString("{0010890E-8789-413C-ADBC-48F5B511B3AF}")
    Local $IID_IUserNotification = _AutoItObject_CLSIDFromString("{BA9711BA-5893-4787-A7E1-41277151550B}")
    _AutoItObject_CoCreateInstance(DllStructGetPtr($CLSID_IUserNotification), 0, 1, DllStructGetPtr($IID_IUserNotification), $pUserNotif)
    If Not $pUserNotif Then
        ConsoleWrite("Error: Failed to create COM instance." & @CRLF)
        Return False
    EndIf

    ; Create wrapper object
    $oNotif = _AutoItObject_WrapperCreate($pUserNotif, $tagIUserNotification)
    If Not IsObj($oNotif) Then
        ConsoleWrite("Error: Failed to create wrapper object." & @CRLF)
        Return False
    EndIf

    ; Load icon
    Local $dwFlags = $NIIF_USER
    Local $iTotal = _WinAPI_ExtractIconEx(@SystemDir & '\shell32.dll', -1, 0, 0, 0)

    If $iIconIndex = Default Or Not IsInt($iIconIndex) Or $iIconIndex < 0 Or $iIconIndex >= $iTotal Then
        $iIconIndex = 13 ; Default icon
        ;ConsoleWrite("Warning: Invalid icon index. Using default icon (index 64)." & @CRLF)
    EndIf

    $hIcon = _WinAPI_ShellExtractIcon(@SystemDir & '\shell32.dll', $iIconIndex, 32, 32)
    If Not $hIcon Then
        ConsoleWrite("Error: Failed to load icon. Switching to NIIF_NONE." & @CRLF)
        $dwFlags = $NIIF_NONE
    EndIf

    ; Configure notification
    If $sSound <> "" Then
        $oNotif.PlaySound($sSound)
    EndIf
    $oNotif.SetBalloonInfo($sTitle, $sMessage, BitOR($NIIF_RESPECT_QUIET_TIME, $dwFlags))
    $oNotif.SetBalloonRetry(0, 0, 0) ; No retries
    $oNotif.SetIconInfo($hIcon, $sTitle)
    $oNotif.Show(0, $iTimeout)

    ; Resource cleanup
    If $hIcon Then _WinAPI_DestroyIcon($hIcon)
    If IsObj($oNotif) Then $oNotif.Release()
    $oNotif = 0
    $pUserNotif = 0
    Return True
EndFunc   ;==>CreateSystemNotification

; Example usage
If CreateSystemNotification("Notification Title", "This is an AutoIt message", 2000, Default, "") Then
    ConsoleWrite("Notification displayed successfully." & @CRLF)
Else
    ConsoleWrite("Failed to display notification." & @CRLF)
EndIf

 

Posted

You can create the object simply with :

Local $CLSID_IUserNotification = "{0010890E-8789-413C-ADBC-48F5B511B3AF}"
    Local $IID_IUserNotification = "{BA9711BA-5893-4787-A7E1-41277151550B}"
    Local $oNotif = ObjCreateInterface($CLSID_IUserNotification, $IID_IUserNotification, $tagIUserNotification)

Or you can even simpler use :

_WinAPI_ShellNotifyIcon

 

Posted
3 hours ago, argumentum said:

Tested and with $NIIF_RESPECT_QUIET_TIME didn't even stay on. Then tried $NIIF_INFO and that, it did like, but no show of anything but the selected icon, and would only go away after clicking the icon. On x64 it'd crash.

Hi @argumentum . Thanks for your feedback. Regarding the constants $NIIF_NONE, $NIIF_INFO, $NIIF_WARNING, and $NIIF_ERROR, I chose to comment them out in this example because they correspond to Windows' predefined system icons. This function focuses on custom icons extracted from shell32.dll (system 🙃), selected by the user, hence the exclusive use of $NIIF_USER to handle icon handles. For $NIIF_RESPECT_QUIET_TIME, you’ll need to configure the object beforehand using the method $oNotif.SetBalloonRetry(3000, 0, 0) to set the retry parameters. This is a simple example, designed to be flexible and adaptable, so feel free to modify it to add other icon sources, reactivate the constants for different notification types, or adjust the retry settings as needed.

 

Posted
1 hour ago, Nine said:

Or you can even simpler use :

_WinAPI_ShellNotifyIcon

 

Hi @NineI’ve been thinking about this function, and while it’s pretty good, I find it too limited because it requires extra coding to handle a callback. Fortunately, the interface provides a method that does the job: $oNotif.SetBalloonRetry(2000, 3000, 2). As a bonus, I can even add some nice music to enhance the experience!

Posted

I just downloaded your script and AutoItObject 1.2.8.2. I'm running Autoit 3.3.16.1 on Windows 11.
When running your script I get the following error:

Quote

TEST Notification.au3" (44) : ==> Can pass constants by reference only to parameters with "Const" keyword.:
$oNotif = _AutoItObject_WrapperCreate($pUserNotif, $tagIUserNotification)
$oNotif = _AutoItObject_WrapperCreate($pUserNotif, ^ ERROR

Did I miss something?

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2024-07-28 - Version 1.6.3.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts
OutlookEX (2021-11-16 - Version 1.7.0.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX_GUI (2021-04-13 - Version 1.4.0.0) - Download
Outlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - Wiki
PowerPoint (2021-08-31 - Version 1.5.0.0) - Download - General Help & Support - Example Scripts - Wiki
Task Scheduler (2022-07-28 - Version 1.6.0.1) - Download - General Help & Support - Wiki

Standard UDFs:
Excel - Example Scripts - Wiki
Word - Wiki

Tutorials:
ADO - Wiki
WebDriver - Wiki

 

Posted
On 6/14/2025 at 8:44 PM, water said:

I just downloaded your script and AutoItObject 1.2.8.2. I'm running Autoit 3.3.16.1 on Windows 11.
When running your script I get the following error:

Did I miss something?

Hey, could you try this code and let me know if it works for you? Here's the optimized version. Thanks!"
 
#AutoIt3Wrapper_AU3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6
#include <WinAPIIcons.au3>
#include <WinAPIShellEx.au3>

; Constants for SetBalloonInfo
;Global Const $NIIF_NONE = 0x00000000, $NIIF_USER = 0x00000004, $NIIF_NOSOUND = 0x00000010, $NIIF_RESPECT_QUIET_TIME = 0x00000080

; Function to create and display the notification
Func CreateSystemNotification($sTitle, $sMessage, $iTimeout = 2000, $iIconIndex = 13, $sSound = "")
    Local $hIcon = 0, $oNotif = 0, $bSuccess = False
    Local Const $sCLSID_IUserNotification = "{0010890E-8789-413C-ADBC-48F5B511B3AF}"
    Local Const $sIID_IUserNotification = "{BA9711BA-5893-4787-A7E1-41277151550B}"
    Local Const $tagIUserNotification = "SetBalloonInfo long(wstr;wstr;dword);" & _
            "SetBalloonRetry long(dword;dword;uint);" & _
            "SetIconInfo long(ptr;wstr);" & _
            "Show long(ptr;dword);" & _
            "PlaySound long(wstr);"

    ; Create COM instance
    $oNotif = ObjCreateInterface($sCLSID_IUserNotification, $sIID_IUserNotification, $tagIUserNotification)
    If Not IsObj($oNotif) Then
        ConsoleWrite("Error: Failed to create COM object." & @CRLF)
        Return False
    EndIf

    ; Load icon
    Local $dwFlags = $NIIF_USER
    If Not IsInt($iIconIndex) Or $iIconIndex < 0 Then
        $iIconIndex = 13 ; Default icon
    Else
        Local $iTotal = _WinAPI_ExtractIconEx(@SystemDir & '\shell32.dll', -1, 0, 0, 0)
        If $iIconIndex >= $iTotal Then
            $iIconIndex = 13 ; Fallback to default if index is out of range
        EndIf
    EndIf

    $hIcon = _WinAPI_ShellExtractIcon(@SystemDir & '\shell32.dll', $iIconIndex, 32, 32)
    If Not $hIcon Then
        ConsoleWrite("Error: Failed to load icon. Switching to NIIF_NONE." & @CRLF)
        $dwFlags = $NIIF_NONE
    EndIf

    ; Configure notification
    If $sSound Then $oNotif.PlaySound($sSound)
    $oNotif.SetBalloonInfo($sTitle, $sMessage, BitOR($NIIF_RESPECT_QUIET_TIME, $dwFlags))
    $oNotif.SetBalloonRetry(0, 0, 0)
    $oNotif.SetIconInfo($hIcon, $sTitle)
    $oNotif.Show(0, $iTimeout)

    $bSuccess = True ; Mark success if we reach this point

    ; Cleanup
    If $hIcon Then _WinAPI_DestroyIcon($hIcon)
    $oNotif = 0 ; AutoIt handles COM cleanup automatically

    Return $bSuccess
EndFunc   ;==>CreateSystemNotification

; Example usage
If CreateSystemNotification("Notification Title", "This is an AutoIt message", 2000) Then
    ConsoleWrite("Notification displayed successfully." & @CRLF)
Else
    ConsoleWrite("Failed to display notification." & @CRLF)
EndIf

 

Posted
On 6/14/2025 at 8:44 PM, water said:

Did I miss something?

It is highly likely that you have an issue with the AutoItObject UDF. However, without tests, I cannot say more. You can redownload the UDF (not the compiled version) and try again.

Posted (edited)
Local $hIcon = 0, $oNotif = 0, $bSuccess = False, $hTimer = TimerInit()
... ...
    If Not IsObj($oNotif) Then
        ConsoleWrite("Error: Failed to create COM object." & @CRLF)
        Return SetError(2, Int(TimerDiff($hTimer)), False)
    EndIf
... ...
Return SetError(Int(Not $bSuccess), Int(TimerDiff($hTimer)), $bSuccess)

..so that when DoNotDisturb is ON, get a feedback of sorts ? ( due to the short time it took to return )

Now, if the Notification board/thingy is open it'll show forever
image.png.0a60615ae742be8db8c79c879df68e8c.png

but if is not then this:
image.png.c2906b5262142112a382e6233a0b8310.png

for a few seconds, but will not show in the above board, even if I leave the script running ( in a while loop ).
Is that a user setting or something that can be coded ?

Edit: ..remembered something about this and .. here is my answer ( untested by me yet ) https://www.autoitscript.com/forum/topic/211659-autoit-notifications-do-not-stay-in-windows-11-notification-centre/#findComment-1531865

 

Edited by argumentum

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

Posted
4 hours ago, Numeric1 said:

Hey, could you try this code and let me know if it works for you? Here's the optimized version. Thanks!"

Your modified version works like a champ! No re-download of the AutoItObject UDF was necessary. Thanks!

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2024-07-28 - Version 1.6.3.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts
OutlookEX (2021-11-16 - Version 1.7.0.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX_GUI (2021-04-13 - Version 1.4.0.0) - Download
Outlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - Wiki
PowerPoint (2021-08-31 - Version 1.5.0.0) - Download - General Help & Support - Example Scripts - Wiki
Task Scheduler (2022-07-28 - Version 1.6.0.1) - Download - General Help & Support - Wiki

Standard UDFs:
Excel - Example Scripts - Wiki
Word - Wiki

Tutorials:
ADO - Wiki
WebDriver - Wiki

 

Posted
1 hour ago, argumentum said:

for a few seconds, but will not show in the above board, even if I leave the script running ( in a while loop ).
Is that a user setting or something that can be coded ?

Starting with Win11, for toast notifications to persist indefinitely, it requires the program to be registered AppX and I think that even requires digital signature.

Even after all that, user can have notifications disabled which renders it pointless. This is why I ended up going with custom notifications for my apps.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...