You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过编程为特定设备启动更新驱动程序向导?

调用Windows更新驱动程序向导的实现方法

要触发和设备管理器右键菜单完全一致的「更新驱动程序软件」向导,核心是调用Windows SetupAPI中的SetupDiCallClassInstaller函数,指定DIF_UPDATEDRIVER操作码。以下是C# WinForms中的具体实现:

实现步骤与代码

1. 导入Windows API与定义结构体

首先通过P/Invoke导入SetupAPI的相关函数,并定义必要的结构体:

using System;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;

public static class DeviceDriverTools
{
    // SetupAPI常量定义
    private const uint DIGCF_ALLCLASSES = 0x00000004;
    private const uint DIGCF_PRESENT = 0x00000002;
    private const int DIF_UPDATEDRIVER = 0x00000017;
    private const int ERROR_SUCCESS_REBOOT_REQUIRED = 0x000000CB;

    // 设备信息结构体
    [StructLayout(LayoutKind.Sequential)]
    private struct SP_DEVINFO_DATA
    {
        public uint cbSize;
        public Guid ClassGuid;
        public uint DevInst;
        public IntPtr Reserved;
    }

    // 类安装器头部结构体
    [StructLayout(LayoutKind.Sequential)]
    private struct SP_CLASSINSTALL_HEADER
    {
        public uint cbSize;
        public uint InstallFunction;
    }

    // P/Invoke函数声明
    [DllImport("setupapi.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern IntPtr SetupDiGetClassDevs(ref Guid classGuid, string enumerator, IntPtr hwndParent, uint flags);

    [DllImport("setupapi.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern bool SetupDiEnumDeviceInfo(IntPtr deviceInfoSet, uint memberIndex, ref SP_DEVINFO_DATA deviceInfoData);

    [DllImport("setupapi.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern bool SetupDiGetDeviceInstanceId(IntPtr deviceInfoSet, ref SP_DEVINFO_DATA deviceInfoData, StringBuilder deviceInstanceId, int deviceInstanceIdSize, out uint requiredSize);

    [DllImport("setupapi.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern bool SetupDiCallClassInstaller(uint installFunction, IntPtr deviceInfoSet, ref SP_DEVINFO_DATA deviceInfoData);

    [DllImport("setupapi.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern bool SetupDiDestroyDeviceInfoList(IntPtr deviceInfoSet);

2. 实现触发向导的方法

添加静态方法用于根据DeviceID找到设备并启动更新向导:

public static bool LaunchUpdateDriverWizard(string targetDeviceId, IntPtr parentWindowHandle)
    {
        Guid emptyGuid = Guid.Empty;
        // 获取系统中所有已连接的设备信息集
        IntPtr deviceInfoSet = SetupDiGetClassDevs(ref emptyGuid, null, parentWindowHandle, DIGCF_ALLCLASSES | DIGCF_PRESENT);
        if (deviceInfoSet == IntPtr.Zero)
        {
            MessageBox.Show($"获取设备信息集失败,错误码:{Marshal.GetLastWin32Error()}");
            return false;
        }

        try
        {
            SP_DEVINFO_DATA deviceInfo = new SP_DEVINFO_DATA();
            deviceInfo.cbSize = (uint)Marshal.SizeOf(typeof(SP_DEVINFO_DATA));
            uint deviceIndex = 0;

            // 遍历设备,匹配目标DeviceID
            while (SetupDiEnumDeviceInfo(deviceInfoSet, deviceIndex, ref deviceInfo))
            {
                StringBuilder deviceIdBuilder = new StringBuilder(1024);
                uint unusedSize;
                if (SetupDiGetDeviceInstanceId(deviceInfoSet, ref deviceInfo, deviceIdBuilder, deviceIdBuilder.Capacity, out unusedSize))
                {
                    if (deviceIdBuilder.ToString().Equals(targetDeviceId, StringComparison.OrdinalIgnoreCase))
                    {
                        // 调用类安装器,触发更新驱动向导
                        bool operationResult = SetupDiCallClassInstaller(DIF_UPDATEDRIVER, deviceInfoSet, ref deviceInfo);
                        int lastError = Marshal.GetLastWin32Error();

                        // 特殊处理:向导执行成功但需要重启的情况
                        if (!operationResult && lastError != ERROR_SUCCESS_REBOOT_REQUIRED)
                        {
                            MessageBox.Show($"触发更新向导失败,错误码:{lastError}");
                            return false;
                        }
                        return true;
                    }
                }

                deviceIndex++;
                // 重置结构体大小,避免下一次枚举失败
                deviceInfo.cbSize = (uint)Marshal.SizeOf(typeof(SP_DEVINFO_DATA));
            }

            MessageBox.Show("未找到指定DeviceID的设备");
            return false;
        }
        finally
        {
            // 释放设备信息集资源
            SetupDiDestroyDeviceInfoList(deviceInfoSet);
        }
    }
}

3. 在WinForms中调用

在窗体的按钮点击事件或其他逻辑中调用该方法即可:

private void btnUpdateDriver_Click(object sender, EventArgs e)
{
    // 替换为你要操作的设备的DeviceID
    string targetDeviceId = "USB\\VID_XXXX&PID_XXXX\\XXXXXXXXXXXXXXXX";
    DeviceDriverTools.LaunchUpdateDriverWizard(targetDeviceId, this.Handle);
}

注意事项

  • 权限要求:程序必须以管理员权限运行,否则无法触发驱动更新向导(驱动操作需要系统级权限)。
  • 错误处理:如果返回ERROR_SUCCESS_REBOOT_REQUIRED(0xCB),说明向导操作成功但需要重启设备或系统,属于正常结果。
  • DeviceID匹配:DeviceID的格式需与系统中设备的实例ID完全一致(注意大小写不敏感)。

内容的提问来源于stack exchange,提问作者totalZero

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 03:43:16