Perform an action when a specific USB device is attached?
Re: Perform an action when a specific USB device is attached?
Hello,
I'm looking for A to J but you know it's for a 9 year old visually impaired kid's computer and he won't put anything else on his computer.
I'm looking for A to J but you know it's for a 9 year old visually impaired kid's computer and he won't put anything else on his computer.
Re: Perform an action when a specific USB device is attached?
@jak64.
Okay. Do not rush. Now I have to go.
And all the changes will be only tomorrow (at best case).
added:
Yes I know. All the same, it is necessary to provide for different cases for universality.
Okay. Do not rush. Now I have to go.
And all the changes will be only tomorrow (at best case).
added:
Yes I know. All the same, it is necessary to provide for different cases for universality.
Re: Perform an action when a specific USB device is attached?
Hello ZX80,
Here is the information requested:
1) E:\MesFilms.exe (or D:\ or F:\...)
2) MesFilms (1 single Windows window in my program)
3) HDD
4) FILMS
5) NTFS
6) 9E9C-9D6C
Here is the information requested:
1) E:\MesFilms.exe (or D:\ or F:\...)
2) MesFilms (1 single Windows window in my program)
3) HDD
4) FILMS
5) NTFS
6) 9E9C-9D6C
Re: Perform an action when a specific USB device is attached?
Hello, jak64.
About the second point: If I understand correctly, this is the title only (no window class).
Okay. Hope your program has a unique title text. That is, there are no more windows with the same title in the system. Didn't do any additional testing. Hope this will be enough.
There are many places in the code where the 'Debug' is used. If this bothers you, then you can painlessly remove them all. But I put a lot of them so that you can see what is happening.
Test the code with different disks, flash drives. Try using them at the same time and see if the target is correctly defined. You can also pre-copy your program to each of them, using the same path. In this case, to the root of the disk. You no longer have to worry about guessing what letter your target drive will be. It's not need (only the path to the program). You can also experiment with deliberately changing the target letter.
Well...
Hope this helps you. Just copy and run this code. I have already entered your information in it.
Also I'm waiting for your report if it works or not for you.
Good luck!
P.S. In the future, you can easily change this code to hide the program window in the system tray, if needed.
About the second point: If I understand correctly, this is the title only (no window class).
Okay. Hope your program has a unique title text. That is, there are no more windows with the same title in the system. Didn't do any additional testing. Hope this will be enough.
There are many places in the code where the 'Debug' is used. If this bothers you, then you can painlessly remove them all. But I put a lot of them so that you can see what is happening.
Test the code with different disks, flash drives. Try using them at the same time and see if the target is correctly defined. You can also pre-copy your program to each of them, using the same path. In this case, to the root of the disk. You no longer have to worry about guessing what letter your target drive will be. It's not need (only the path to the program). You can also experiment with deliberately changing the target letter.
Well...
Hope this helps you. Just copy and run this code. I have already entered your information in it.
Also I'm waiting for your report if it works or not for you.
Code: Select all
Structure DiskInfo
type.i
type_str.s
DriveLetter.s
FileSystem.s{256}
VolName.s{256}
Serial.l
Serial_str.s
EndStructure
Enumeration #PB_EventType_FirstCustomValue
#EventType_Attach
#EventType_Detach
EndEnumeration
Enumeration
#Window_0
#Editor
EndEnumeration
Global Dim AttachedDrives.DiskInfo(25)
Global TargetDrive.DiskInfo
Global testdisk.DiskInfo
Global TimeOUT = #True, Eject = #False
Global AllDrive$, Old_DriveLetter$
#time_out = 1000
#separator = "------------"
Define path$ = "\MesFilms.exe" ; relative path (without drive letter / without root), because the drive letter can change over time.
Define ptitle$ = "MesFilms" ; put all or part of the window title here (my own program).
With TargetDrive
\type_str = "HDD" ; or FLASH
\VolName = "FILMS" ; check it in the drive properties window from "My Computer"
\FileSystem = "NTFS" ; check it in the drive properties window from "My Computer"
\Serial_str = "9E9C-9D6C" ; check it in the command line by selecting the desired drive and running the 'dir' command.
; you will find it in the listing. The serial number is assigned To the drive when it is formatted.
; or you can see all the data of the desired disk in the debug window !!!
EndWith
Macro GetTimeStamp
FormatDate("%dd-%mm-%yyyy %hh:%ii:%ss", Date()) + #CRLF$
EndMacro
Macro Writelog
AddGadgetItem(#Editor, -1, logtxt)
If GetWindowLongPtr_(GadgetID(#Editor), #GWL_STYLE) & #WS_VSCROLL
SendMessage_(GadgetID(#Editor), #EM_SCROLL, #SB_BOTTOM, 0)
EndIf
EndMacro
Macro oCheck
IsTarget = #False
If testdisk\type_str=TargetDrive\type_str And testdisk\VolName=TargetDrive\VolName And testdisk\FileSystem=TargetDrive\FileSystem And testdisk\Serial_str=TargetDrive\Serial_str
IsTarget = #True
EndIf
EndMacro
Macro EjectDrive
Debug testdisk\type_str + " drive was disconnected: " + testdisk\DriveLetter
oCheck
If IsTarget = #True
If PostEvent(#EventType_Detach) = 0
Debug "Failed to send message to main thread :("
EndIf
EndIf
AllDrive$ = RemoveString(AllDrive$, Old_DriveLetter$)
Debug #separator
EndMacro
Macro GetVolumeInformation
If scan = 0
ClearStructure(@testdisk, DiskInfo)
If Mask = 0
i = 1
testdisk\DriveLetter = "A:"
Else
For i = 1 To 26
If Mask & 1
Break
EndIf
Mask = Mask >> 1
Next
EndIf
testdisk\DriveLetter = Chr(i + 64)+ ":"
DriveLetter = testdisk\DriveLetter + "\"
i-1
EndIf
If action = #DBT_DEVICEARRIVAL
testdisk\type = GetDriveType_(DriveLetter)
If testdisk\type = 2
testdisk\type_str = "FLASH"
ElseIf testdisk\type = 3
testdisk\type_str = "HDD"
EndIf
GetVolumeInformation_(@DriveLetter, @testdisk\VolName, 255, @testdisk\Serial, 0, 0, @testdisk\FileSystem, 255)
testdisk\Serial_str = RSet(Hex(PeekW(@testdisk\Serial + 2) & $FFFF), 4, "0") + "-" + RSet(Hex(PeekW(@testdisk\Serial) & $FFFF), 4, "0")
If scan = 0 : CopyStructure(@testdisk, @AttachedDrives(i), DiskInfo) : EndIf
EndIf
EndMacro
Procedure CallBack_NewDevice(WindowID, Message, wParam, lParam)
Protected *db.DEV_BROADCAST_HDR
Protected *dbv.DEV_BROADCAST_VOLUME
Protected Mask.l
Protected Result, IsTarget, action, scan=0, i
Protected.s DriveLetter, logtxt
Result = #PB_ProcessPureBasicEvents
Select Message
Case #WM_DEVICECHANGE
If wParam = #DBT_DEVICEARRIVAL
*db = lParam : action = #DBT_DEVICEARRIVAL
If *db\dbch_devicetype = #DBT_DEVTYP_VOLUME
*dbv = lParam : Mask = *dbv\dbcv_unitmask : GetVolumeInformation : oCheck
Debug "action: connect drive"
With testdisk
If IsTarget = #True
If TimeOUT = #False
If Eject = #True
RemoveWindowTimer(#Window_0, 100) : Eject = #False
EndIf
If \DriveLetter <> TargetDrive\DriveLetter
If FindString(AllDrive$, TargetDrive\DriveLetter) = 0
Goto label
EndIf
Debug "*** target drive letter changed to: " + \DriveLetter
Debug Old_DriveLetter$ + " => " + \DriveLetter
Debug #separator
logtxt = GetTimeStamp + "target device changed the drive letter to: (" + \DriveLetter + ")" + #CRLF$ + Old_DriveLetter$ + " => " + \DriveLetter + #CRLF$
AllDrive$ = RemoveString(AllDrive$, Old_DriveLetter$) : AllDrive$ + \DriveLetter
TargetDrive\DriveLetter = \DriveLetter
Writelog
EndIf
Else
label:
Debug "New " + \type_str + " drive connected: " + \DriveLetter
Debug "FileSystem: " + \FileSystem
Debug "VolName: " + \VolName
Debug "Serial: " + \Serial_str
Debug "" : Debug " caught !!!" : Debug ""
TargetDrive\DriveLetter = \DriveLetter
AllDrive$ + \DriveLetter
If PostEvent(#EventType_Attach) = 0
Debug "Failed to send message to main thread :("
Debug #separator
EndIf
EndIf
Else
If TimeOUT = #False
If Eject = #True
RemoveWindowTimer(#Window_0, 100) : Eject = #False
EndIf
If \DriveLetter <> Old_DriveLetter$
If FindString(AllDrive$, Old_DriveLetter$) = 0
Goto label2
EndIf
Debug "*** drive letter changed to: " + \DriveLetter
Debug Old_DriveLetter$ + " -> " + \DriveLetter
AllDrive$ = RemoveString(AllDrive$, Old_DriveLetter$)
AllDrive$ + \DriveLetter
EndIf
Else
label2:
Debug "New " + \type_str + " drive connected: " + \DriveLetter
Debug "FileSystem: " + \FileSystem
Debug "VolName: " + \VolName
Debug "Serial: " + \Serial_str
AllDrive$ + \DriveLetter
EndIf
Debug #separator
EndIf
EndWith
EndIf
ElseIf wParam = #DBT_DEVICEREMOVECOMPLETE
*db = lParam : action = #DBT_DEVICEREMOVECOMPLETE
If *db\dbch_devicetype = #DBT_DEVTYP_VOLUME
*dbv = lParam : Mask = *dbv\dbcv_unitmask : GetVolumeInformation
Old_DriveLetter$ = testdisk\DriveLetter
Debug "action: eject drive"
If AttachedDrives(i)\DriveLetter <> ""
CopyStructure(@AttachedDrives(i), @testdisk, DiskInfo)
ClearStructure(@AttachedDrives(i), DiskInfo)
TimeOUT = #False : Eject = #True
AddWindowTimer(#Window_0, 100, #time_out)
Else
Debug "Unknown USB drive was disconnected: " + testdisk\DriveLetter
Debug #separator
EndIf
EndIf
EndIf
EndSelect
ProcedureReturn Result
EndProcedure
Procedure target_search()
Protected Mask.l = GetLogicalDrives_()
Protected Result = #False, i, action = #DBT_DEVICEARRIVAL
Protected scan = 1, type, IsTarget
Protected DriveLetter.s
For i = 1 To 26
If Mask & 1
testdisk\DriveLetter = Chr(i + 64)+ ":"
DriveLetter = testdisk\DriveLetter + "\"
type = GetDriveType_(DriveLetter)
If type = 2 Or type = 3
GetVolumeInformation
With testdisk
Debug \type_str + " drive connected: " + \DriveLetter
Debug "FileSystem: " + \FileSystem
Debug "VolName: " + \VolName
Debug "Serial: " + \Serial_str
Debug ""
CopyStructure(@testdisk, @AttachedDrives(i-1), DiskInfo)
AllDrive$ + \DriveLetter
If Result = #False
oCheck
If IsTarget = #True
TargetDrive\DriveLetter = \DriveLetter
Result = #True
EndIf
EndIf
EndWith
EndIf
EndIf
Mask = Mask >> 1
Next
Debug "All drives: " + AllDrive$
Debug "=============================="
Debug ""
ProcedureReturn Result
EndProcedure
Procedure FindWin(Title$) ;code by RASHAD
text$ = Space(#MAX_PATH)
Repeat
hwnd = FindWindowEx_(0, hwnd, 0, 0)
GetWindowText_(hwnd, @Text$, #MAX_PATH)
If FindString(LCase(Text$), LCase(Title$), 1) <> 0
findwin = hWnd
Break
EndIf
x + 1
Until findwin Or x > 1000
ProcedureReturn findwin
EndProcedure
Define.i Event, Exit, Result, hWnd
Define.s logtxt
Define my_app$
hWnd = OpenWindow(#Window_0, 0, 0, 500, 300, "Detect events of a specific USB device", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
If hWnd
EditorGadget(#Editor, 10, 10, WindowWidth(#Window_0)-20, WindowHeight(#Window_0)-20)
logtxt = GetTimeStamp + "watchdog started" + #CRLF$
If target_search() = #True
Debug "target device is already connected (" + TargetDrive\DriveLetter + ")"
logtxt = logtxt + "target device is already connected (" + TargetDrive\DriveLetter + ")" + #CRLF$
AddWindowTimer(#Window_0, 101, #time_out)
Else
logtxt = logtxt + "target device not found" + #CRLF$
EndIf
Writelog
SetWindowCallback(@CallBack_NewDevice(), #Window_0)
Repeat
Event = WaitWindowEvent()
Select Event
Case #PB_Event_CloseWindow
Exit = #True
Case #PB_Event_Timer
If EventTimer() = 100
TimeOUT = #True
RemoveWindowTimer(#Window_0, 100)
If Eject = #True
Eject = #False
EjectDrive
EndIf
Else
RemoveWindowTimer(#Window_0, 101)
If FindWin(ptitle$)
Debug "... and your program is already running. Do nothing."
Debug #separator
Else
Debug "Do you want to run the program ?"
Result = MessageRequester("Info", "The target device has been detected."+#CRLF$+"Would you like to launch your program now?", #PB_MessageRequester_YesNo)
If Result = #PB_MessageRequester_Yes
Debug "Your answer: YES"
If PostEvent(#EventType_Attach) = 0
Debug "Failed to send message to main thread :("
Debug #separator
EndIf
Else
Debug "Your answer: No"
Debug #separator
EndIf
EndIf
EndIf
Case #EventType_Attach
SendMessage_(#HWND_BROADCAST, #WM_SYSCOMMAND, #SC_HOTKEY, hWnd)
my_app$ = TargetDrive\DriveLetter + path$
If Result = #PB_MessageRequester_Yes
Result = #False
Else
logtxt = GetTimeStamp + "target device has been connected (" + TargetDrive\DriveLetter + ")" + #CRLF$ : Writelog
Debug "Sleep_(" + Str(#time_out) + ")"
Sleep_(#time_out)
EndIf
If FindWin(ptitle$) ; In case the program is already running from another place
Debug "... and your program is already running. Do nothing."
Else
If FileSize(my_app$) = -1
Debug "file " + #DQUOTE$ + my_app$ + #DQUOTE$ + " was not found :("
Else
Debug "launching... " + #DQUOTE$ + my_app$ + #DQUOTE$
RunProgram(my_app$)
EndIf
EndIf
Debug #separator
Case #EventType_Detach
SendMessage_(#HWND_BROADCAST, #WM_SYSCOMMAND, #SC_HOTKEY, hWnd)
logtxt = GetTimeStamp + "target device has been disconnected (" + TargetDrive\DriveLetter + ")" + #CRLF$ : Writelog
TargetDrive\DriveLetter = Str(#Null)
EndSelect
Until Exit
EndIf
P.S. In the future, you can easily change this code to hide the program window in the system tray, if needed.
Re: Perform an action when a specific USB device is attached?
Hello,
thank you for your work, it works but I think I expressed myself badly.
I would like the program that is on the HDD to run automatically as soon as the HDD disk is connected (without launching any other program and without doing anything else, nothing, nothing at all).
But you have to launch your program for it to work, in this case, if you have to run a program, you might as well run the program directly on the HDD.
thank you for your work, it works but I think I expressed myself badly.
I would like the program that is on the HDD to run automatically as soon as the HDD disk is connected (without launching any other program and without doing anything else, nothing, nothing at all).
But you have to launch your program for it to work, in this case, if you have to run a program, you might as well run the program directly on the HDD.
Re: Perform an action when a specific USB device is attached?
Haha, even if you write 2000 lines of code, it still won't run. You should have discussed in your topic, since this topic has a different focus - the reaction to connecting a flash drive. And your topic is how to force a file to run from a USB flash drive when it is inserted. You have already been told that this is not possible.
Re: Perform an action when a specific USB device is attached?
Ok, thanks but I still learned some things with the ZX80 code, so it's not lost (for me anyway)
Re: Perform an action when a specific USB device is attached?
I said it
https://www.purebasic.fr/english/viewto ... 00#p581100
See sample
https://albertassaad.medium.com/know-if ... 177758cf73
Just fill "actions" tab with your program
That said, I tried to do it but my PC doesn't show anything in the log when I insert a key. But I've changed it so much since I got it that I probably disabled too many things.
In this example it creates a log filter, but in the possible actions there is also launch a program. It is enough (to try) to launch your program on the key. If it is not there because it is another key, nothing will happen.


https://www.purebasic.fr/english/viewto ... 00#p581100
See sample
https://albertassaad.medium.com/know-if ... 177758cf73
Just fill "actions" tab with your program
That said, I tried to do it but my PC doesn't show anything in the log when I insert a key. But I've changed it so much since I got it that I probably disabled too many things.
In this example it creates a log filter, but in the possible actions there is also launch a program. It is enough (to try) to launch your program on the key. If it is not there because it is another key, nothing will happen.

Re: Perform an action when a specific USB device is attached?
@jak64
You are welcome.
I have been asking you about it from the very beginning.
You are welcome.
I have been asking you about it from the very beginning.
here.I think it's possible, but you have to understand that the program that monitors usb connections must be running all the time. Watch dog in the background. Does it suit you?
Re: Perform an action when a specific USB device is attached?
ZX80
Your code is not installed by itself and is not added to autostart. And what you gave I gave a long time ago, right after your post. But even when you do everything, I will not be surprised that you will be told that it does not work.
Your code is not installed by itself and is not added to autostart. And what you gave I gave a long time ago, right after your post. But even when you do everything, I will not be surprised that you will be told that it does not work.
Re: Perform an action when a specific USB device is attached?
Hey jak64,
i think all the programming tricks have been shown here by the professionals.
More info on this topic: you can enter the following in your favorite search engine "autorun and autoplay".
There are many pages explaining how, where, and what the so-called removable devices are all about.
Good luck.
i think all the programming tricks have been shown here by the professionals.
More info on this topic: you can enter the following in your favorite search engine "autorun and autoplay".
There are many pages explaining how, where, and what the so-called removable devices are all about.
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).
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).
Re: Perform an action when a specific USB device is attached?
Hi Axolotl
Tank you
Tank you
Re: Perform an action when a specific USB device is attached?
AZJIO,
I assumed that my resident program would be launched along with the start of the operating system. Yes, I also thought about setting the registry flag - "run at the next OS boot". And every time you run the watchdog (my prog), install it again. Thus, it turns out that we need to run the watchdog program only once. And then everything will be done in a cycle automatically. Only there is a condition that the watchdog program is always available. That is, on some section of the client machine. I don't understand what's wrong with doing it this way.
offtopic:
I also suffer with my eyes(never said it here). And I wanted to show solidarity with the guy for whom this was done. Also in one of the topics jak64 (I'm already confused) said that he was already many years old. And this also played an important role.
Well... Still, it was an exciting journey. And there are many uses for this. For example, protecting a program with an iron key. I understand that in this form it looks childish. However, this is only one of the options.
In any case, if at least one person will use it, then everything was not in vain.
@jak64
I have nothing more to offer you. It's true. I'm very sorry.
That's all.
I assumed that my resident program would be launched along with the start of the operating system. Yes, I also thought about setting the registry flag - "run at the next OS boot". And every time you run the watchdog (my prog), install it again. Thus, it turns out that we need to run the watchdog program only once. And then everything will be done in a cycle automatically. Only there is a condition that the watchdog program is always available. That is, on some section of the client machine. I don't understand what's wrong with doing it this way.
I already understood it. Large bold letters and red link color as a consequence. Yes, everything has a reason. I know it's not necessary to do this. Sorry. Red is the admin color. Not for the average user. This is a good tone in other forums.But even when you do everything, I will not be surprised that you will be told that it does not work.
offtopic:
I also suffer with my eyes(never said it here). And I wanted to show solidarity with the guy for whom this was done. Also in one of the topics jak64 (I'm already confused) said that he was already many years old. And this also played an important role.
Well... Still, it was an exciting journey. And there are many uses for this. For example, protecting a program with an iron key. I understand that in this form it looks childish. However, this is only one of the options.
In any case, if at least one person will use it, then everything was not in vain.
@jak64
I have nothing more to offer you. It's true. I'm very sorry.
That's all.
Re: Perform an action when a specific USB device is attached?
Hello ZX89,
Thank you for all you have done, it was very kind of you to take the time to try to help me.
Good continuation and see you soon to give me other advice on lots of subjects, there is so much to learn and I love using Purebasic.
Thank you for all you have done, it was very kind of you to take the time to try to help me.
Good continuation and see you soon to give me other advice on lots of subjects, there is so much to learn and I love using Purebasic.
Re: Perform an action when a specific USB device is attached?
Hello, jak64.
I'll tell you a secret: each hard drive has a mini OS. Do not tell anyone... tsss... be quiet
One part of the firmware is stored in a chip, and the other on pancakes. At least at Seagate it is. You can connect to the disk via arduino and give commands to it. The hard disk has a separate service connector consisting of four pins (especially for these purposes). I did this in the terminal program 'putty' with my old hard drive (5.25 inch disk). For research purposes only. Maybe this info will be a clue for you. But I have no idea how can this info be applied to your task. And... is it even possible? Please don't ask me about it. I also do not recommend you to do this and just forget it. This is very dangerous and you need to understand what you are doing. Otherwise, you will not even have time to blink an eye as you kill your hard drive. To do this, just enter the wrong command.
Try reading about mbr, partition table, etc. This information is outdated these days, but it's interesting to know how it works anyway.
Another variant. Perhaps, your task can be done by editing the driver. But then you will lose the signature and trust of the system. For 64-bit systems, this is 100% true! Since they are very sensitive to the absence of a signature.
I'm not helping you here either. These are just thoughts spoken out loud.
P.S. Nobody said it would be easy if you follow all your desires. You need to understand and accept some limitations. And come to a compromise solution.
Some members will say it's trolling. And they will be right, but only slightly.
However, this post contains some useful information.
I'll tell you a secret: each hard drive has a mini OS. Do not tell anyone... tsss... be quiet

One part of the firmware is stored in a chip, and the other on pancakes. At least at Seagate it is. You can connect to the disk via arduino and give commands to it. The hard disk has a separate service connector consisting of four pins (especially for these purposes). I did this in the terminal program 'putty' with my old hard drive (5.25 inch disk). For research purposes only. Maybe this info will be a clue for you. But I have no idea how can this info be applied to your task. And... is it even possible? Please don't ask me about it. I also do not recommend you to do this and just forget it. This is very dangerous and you need to understand what you are doing. Otherwise, you will not even have time to blink an eye as you kill your hard drive. To do this, just enter the wrong command.
Try reading about mbr, partition table, etc. This information is outdated these days, but it's interesting to know how it works anyway.
Another variant. Perhaps, your task can be done by editing the driver. But then you will lose the signature and trust of the system. For 64-bit systems, this is 100% true! Since they are very sensitive to the absence of a signature.
I'm not helping you here either. These are just thoughts spoken out loud.
P.S. Nobody said it would be easy if you follow all your desires. You need to understand and accept some limitations. And come to a compromise solution.
Some members will say it's trolling. And they will be right, but only slightly.

However, this post contains some useful information.