Shutdown the PC if the monitor is turned off or not connected (VGA / HDMI) within a period of time. #VB.NET RRS feed

  • Question

  • Hi there, I am developing a tool which can detect the PowerState  of a monitor via VB.NET. I want to shutdown a PC if the monitor is off or not connected within  5mins. Please Help Me. Thank You

    Friday, November 17, 2017 5:12 PM

All replies

  • You can handle WM_POWERBROADCAST to detect when the monitor is on/off (then you start a 5mn timer and shutdown)

    (RegisterPowerSettingNotification() with GUID_MONITOR_POWER_ON at first)

    Declarations :

    <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Unicode)>
        Public PowerSetting As Guid
        Public DataLength As Integer
        <MarshalAs(UnmanagedType.ByValArray, SizeConst:=1)>
        Public Data As Byte()
    End Structure
    Public Const WM_POWERBROADCAST As Integer = &H218
    Public Const PBT_POWERSETTINGCHANGE As Integer = &H8013
    Public Const DEVICE_NOTIFY_WINDOW_HANDLE As Integer = &H0
    Public Const DEVICE_NOTIFY_SERVICE_HANDLE As Integer = &H1
    Dim GUID_MONITOR_POWER_ON As New Guid("02731015-4510-4526-99E6-E5A17EBD1AEA")
        Public Shared Function RegisterPowerSettingNotification(hRecipient As IntPtr, ByRef PowerSettingGuid As Guid, Flags As Integer) As IntPtr
        End Function

    Friday, November 17, 2017 6:13 PM
  •  As Castorix31 has suggested,  you can use the RegisterDeviceNotification function to register your application to receive the WM_POWERBROADCAST message in it's WndProc whenever the monitor's power state changes.  However,  instead of using the GUID_MONITOR_POWER_ON in the example below,  i used the GUID_CONSOLE_DISPLAY_STATE as is suggested to use for newer applications in the Power Setting GUIDs document.  You should also use the UnregisterDeviceNotification function when you no longer need to receive the notifications.

     Now... just so you are aware,  most newer computers use a "Power Plan" which can be located in (Start Menu \ Control Panel \ Power Options).  You can click on the (Change Plan Settings) and change the settings.  The Power Plan Settings have an option to specify a time before the the display is Dimmed,  another for when the display power is turned off,  and another for when it should enter the sleep mode.  If you have the setting for turning off the display set so that it will shut off the monitor after X minutes,  this will trigger the notification and start the 5 minute countdown.

     You can try this in a new form project,  no controls needed.  I am on a laptop at the moment so,  i am not sure if it was working when the monitor's power button was turned on/off but,  it was working fine when the Power Plan Setting turned the monitor power off.

    Imports System.Runtime.InteropServices
    Public Class Form1
        Private hEvent As IntPtr = IntPtr.Zero
        Private PowerOffTime As Date
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            Timer1.Interval = 5000
            hEvent = RegisterPowerSettingNotification(Me.Handle, GUID_CONSOLE_DISPLAY_STATE, DEVICE_NOTIFY_WINDOW_HANDLE)
        End Sub
        Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles Me.FormClosing
        End Sub
        Protected Overrides Sub WndProc(ByRef m As Message)
            If m.Msg = WM_POWERBROADCAST AndAlso m.WParam.ToInt32 = PBT_POWERSETTINGCHANGE Then
                'pbs.Data(0) will be 0-2 meaning --> (0 = Monitor Turned Off) (1 = Monitor Turned On) (2 = Monitor Entered 'Dimmed' State)
                If pbs.Data(0) = 0 Then PowerOffTime = Now
                Timer1.Enabled = (pbs.Data(0) = 0) 'enable timer if monitor is turned off | disable timer if monitor is turned on
            End If
        End Sub
        Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
            Dim ts As TimeSpan = Now - PowerOffTime
            If ts.TotalMinutes >= 5.0 Then 'if it has been 5 minutes...
                'Monitor Power Has Been Off For 5 Minutes, start shutdown...
            End If
        End Sub
    #Region "Native Methods"
        Private Structure POWERBROADCAST_SETTING
            Public PowerSetting As Guid
            Public DataLength As Integer
            <MarshalAs(UnmanagedType.ByValArray, SizeConst:=1)> Public Data As Byte()
        End Structure
        Private Const WM_POWERBROADCAST As Integer = &H218
        Private Const PBT_POWERSETTINGCHANGE As Integer = &H8013
        Private Const DEVICE_NOTIFY_WINDOW_HANDLE As Integer = &H0
        Private GUID_CONSOLE_DISPLAY_STATE As New Guid("6fe69556-704a-47a0-8f24-c28d936fda47") 'See -->
        Private Shared Function RegisterPowerSettingNotification(hRecipient As IntPtr, ByRef NotificationFilter As Guid, Flags As Integer) As IntPtr
        End Function
        Private Shared Function UnregisterPowerSettingNotification(ByVal Handle As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean
        End Function
    #End Region
    End Class

    If you say it can`t be done then i`ll try it

    • Edited by IronRazerz Saturday, November 18, 2017 3:17 AM
    Saturday, November 18, 2017 3:09 AM
  • sir your compile code 100% work for monitor display off, but in function change monitor state bring event for monitor power off is not working. I want to know want source work for her becouse that source help me bussnes to autoshutdown my pc's if my costumer will not use after timer period is zero..
    • Edited by Niel Mar Thursday, January 24, 2019 5:39 AM
    Thursday, January 24, 2019 5:31 AM