Search code examples
windowspowershellpinvoke

How do I PInvoke SHQueryUserNotificationState for use in Powershell?


Add-Type -TypeDefinition @"
using System;
using System.Runtime.InteropServices;
public enum QUERY_USER_NOTIFICATION_STATE {
        QUNS_NOT_PRESENT = 1,
        QUNS_BUSY = 2,
        QUNS_RUNNING_D3D_FULL_SCREEN = 3,
        QUNS_PRESENTATION_MODE = 4,
        QUNS_ACCEPTS_NOTIFICATIONS = 5,
        QUNS_QUIET_TIME = 6
    };
public class UserWindows {
    [DllImport("shell32.dll")]
    public static extern int SHQueryUserNotificationState(out QUERY_USER_NOTIFICATION_STATE pquns);
}
"@;

$state = [UserWindows]::QUERY_USER_NOTIFICATION_STATE
[UserWindows]::SHQueryUserNotificationState([ref]$state)

I've tried a few different ways, just can't seem to get it working completely right. This is the exception I'm getting now.

Exception calling "SHQueryUserNotificationState" with "1" argument(s): "Cannot 
convert null to type "QUERY_USER_NOTIFICATION_STATE" due to enumeration values that 
are not valid. Specify one of the following enumeration values and try again. The 
possible enumeration values are "QUNS_NOT_PRESENT,QUNS_BUSY,QUNS_RUNNING_D3D_FULL_SCRE
EN,QUNS_PRESENTATION_MODE,QUNS_ACCEPTS_NOTIFICATIONS,QUNS_QUIET_TIME"."
At D:\pintest.ps1:20 char:1
+ [UserWindows]::SHQueryUserNotificationState([ref]$state)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : PSInvalidCastException

I'm having trouble figuring out how to pass the enum reference to SHQueryUserNotificationState so that it will point to a specific member of QUERY_USER_NOTIFICATION_STATE

For reference - https://learn.microsoft.com/en-us/windows/win32/api/shellapi/nf-shellapi-shqueryusernotificationstate


Solution

  • The P/Invoke definition is correct.

    Call it like this:

    $state = [QUERY_USER_NOTIFICATION_STATE]::QUNS_NOT_PRESENT
    $hresult = [UserWindows]::SHQueryUserNotificationState([ref]$state)
    if( $hresult -ge 0 ) {
        # HRESULT >= 0 indicates success
        "User notification state: $state"
    }
    else {
        # HRESULT < 0 indicates failure
        "Could not query user notification state (HRESULT: $hresult)"
    }
    

    Possible output:

    User notification state: QUNS_ACCEPTS_NOTIFICATIONS