Welcome to Blogs @ Andrew Qu
Blog Index
All blogs
Search results

Removing Hidded Devices on PC

Summary

How to remove hidden devices on a PC ? You do this by using Device Manager. But this cane be tideous if you have hundreds of hidden devices. In this blog, I will use Windows WDK to write a console program to accomplish the job.

Showing Hidden Devices

When you start the Device Manager, by default, the hidden devices are not displayed. You need to set an environment variable to enable it. The following command lines will do this:

set devmgr_show_nonpresent_devices=1
start \windows\system32\devmgmt.msc

The Device Manager will start. In it, click [View] -> [Show hidden devices]

Checking Device Class GUID and Vendor ID

To match a device, we need the device's Class GUID and it's Vendor ID. The information can be found in the Device Manager by listing the device properties, as showing in the following screen shot:



Creating the Project

You must install Window Driver Kit (7 or 8) and have the matching version of Visual Studio. Download WDK Here (WDK includes devcon.exe built from the WDK sample, but it cannot remove hidden devices).

  1. Create a Win32 Console Application
  2. Select [Using ATL], this will reduce the effort needed to sort the header files.
  3. Add setupapi.lib to the project's [Additinal dependencies] list.
Full listing of the code:
#include "stdafx.h"

#include <conio.h>
#include <SetupAPI.h>
#include <Newdev.h>

#define INITGUID 
#include <Devpkey.h>
#include <Cfgmgr32.h>

// Hard coded IDs for convenience if one can rebuild the program
CString ClassGUID_2Match[10] = {
   _T("{3F776BD0-EA14-4ec5-771C-E326986C6228}"),
};
CString VID_2Match[10] = {
   _T("VID_32F1"),
};
BOOL MatchDevice(HDEVINFO DeviceInfoSet, SP_DEVINFO_DATA *DeviceInfoData);

int _tmain(int argc, _TCHAR* argv[])
{
   SP_DEVINFO_DATA DeviceInfoData;
   DEVPROPTYPE PropType;
   WCHAR desc[200];
   char input[200];

//   BOOL needReset;
   HDEVINFO DeviceInfoSet = SetupDiGetClassDevs(NULL, NULL, NULL, DIGCF_ALLCLASSES);// | DIGCF_PRESENT);
   ZeroMemory(&DeviceInfoData, sizeof(SP_DEVINFO_DATA));
   DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);

   // Print hard coded guids
   int nGuids = 0;
   while( ClassGUID_2Match[nGuids].GetLength() > 1 )
   {
      _tprintf(_T("Class GUID to match: %s\n"), ClassGUID_2Match[nGuids]);
      nGuids++;
   }
   int nVids = 0;
   while( VID_2Match[nVids].GetLength() > 1 )
   {
      _tprintf(_T("VID to match: %s\n"), VID_2Match[nVids]);
      nVids++;
   }
   // Read additional GUID/VID from file
   FILE *fids = fopen("guid_vid.txt", "rt");
   if( !fids )
   {
      printf("\nAdditional GUIDS and VIDs can be specified in a file named guid_vid.txt\n");
      printf("Place each GUID or VID on a separate line.\n");
   }
   else
   {
      while( fgets(input, 200, fids) )
      {
         if(strlen(input) < 10) 
         {
            if(nVids < 10) 
            {
                VID_2Match[nVids++] = input;
                printf("VID to match: %s\n", input);
            }
         }
         else if(nGuids < 10) 
         {
             printf("Class GUID to match: %s\n", input);
             ClassGUID_2Match[nGuids++] = input;
         }
      }
      fclose(fids);
   }

   _tprintf(_T("Scanning device tree, pleast wait..."));

   // Get total lnumber of devices
   int DeviceIndex = 0;
   int nRemoved = 0;
   while (SetupDiEnumDeviceInfo(DeviceInfoSet, DeviceIndex, &DeviceInfoData))
   {
      DeviceIndex++;
      if( MatchDevice(DeviceInfoSet, &DeviceInfoData) ) nRemoved++;
   }
   printf("\nNumber of devices found: %d\n\n", nRemoved);      
   //
   DeviceIndex = 0;
   nRemoved = 0;
   BOOL bRemoveAll = FALSE;
   DWORD Size;
   // Remove devices
   //
   while(SetupDiEnumDeviceInfo(DeviceInfoSet, DeviceIndex, &DeviceInfoData))
   {
      DeviceIndex++;
      if( !MatchDevice(DeviceInfoSet, &DeviceInfoData) ) continue;
      // Get device description
      SetupDiGetDeviceProperty(DeviceInfoSet, &DeviceInfoData,
            &DEVPKEY_Device_DeviceDesc, &PropType, (PBYTE)desc, sizeof(desc), &Size, 0);
      char tc;
      if( bRemoveAll ) {  Sleep(100);   tc = 'y'; }
      else
      {
         _tprintf(_T("Found device: %s  Remove (y/n/all) ? "), desc);
         char tc = _getch();
         if( tc == 'a' ) {  tc = 'y';   bRemoveAll = TRUE; }
      }
      if( tc != 'y' )  _tprintf(_T("n\n"));
      else
      {
         _tprintf(_T("y\n   Removing device.\n"));
         SetupDiRemoveDevice(DeviceInfoSet, &DeviceInfoData);
         nRemoved++;
      }
   }
   printf("\nNumber of devices removed: %d", nRemoved);      
   if (DeviceInfoSet)
   {
      SetupDiDestroyDeviceInfoList(DeviceInfoSet);
   }
   _tprintf(_T("\nPress any key to exit..."));
   _getch();
   return 0;
}

BOOL MatchDevice(HDEVINFO DeviceInfoSet, SP_DEVINFO_DATA *DeviceInfoData)
{
    DEVPROPTYPE PropType;
    WCHAR hwids[200];
    DWORD Size;

    const CComBSTR guidBstr(DeviceInfoData->ClassGuid);
    const CString guidStr(guidBstr);

    // Match class ID
    BOOL bMatched = FALSE;
    int i=0;
    while( ClassGUID_2Match[i].GetLength() > 10 )
    {
       if( guidStr.CompareNoCase(ClassGUID_2Match[i++]) == 0 )
       {
          bMatched = TRUE;
          break;
       }
    }
    if( !bMatched ) return FALSE;

    // Match VID
    if ( !SetupDiGetDeviceProperty(DeviceInfoSet, DeviceInfoData,
          &DEVPKEY_Device_HardwareIds, &PropType, (PBYTE)hwids, sizeof(hwids),
          &Size, 0) || PropType != DEVPROP_TYPE_STRING_LIST)
    {
        _tprintf(_T("This device has no hardware ID\n"));                     
        return FALSE;
    }
    CString csID(hwids);
    bMatched = FALSE;
    i = 0;
    while( VID_2Match[i].GetLength() > 3)
    {
       if( csID.Find( VID_2Match[i++] ) > 0 )
       {
          bMatched = TRUE;
          break;
       }
    }
    return bMatched;
}
Code Analysis
#define INITGUID 
#include <Devpkey.h>
In the above, #define INITGUID is necessary (for some reason). Otherwise there will be compiler errors.
CString ClassGUID_2Match[10] = {
CString VID_2Match[10] = {
Lists hard coded Class GUIDs and Vendor IDs to match devices. This is purely for convenience if you are able to rebuild the program. Additional GUIDs and VIDs can be add to a file named "guid_vid.txt" located in the same folder as the exe file. Place each ID on a separate line, for example,
{3F776BD0-EA14-4ec5-771C-E326986C6228}
VID_32F1
The IDs from the file are appended to the harded coded IDs.
HDEVINFO DeviceInfoSet = SetupDiGetClassDevs(NULL, NULL, NULL, DIGCF_ALLCLASSES);// | DIGCF_PRESENT);
This call selects a set of devices using the given filter conditions. In this case, we are getting all devices. If the flag DIGCF_PRESENT is specified, then we'll only get the connected devices.
while (SetupDiEnumDeviceInfo(DeviceInfoSet, DeviceIndex, &DeviceInfoData))
This call enumerates through the devices in the device set, using a DeviceIndex that is increamented by 1 in each step. The call sets the DeviceInfoData for the device, if successful.
SetupDiGetDeviceProperty(DeviceInfoSet, &DeviceInfoData,
    &DEVPKEY_Device_DeviceDesc, &PropType, (PBYTE)desc, sizeof(desc), &Size, 0);
This call retrieves the device's specified property. In the above example, we are getting the device's description (DEVPKEY_Device_DeviceDesc). Other possible properties are DEVPKEY_Device_HardwareIds
DEVPKEY_Device_Class
etc
SetupDiRemoveDevice(DeviceInfoSet, &DeviceInfoData);
This call removes the given device.

Source code download
Download full source code

The zip file also includes the built executable that may be used straight away.
Ads from Google
Dr Li Anchor Profi
www.anchorprofi.de
Engineering anchorage plate design system
©Andrew Qu, 2015. All rights reserved. Code snippets may be used "AS IS" without any kind of warranty. DIY tips may be followed at your own risk.