Perform an action when a specific USB device is attached?

Just starting out? Need help? Post your questions and find answers here.
Axolotl
Addict
Addict
Posts: 830
Joined: Wed Dec 31, 2008 3:36 pm

Re: Perform an action when a specific USB device is attached?

Post by Axolotl »

Hey jak64,
as I wrote the othe day, I liked the solutions and ideas of the others....

Because I don't think we can help you with your problem otherwise. The operating system doesn't allow it. (my state of affairs)
Nevertheless here is some more information about the topic.

If you tried out the AutoRun and AutoPlay search, you probably found some information like this:

For security reasons, programs can no longer be started automatically from a USB stick via AutoRun.inf under the default settings as of Windows 7. With tools like 'AutoRunnerX' you can nevertheless command your USB stick to start a program immediately after the stick has been connected.
The mode of AutoRunnerX's:operation corresponds to that of the above examples.
In my opinion a usb stick will behave exactly the same as an attached hard disk.

The AutoRun.inf is the configuration stuff, which works on older windows. eg Windows XP
Autorun.inf for USB stick
# first save a text fle on the USB stick under the name "Autorun.inf".
# open the Autorun file on your USB stick again with a text editor.
# Add the line "open=exampleprogram.exe" without quotes.
So here the program exampleprogram would be executed.
The associated exe file must be on the stick for this.
# If you want to see your own image instead of the usual drive icon, add "icon=image.ico" to the next line.
The image must also be stored on the USB carrier.
# You change the name of the data carrier by adding "label=name".

Maybe you can change settings with SetACL and Registry Permissions so that it also works under new windows versions, probably at the expense of security. But I will not go into this further, because I have even less knowledge about it.

And also antivirus programs restrict the use of autorun and autoplay.

Okay, and one last tip:
To open the autoplay settings just enter the following clsid code in the run dialog (WIN+R).
shell:::{9C60DE1E-E5FC-40f4-A487-460851A8D915}

Good luck.
Just because it worked doesn't mean it works.
PureBasic 6.04 (x86) and <latest stable version and current alpha/beta> (x64) on Windows 11 Home. Now started with Linux (VM: Ubuntu 22.04).
User avatar
ChrisR
Addict
Addict
Posts: 1466
Joined: Sun Jan 08, 2017 10:27 pm
Location: France

Re: Perform an action when a specific USB device is attached?

Post by ChrisR »

Based on AZJIO code for automatic program execution, when a device has been inserted.
I extended it a bit to enable almost the same Open or ShellExecute features as the old Autorun one, via the Autorun.inf file.

Ex: Autorun.inf with PStart

Code: Select all

[Autorun]
Label=PStart
UseAutoPlay=0
Open=PStart.exe
Icon=PStart.exe
ShellExecute=http://www.pegtop.net

Parameter: Autorun.exe [Install | Uninstall]
  • Autorun.exe Install : Copy Autorun.exe in %AppData%\Autorun folder and Add the entry in HKCU\Software\Microsoft\Windows\CurrentVersion\Run registry key. To make Autorun.exe run when a user logs on
  • Autorun.exe Uninstall: Remove %AppData%\Autorun folder and Remove the autorun registry entry
  • Autorun.exe : Run Autorun.exe manually from its current location, waiting for an inserted device

Code: Select all

; -----------------------------------------------------------------------------
;           Name: Autorun.pb - Autorun.exe 
;    Description: Enable the old Open or ShellExecute features of Autorun.inf, when a device has been inserted and becomes available. 
;                 The Autorun Windows features have been removed to avoid running possible malware.
;         Author: ChrisR base on AZJIO's code
;           Date: 2022-02-24
;        Version: 1.0
;     PB-Version: 5.73 LTS
;             OS: Windows x64/x86
;          Forum: https://www.purebasic.fr/english/viewtopic.php?p=580922#p580922
; -----------------------------------------------------------------------------
; Parameter: Autorun.exe [Install | Uninstall]
;   - Autorun.exe Install  : Copy Autorun.exe in %AppData%\Autorun folder and Add the entry in HKCU\Software\Microsoft\Windows\CurrentVersion\Run registry key
;                            To make Autorun.exe run when a user logs on
;   - Autorun.exe Uninstall: Remove %AppData%\Autorun folder and Remove the autorun registry entry
;   - Autorun.exe          : Run Autorun.exe manually from its current location, waiting for an inserted device 
; -----------------------------------------------------------------------------

EnableExplicit

#KEY_WOW64_64KEY = $100

#Windows_0     = 0
#SysTrayIcon   = 0
#Menu          = 0

Enumeration
  #About
  #Exit
EndEnumeration

Global Drives_Avail, Letters$

; Here you need a code to prevent the program from restarting
Define *a = CreateSemaphore_(#Null, 0, 1, "USB5671230")
If *a And GetLastError_() = #ERROR_ALREADY_EXISTS
  CloseHandle_(*a)
  ; 	MessageRequester("Autorun","The program is already running")   ; Optional, you can report that the program is already running
  End
EndIf

Procedure Exit()
  If IsSysTrayIcon(#SysTrayIcon)
    RemoveSysTrayIcon(#SysTrayIcon)
  EndIf
  CloseWindow(#Windows_0)
  End
EndProcedure

Procedure StartWithWindows(Program$, State.b)   ; By Joakim Christiansen
  If FileSize(Program$) <= 0 : ProcedureReturn : EndIf
  Protected Key.l = #HKEY_CURRENT_USER   ; Or #HKEY_LOCAL_MACHINE for every user on the machine
  Protected Path.s = "Software\Microsoft\Windows\CurrentVersion\Run"
  Protected Value.s = "Autorun"
  Protected String.s = Chr(34) + Program$ + Chr(34)
  Protected CurKey.l = #KEY_WOW64_64KEY
  If State
    RegCreateKey_(Key, @Path, @CurKey)
    RegSetValueEx_(CurKey, @Value, 0, #REG_SZ, @String, 255)
  Else
    RegOpenKey_(Key, @Path, @CurKey)
    RegDeleteValue_(CurKey, @Value)
  EndIf
  RegCloseKey_(CurKey)
EndProcedure

Procedure Add_drive(Mask.l)
  Protected i, CurLetter$, Open$, ShellExecute$, StartDisk = 2
  For i = StartDisk To 25
    If ((Mask >> i) & 1)   ; Check each flag
      CurLetter$ = Chr(i + 65)
      ;	Reaction to Autorun.inf marker file
      If FileSize(CurLetter$ + ":\Autorun.inf") > 0
        
        Open$ = "" : ShellExecute$ = ""
        If OpenPreferences(CurLetter$ + ":\Autorun.inf")
          If PreferenceGroup("autorun")
            Open$         = ReadPreferenceString("Open", Open$)
            ShellExecute$ = ReadPreferenceString("ShellExecute", ShellExecute$)
          EndIf
          ClosePreferences()
        EndIf
        ; Parameter for Open or ShellExecute is not yet done, it is rarely used
        If Open$ <> ""
          If Left(Open$, 1) <> "\" : Open$ = "\" + Open$ : EndIf
          If FileSize(CurLetter$ + ":" + Open$) > 0
            RunProgram(CurLetter$ + ":" + Open$, "", GetPathPart(CurLetter$ + ":" + Open$))
          EndIf
        EndIf
        If ShellExecute$ <> ""
          ShellExecute_(0, "Open", ShellExecute$, "", "", #SW_SHOWNORMAL)
        EndIf
        
      EndIf
      Letters$ + CurLetter$
    EndIf
  Next
  Debug Letters$
EndProcedure

Procedure Del_drive(Mask.l)
  Protected i, Count, CurLetter$
  Count = Len(Letters$)
  For i = Count To 1 Step - 1
    CurLetter$ = Mid(Letters$, i, 1)
    If (Mask >> (Asc(CurLetter$) - 65)) & 1
      Letters$ = ReplaceString(Letters$, CurLetter$, "", #PB_String_NoCase, i, 1)
      ;ex: RunProgram("cmd.exe", "/c (taskkill /im " + xxx.exe + ")", "")
    EndIf
  Next
  Debug Letters$
EndProcedure

Procedure WinCallback(hWnd, uMsg, wParam, lParam)
  Protected Result = #PB_ProcessPureBasicEvents, Mask, Drive.s,  *pDBHDR.DEV_BROADCAST_HDR, *pDBV.DEV_BROADCAST_VOLUME
  Protected Tmp
  Select uMsg
      ;Case #WM_UNINITMENUPOPUP
      ;  Debug "PopupMenu has been closed."
    Case #WM_DEVICECHANGE   ; Change when connecting external drives.
      Result = #True
      Select wParam
        Case #DBT_DEVICEARRIVAL, #DBT_DEVICEREMOVECOMPLETE
          *pDBHDR.DEV_BROADCAST_HDR    = lParam
          If *pDBHDR\dbch_devicetype   = #DBT_DEVTYP_VOLUME
            *pDBV.DEV_BROADCAST_VOLUME = lParam
            Mask                       = *pDBV\dbcv_unitmask
            Select wParam
              Case #DBT_DEVICEARRIVAL
                ; Debug Bin(Drives_Avail)
                ; Debug Bin(Mask)
                Tmp = Drives_Avail
                Drives_Avail | Mask
                If Tmp <> Drives_Avail
                  Add_drive(Mask)
                EndIf
              Case #DBT_DEVICEREMOVECOMPLETE
                Drives_Avail ! (Mask & Drives_Avail)
                Del_drive(Mask)
            EndSelect
          EndIf
      EndSelect
  EndSelect
  ProcedureReturn Result
EndProcedure

;- Main
If OSVersion() < #PB_OS_Windows_7
  MessageRequester("Autorun","Native Autorun is already enabled on systems below Windows 7" + #CRLF$+ "Exit")
  End
EndIf

If CountProgramParameters() = 1
  Define AutorunPath$ = GetUserDirectory(#PB_Directory_ProgramData)  + "Autorun\"   ; Or #PB_Directory_AllUserData for every user on the machine
  Define AutorunExe$ = AutorunPath$ + "Autorun.exe"
  Select LCase(ProgramParameter(0))
    Case "install"
      If FileSize(AutorunExe$) = -1
        If FileSize(AutorunPath$) <> -2
          CreateDirectory(AutorunPath$)
        EndIf
        CopyFile(ProgramFilename(), AutorunExe$)
      EndIf
      If FileSize(AutorunExe$) > 0
        StartWithWindows(AutorunExe$, #True)
      EndIf
    Case "uninstall"
      If FileSize(AutorunExe$) > 0
        StartWithWindows(AutorunExe$, #False)
        DeleteDirectory(AutorunPath$, "*.*")
      EndIf
  EndSelect
  End
EndIf

Define hWin_0 = OpenWindow(#Windows_0, 0, 0, 0, 0, "", #PB_Window_Invisible)

If GetClassLongPtr_(hWin_0, #GCL_HICON)
  AddSysTrayIcon(#SysTrayIcon, hWin_0, GetClassLongPtr_(hWin_0, #GCL_HICON))
  SysTrayIconToolTip(#SysTrayIcon, "Autorun Monitoring")
  
  CreatePopupMenu(#Menu)
  MenuItem(#Exit, "Exit")
  
  BindMenuEvent(#Menu, #Exit, @Exit())
EndIf

SetWindowCallback(@WinCallback())

Repeat
  Select WaitWindowEvent()
    Case #PB_Event_SysTray
      Select EventType()
        Case #PB_EventType_RightClick
          DisplayPopupMenu(#Menu, hWin_0)
      EndSelect
    Case #PB_Event_CloseWindow
      Exit()
  EndSelect
ForEver
Exit()

; IDE Options = PureBasic 5.73 LTS (Windows - x64)
; Folding = -
; EnableXP
; UseIcon = Autorun.ico
; Executable = Autorun.exe
jak64
Enthusiast
Enthusiast
Posts: 625
Joined: Sat Aug 15, 2020 5:02 pm
Location: Ciboure (France)

Re: Perform an action when a specific USB device is attached?

Post by jak64 »

Thank you all for all this information
Post Reply