I am trying to install a driver during a windows-setup project.
The first step I do is to copy the INF file and preinstall the driver.
SetupCopyOEMInf(infFile, null, 1, 0, null, 0, 0, null);
This correctly preinstalls the driver, but the device is not ready to use until a hardware rescan is done in Device Manager. I want to automate this as well. I have tried using the setupapi.dll to invoke the hardware rescan, but it was not always successful for me. Using devcon.exe rescan always forces the hardware rescan, but it is a synchronous command, and it returns before the device is finished installing. Is there any way to get a return result after the hardware scan completes and the driver is successfully installed?
Thanks,
Misha
Edit
Here is my working code:
public const UInt32 CR_SUCCESS = 0;
public const UInt64 CM_REENUMERATE_SYNCHRONOUS = 1;
public const UInt64 CM_LOCATE_DEVNODE_NORMAL = 0;
[DllImport("setupapi.dll")]
public static extern bool SetupCopyOEMInf(
string SourceInfFileName,
string OEMSourceMediaLocation,
int OEMSourceMediaType,
int CopyStyle,
string DestinationInfFileName,
int DestinationInfFileNameSize,
int RequiredSize,
string DestinationInfFileNameComponent
);
[DllImport("cfgmgr32.dll")]
public static extern int CM_Locate_DevNode_Ex(ref IntPtr deviceHandle, int deviceId, uint flags, IntPtr machineHandle);
[DllImport("cfgmgr32.dll")]
public static extern int CM_Reenumerate_DevNode_Ex(IntPtr devInst, UInt64 flags);
[DllImport("cfgmgr32.dll")]
public static extern int CMP_WaitNoPendingInstallEvents(UInt32 timeOut);
static void Main() {
bool success = SetupCopyOEMInf(infFile, null, 1, 0, null, 0, 0, null);
if(!success) {
throw new Exception("Error installing driver");
}
success = RescanAllDevices();
if (!success) {
throw new Exception("Error installing driver");
}
}
public static bool RescanAllDevices() {
int ResultCode = 0;
IntPtr LocalMachineInstance = IntPtr.Zero;
IntPtr DeviceInstance = IntPtr.Zero;
UInt32 PendingTime = 30000;
ResultCode = CM_Locate_DevNode_Ex(ref DeviceInstance, 0, 0, LocalMachineInstance);
if (CR_SUCCESS == ResultCode) {
ResultCode = CM_Reenumerate_DevNode_Ex(DeviceInstance, CM_REENUMERATE_SYNCHRONOUS);
ResultCode = CMP_WaitNoPendingInstallEvents(PendingTime);
}
return ResultCode == CR_SUCCESS;
}
The source for devcon is available in the WDK. It's in the src\setup\devcon directory. The logic for the rescan command is in the cmdRescan function in cmds.cpp. It would be a simple matter to copy that logic into your own code and make sure it doesn't return immediately.