Theory first
- We need to periodically check whether the external webcam is connected to the computer.
- When the external webcam is plugged in, the built-in one should be disabled.
- Then built-in device should be enabled back after the external camera is unplugged.
Preliminary steps
The proposed solution uses batch scripting and task scheduling techniques to handle all of this. Before we can actually jump to the juicy bits, we need to do a few things.
Obtain the Device Console (DevCon) utility
DevCon is a command-line tool that displays detailed information about devices, and lets you search for and manipulate devices from the command line. DevCon enables, disables, installs, configures, and removes devices on the local computer and displays detailed information about devices on local and remote computers.
Download the appropriate
.cab
package depending on the operating system:Open the
.cab
archive and extract the file namedfil[some letters and numbers]
. It should be about 80 KB.- Rename it to
devcon.exe
.
Note In order to enable/disable any device, devcon.exe
must be run with admin rights.
Determine the required hardware identifiers
Windows identifies devices and the setup classes they belong to by using a special set of identifiers. These identifiers are used to match hardware devices with the device drivers that allow them to communicate with Windows.
One or more device IDs are assigned to a device by its manufacturer. One of them, the hardware ID, is very specific - down to the make, model, and even the firmware version of the device. Other device IDs are also assigned, and are more generic, with the IDs possibly being assigned to other devices from the manufacturer that are compatible at some level.
Source: Discovering Hardware IDs and Device Setup Classes for your Devices
- Plug the external webcam in.
- Open the Device Manager (
devmgmt.msc
). - Find your built-in camera in the list.
- Right-click the entry for the device, and then click Properties.
- Select the Details tab and choose Hardware Ids from the property list.
- Right-click the first value shown and copy it. Take note of the value somewhere.
- Repeat steps 3-6 for the external webcam.
Creating the batch script
Save the following code as
WebcamCheck.cmd
:@echo off REM ensure there at least 2 parameters if "%~2" == "" exit /b 2 REM verify devcon.exe is not missing cd /d "%~dp0" if not exist devcon.exe exit /b 3 REM set the interval to 15 seconds if not specified if "%~3" == "" (set interval=15) else (set interval=%3) :poll for /f "tokens=1 delims=\" %%G in ("%~2") do (devcon.exe find *%%G* | findstr /i /c:"%~2" >nul) goto :check%errorlevel% :check0 devcon.exe status "%~1" | findstr /i /c:"disabled" >nul if %errorlevel% == 1 (devcon.exe disable "%~1") :wait timeout /t %interval% /nobreak >nul goto :poll :check1 devcon.exe status "%~1" | findstr /i /c:"disabled" >nul if %errorlevel% == 0 (devcon.exe enable "%~1") goto :wait
Copy the
devcon.exe
file and paste into the same directory as the file you just saved.
How it works
The script takes three parameters: the first one is the target device ID (the built-in webcam); the second one is the trigger device ID (the external webcam); the third one is the polling interval (in seconds), and it's optional.
At first the script will make sure there are enough parameters, and that devcon.exe
isn't missing.
When no polling interval is specified, the default value will be used instead (15 seconds). The value is used to determine how many seconds should elapse between each device check. Lowering the value means the detection is faster, which in turns means there's more system overhead. Before trying a different value, test it with the default one and see how it goes. Either way, I wouldn't recommend going below 10 seconds.
The batch script requires generic device IDs, which use the following format:
XXX\VID_YYYY&PID_ZZZZ
XXX
is the device class (e.g. USB, PCI, etc.); YYYY
is the Vendor ID, an unique value assigned to hardware manufacturers; ZZZZ is the Product ID, which identifies the device model.
For example, if you got a device ID like this:
USB\VID_1D4D&PID_1002&REV_0039&MI_00
the generic ID would be:
USB\VID_1D4D&PID_1002
After checking whether the trigger device (external webcam) is connected, the script will either disable or enable the target device (built-in webcam), unless it's disabled/enabled already.
Scheduling it
The only thing we need now is to make the batch script start automatically at log on.
- Open the Task Scheduler (
taskschd.msc
) and click Action > Create Task. - Name it
WebcamCheck
. - While in the General tab, click Change User or Group.
- Type
system
in the textbox, click Check Names, and then click OK. - Enable the Run with highest privileges option.
- Change the Configure for value to Windows 7, Windows Server 2008 R2.
- Select the Triggers tab, and click New.
- Change the Begin the task to At log on, then press OK.
- Switch to the Actions tab, and click New.
- Type
"X:\Path\to\WebcamCheck.cmd"
in the Program/script textbox, replacing it with the actual file path. - Type
"XXX\VID_YYYY&PID_ZZZZ" "AAA\VID_BBBB&PID_CCCC"
in the Add arguments textbox, replacing the device IDs with the proper values. - Click the Conditions tab and uncheck Start the task only if the computer is on AC power option.
- Select the Settings tab, and uncheck both the Allow task to be run on demand and Stop the task if it runs longer than fields.
- Enable the Run task as soon as possible after a scheduled start is missed option.
- Leave all other settings to default values and press OK.
Note If you want the built-in webcam to be disabled as soon as possible, connect the external one before logging in.
Update
Here's a simplified version of the batch script which will check the external camera only when started and then exit:
@echo off REM ensure there at least 2 parameters if "%~2" == "" exit /b 2 REM verify devcon.exe is not missing cd /d "%~dp0" if not exist devcon.exe exit /b 3 :check for /f "tokens=1 delims=\" %%G in ("%~2") do (devcon.exe find *%%G* | findstr /i /c:"%~2" >nul) goto :check%errorlevel% :check0 devcon.exe status "%~1" | findstr /i /c:"disabled" >nul if %errorlevel% == 1 (devcon.exe disable "%~1") exit /b :check1 devcon.exe status "%~1" | findstr /i /c:"disabled" >nul if %errorlevel% == 0 (devcon.exe enable "%~1") exit /b