Hi,

I want to be able to stop hardware devices and I was wondering if it was possible and how you go about doing it.

I'll explain the plan;
I am making an automated install account. Users on the domain would login with a certain user. An install would start and install a certain piece of software. What I was thinking is that the first thing the account does is to run a VB app which would turn off the mouse and keyboard, thus not allowing the user to interact with the process at all. Once the software was installed, the machine would reboot and the hardware could be used again.

Any ideas?

Recommended Answers

All 9 Replies

I have found this code:

Set WshShell = CreateObject("WScript.Shell")
WshShell.Run "devmgmt.msc"
While WshShell.AppActivate("Device Manager") = False
Wend
WshShell.AppActivate "Device Manager"
WshShell.SendKeys "{Tab}"
WshShell.SendKeys "Mice"
WshShell.SendKeys "{Right}"
WshShell.SendKeys "{Down}"
WshShell.SendKeys "+{F10}"
WshShell.SendKeys "D"
WshShell.SendKeys "%Y"
WshShell.SendKeys "%{F4}"

Which turns off the mouse, however the keyboard can't be disabled so it won't work for that.

I have had a play around with the code and found this;

If I unistall the device then I stop the hardware. You can do this for both the mouse and the keyboard. If you do it this way on reboot the machine will now find the hardware and reinstall it.

Now thats XP and 2000 workstations sorted but NT........ Maybe the net stop command in DOS will work here, I haven't got an NT machine to try this out, so I will update this thread at a later date.

The code:

Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)

Private Sub Form_Load()
Set WshShell = CreateObject("WScript.Shell")
WshShell.Run "devmgmt.msc"
While WshShell.AppActivate("Device Manager") = False
Wend
WshShell.AppActivate "Device Manager"
WshShell.SendKeys "{Tab}"
WshShell.SendKeys "Mice"
WshShell.SendKeys "{Right}"
WshShell.SendKeys "{Down}"
WshShell.SendKeys "+{F10}"
WshShell.SendKeys "U"
WshShell.SendKeys "{ENTER}"
WshShell.SendKeys "Keyboards"
WshShell.SendKeys "{Right}"
WshShell.SendKeys "{Down}"
WshShell.SendKeys "+{F10}"
WshShell.SendKeys "U"
WshShell.SendKeys "{ENTER}"
WshShell.SendKeys "%{F4}"
Debug.Print "Started - " & Time()
Sleep 1000
Debug.Print "Ended - " & Time()
Unload Me
End Sub

I had to put the sleep in as the VB code would finish before the machine would prompt for the send key.

If your going to test this beware! As when you run this code you'll have no way of getting the devices reinstalled without a reboot. What I did was to comment out either the Keyboard or the mouse section of the code so I had some means of input.

it's not a good idea to use sleep. Sleeping may always wait (in this case) 1 second, but some machines may take longer than 1 second to load the prompt. Basically, you are having to guess how long it will take that window to appear, and shoot in the dark at an approximate range. I suggest using a findwindow API call, and put yourself in a do loop.... say, do until the return value of findwindow is not 0, then sendkeys to the window.

I've never used the Findwindow API call so any assistance would be greatfully received. I've added this into my code:

Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long

Set WshShell = CreateObject("WScript.Shell")
WshShell.Run "devmgmt.msc"
While WshShell.AppActivate("Device Manager") = False
Wend
WshShell.AppActivate "Device Manager"
WshShell.SendKeys "{Tab}"
'WshShell.SendKeys "Mice"
'WshShell.SendKeys "{Right}"
'WshShell.SendKeys "{Down}"
'WshShell.SendKeys "+{F10}"
'WshShell.SendKeys "U"
'WshShell.SendKeys "{ENTER}"
WshShell.SendKeys "Keyboards"
WshShell.SendKeys "{Right}"
WshShell.SendKeys "{Down}"
WshShell.SendKeys "+{F10}"
WshShell.SendKeys "U"
ret = 1
Do Until ret = 0
ret = FindWindow(vbNullString, "Confirm Device Removal")
Loop
WshShell.SendKeys "{ENTER}"
Unload Me

Now ret gets changed during the loop but the "Confirm Device Removal" box never appears? I'm bound to be doing something daft.......

The code runs but the device doesn't get uninstalled.

I've played some more and sort the Findwindow API usage but I've had to put a sleep back in. The addition of a sleep is because the app unloads b4 its sent the keys. Does anyone know what the desktop window is called?

The code:

Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long


Private Sub Form_Load()
Set WshShell = CreateObject("WScript.Shell")
WshShell.Run "devmgmt.msc"
While WshShell.AppActivate("Device Manager") = False
Wend
WshShell.AppActivate "Device Manager"
Do Until ret > 0
ret = FindWindow(vbNullString, "Device Manager")
Loop
WshShell.SendKeys "{Tab}"
WshShell.SendKeys "Mice"
WshShell.SendKeys "{Right}"
WshShell.SendKeys "{Down}"
WshShell.SendKeys "+{F10}"
WshShell.SendKeys "U"
ret = 0
Do Until ret > 0
ret = FindWindow(vbNullString, "Confirm Device Removal")
Loop
WshShell.SendKeys "{ENTER}"
ret = 0
Do Until ret > 0
ret = FindWindow(vbNullString, "Device Manager")
Loop
WshShell.SendKeys "Keyboards"
WshShell.SendKeys "{Right}"
WshShell.SendKeys "{Down}"
WshShell.SendKeys "+{F10}"
WshShell.SendKeys "U"
ret = 0
Do Until ret > 0
ret = FindWindow(vbNullString, "Confirm Device Removal")
Loop
WshShell.SendKeys "{ENTER}"
WshShell.SendKeys "%{F4}"
Debug.Print "Started - " & Time()
Sleep 1000
Debug.Print "Ended - " & Time()
Unload Me
End Sub

I'm not sure why you need the sleep, findwindow returns a number (the handle to a window) and if it can not find the window, it returns 0. So, do until ret > 0 should work just fine. You may also consider using "doevents" which makes the program process other things temporarily before moving on your code. To answer you actual question, however, there is another API call, called "getdesktopwindow" which will return the hwnd (the numbers that windows refers to the window as) of the desktop to a long variable..

Something that you might want to look at, is the blockinput API call. This will help you I think, but there is a problem, that I'm still looking into, and that is how to disable ctrl-alt-delete with it.... it seems to block everything except for ctrl-alt-del..... so try this:

Private Declare Function BlockInput Lib "user32" (ByVal fBlock As Long) As Long
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)

Private Sub Form_Load()
DoEvents
retval = BlockInput(True)
Sleep 10000
retval = BlockInput(False)
End Sub

This code blocks all input (except for ctrl-alt-delete, working on that) for 10 seconds..... you can obviously block for as long as you want, be it in a loop or whatever.... but be careful ;)

What a nightmare......It turns out that the PC's I need to stop the hardware on are all using PS2 ports and the mahine needs to reboot to uninstall a PS2 device. I'm using USB at home and that works fine with this approach.

So it looks like the Blockinput approach needs developing.......I will report back wth my findings.

I've used the block input approach and found that the vb app needs to be running for the block to work. So what I've done is this:

I've created a batch file which can be used as the users logon script, that batch calls the vb app. The vb app runs the block and calls another batch file that installs the software. Once the software has been installed the focus goes back to the vb app to finish. This then returns focus back to the login batch which reboots the machine.

Private Declare Function BlockInput Lib "user32" (ByVal fBlock As Long) As Long

Private Sub Form_Load()
retval = BlockInput(True)
Set WSHShell = CreateObject("WScript.Shell")
WSHShell.Run "install.bat", 2, True
Unload Me
End Sub

Outstanding, marking the thread solved.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.