DeviceIDPnP v2 - Automatically launch actions when devices are connected or disconnected.

Post your working scripts, libraries and tools.
XMCQCX
Posts: 245
Joined: 14 Oct 2020, 23:44

DeviceIDPnP v2 - Automatically launch actions when devices are connected or disconnected.

02 Mar 2023, 16:28

I've updated DeviceIDPnP to support groups of devices and added new options. Try it out if you are interested!

New
  • Updated to AutoHotkey v2.
  • Added support for groups of devices.
  • Option to launch or not launch the device's actions when the script starts.
  • Option to show or hide tooltips in the top left corner.
For the latest version of this script and the instruction, head over to the GitHub page.
:arrow: Download on GitHub

DeviceIDFinder

Code: Select all

/*
Script:    DeviceIDFinder.ahk
Author:    XMCQCX
Date:      2023-03-01
Version:   2.0.0
Github:    https://github.com/XMCQCX/DeviceIDPnP
AHK forum: https://www.autohotkey.com/boards/viewtopic.php?f=83&t=114610

Credits: jNizM
This is a modified version of his script.
Example 2: Detect / Monitor Plug and Play device connections and removes
https://www.autohotkey.com/boards/viewtopic.php?f=83&t=105171
*/

#Requires AutoHotkey v2.0
#SingleInstance Force

;=============================================================================================

Main := Gui("+Resize +MinSize500x300", "DeviceIDFinder")
Main.SetFont("s10")
Main.Add("Text", "xm-5", "Connect or disconnect your devices to view their IDs. Use the right-click context menu to copy selected items.")
LV := Main.AddListView("w865 h490 r10 +BackgroundDEDEDE Grid", ["Event", "Time", "Device Name", "Device ID"])
for k, v in ["95", "70", "230", "465"]
	LV.ModifyCol(k, v)

LV.OnEvent("ContextMenu", ShowContextMenu)
Main.OnEvent("Size", GuiSize)
Main.OnEvent("Close", GuiClose)
Main.Show()

;=============================================================================================

WMI := ComObjGet("winmgmts:")
ComObjConnect(Sink := ComObject("WbemScripting.SWbemSink"), "SINK_")
command := "WITHIN 1 WHERE TargetInstance ISA 'Win32_PnPEntity'"
WMI.ExecNotificationQueryAsync(Sink, "SELECT * FROM __InstanceCreationEvent " . command)
WMI.ExecNotificationQueryAsync(Sink, "SELECT * FROM __InstanceDeletionEvent " . command)

;=============================================================================================

SINK_OnObjectReady(Obj, *)
{
	TI := Obj.TargetInstance
	Time := FormatTime(A_Now, "HH:mm:ss")
	switch Obj.Path_.Class
	{
		case "__InstanceCreationEvent": EventType := "Connected"
		case "__InstanceDeletionEvent": EventType := "Disconnected"
	}
	LV.Insert(1,, EventType, Time, TI.Name, TI.DeviceID)
}

;=============================================================================================

ShowContextMenu(LV, Item, IsRightClick, X, Y)
{
    MouseGetPos(,,, &mouseOverClassNN)
    if (Item = 0 || InStr(mouseOverClassNN, "SysHeader"))
        Return

    ContextMenu := Menu()
    ContextMenu.Add("Copy Selected Item", CopyToClipboard)
    ContextMenu.Add("Clear Listview", ClearListview)
    ContextMenu.Show(X, Y)

    CopyToClipboard(*)
    {
        rowNumber := 0
        Loop
        {
            rowNumber := LV.GetNext(rowNumber)
            if not rowNumber
                break
            deviceName := LV.GetText(rowNumber, 3)
            deviceID := LV.GetText(rowNumber, 4)
            strDev .= deviceName ": " deviceID "`n"
        }
        strDev := RTrim(strDev, "`n")
        A_Clipboard := ""
        A_Clipboard := strDev
        if !ClipWait(1)
            return
    }

    ClearListview(*) => LV.Delete()
}

;=============================================================================================

GuiSize(thisGui, MinMax, Width, Height)
{
	if (MinMax = -1)
		return
	LV.Move(,, Width - 20, Height  - 40)
	LV.Redraw()
}

;=============================================================================================

GuiClose(*)
{
	ComObjConnect(Sink)
	ExitApp
}
DeviceIDPnP

Code: Select all

/*
Script:    DeviceIDPnP.ahk
Author:    XMCQCX
Date:      2023-03-01
Version:   2.0.0
Github:    https://github.com/XMCQCX/DeviceIDPnP
AHK forum: https://www.autohotkey.com/boards/viewtopic.php?f=83&t=114610
*/

#Requires AutoHotkey v2.0
#SingleInstance Force
Persistent
CoordMode "ToolTip", "Screen"
MyDevices := MyDevicesAdd()

;=============================================================================================

MyDevices.Add({DeviceName:"USB 3.0", DeviceID:"USB\VID_0951&PID_1666\E0D55EA573DCF450E97C104C"})

;=============================================================================================

DevicesActions(thisDeviceStatus) {

    if thisDeviceStatus = "USB 3.0 Connected"
        if !WinExist("ahk_exe Notepad.exe")
            Run "Notepad.exe"

    if thisDeviceStatus = "USB 3.0 Disconnected"
        if WinExist("ahk_exe Notepad.exe")
            Winclose "ahk_exe Notepad.exe"
}

;=============================================================================================

Class MyDevicesAdd {
    
    aMyDevices := []

	Add(oItem)
	{
        aDevIDs := [], devCount := 0

        if InStr(oItem.DeviceID, "|&|") {
            for _, devID in StrSplit(oItem.DeviceID, "|&|") {
                aDevIDs.push(devID := Trim(devID))
                oItem.DeviceCount := ++devCount
            }
            if !oItem.HasOwnProp("DevicesMatchMode")
                oItem.DevicesMatchMode := 1
        }
        else {
            aDevIDs.push(oItem.DeviceID := Trim(oItem.DeviceID))
            oItem.DeviceCount := 1
            oItem.DevicesMatchMode := 1
        }   
        
        if !oItem.HasOwnProp("ActionAtStartup")
            oItem.ActionAtStartup := "true"
        
        if !oItem.HasOwnProp("Tooltip")
            oItem.Tooltip := "true"

        oItem.DeviceID := aDevIDs
        this.aMyDevices.push(oItem)
        
        devExist := DevicesExistCheck(aDevIDs, oItem.DeviceCount, oItem.DevicesMatchMode)

        if devExist
            this.aMyDevices[this.aMyDevices.Length].DeviceStatus := "Connected"
        else
            this.aMyDevices[this.aMyDevices.Length].DeviceStatus := "Disconnected"
	}
}

;=============================================================================================

TooltipDevicesActions(Mydevices.aMyDevices)

TooltipDevicesActions(Array) {

    strTooltip := ""

    for _, item in Array
    {
        if item.Tooltip = "true"
            strTooltip .= item.DeviceName A_Space item.DeviceStatus "`n"
        
        if item.ActionAtStartup = "true"
            DevicesActions(item.DeviceName A_Space item.DeviceStatus)
    }

    If strTooltip {
        strTooltip := RTrim(strTooltip, "`n")
        Tooltip strTooltip, 0, 0
        SetTimer () => ToolTip(), -6000
    }
}

;=============================================================================================

DevicesExistCheck(aDevIDs, DeviceCount, DevicesMatchMode) {

    aDevList :=  [], devExistCount := 0
    
    for dev in ComObjGet("winmgmts:").ExecQuery("Select * from Win32_PnPEntity")
        aDevList.Push({DeviceID: dev.DeviceID, DeviceStatus :dev.Status})

    for _, mydevID in aDevIDs
        for _, dev in aDevList
            if mydevID = dev.DeviceID
                if dev.DeviceStatus = "OK"
                    devExistCount++
    
    if DevicesMatchMode = 1
        if DeviceCount = devExistCount
            Return true
    
    if DevicesMatchMode = 2
        if devExistCount
            Return true
}

;=============================================================================================

OnMessage(0x219, WM_DEVICECHANGE)
WM_DEVICECHANGE(wParam, lParam, msg, hwnd) {
    SetTimer DevicesStatusCheck, -1250
}

DevicesStatusCheck() {

    aNewDevStatus := []
    for _, dev in MyDevices.aMyDevices
    {
        devExist := DevicesExistCheck(dev.DeviceID, dev.DeviceCount, dev.DevicesMatchMode)

        if (devExist && dev.DeviceStatus = "Disconnected") {
            dev.DeviceStatus := "Connected"
            aNewDevStatus.Push({DeviceName:dev.DeviceName, DeviceStatus:dev.DeviceStatus, Tooltip:dev.Tooltip, ActionAtStartup:"true"})
        }

        if (!devExist && dev.DeviceStatus = "Connected") {
            dev.DeviceStatus := "Disconnected"
            aNewDevStatus.Push({DeviceName:dev.DeviceName, DeviceStatus:dev.DeviceStatus, Tooltip:dev.Tooltip, ActionAtStartup:"true"})
        }
    }

    If aNewDevStatus.Length >= 1
        TooltipDevicesActions(aNewDevStatus)
}
Kisang Kim
Posts: 12
Joined: 31 Jul 2019, 02:37

Re: DeviceIDPnP v2 - Automatically launch actions when devices are connected or disconnected.

05 Mar 2023, 08:29

:bravo: very good work.
DeviceIDFinder is specillay usful to me.
Thank you for Your post.
ninjahosk
Posts: 1
Joined: 06 Dec 2023, 18:54
Contact:

Re: DeviceIDPnP v2 - Automatically launch actions when devices are connected or disconnected.

06 Dec 2023, 19:04

These scripts were especially helpful for me, I have a use case where I only want my hotkeys to run if I have a certain USB SPDIF adapter connected. By using a #HotIf statement checking the DeviceStatus field, I can conditionally use the hotkeys!

Return to “Scripts and Functions (v2)”

Who is online

Users browsing this forum: No registered users and 13 guests