C# 在Windows 7上使用.NET以编程方式创建/销毁网桥 我试图在Windows 7上编程地创建和销毁一个网络桥。技术上,我希望留在.NET 4领域(PInvokes很好,OFC),但是利用C++是一种选择。 到目前为止,我的研究发现,对于配置,netsh-命令是有效的。然而,似乎没有办法与他们真正建立一座新的桥梁。 我目前正在调查使用INetCfgapi的程序,但该程序或更具体地说,api似乎无法(再次)构建新的桥接。 如果有人能为解决问题做出贡献,我们将非常感谢任何帮助。 [更新:]似乎NewWork桥接器是使用一个驱动程序实现的,该驱动程序随后绑定到两个设备。我还不能充分利用这些信息,因此仍然非常感谢您的帮助。

C# 在Windows 7上使用.NET以编程方式创建/销毁网桥 我试图在Windows 7上编程地创建和销毁一个网络桥。技术上,我希望留在.NET 4领域(PInvokes很好,OFC),但是利用C++是一种选择。 到目前为止,我的研究发现,对于配置,netsh-命令是有效的。然而,似乎没有办法与他们真正建立一座新的桥梁。 我目前正在调查使用INetCfgapi的程序,但该程序或更具体地说,api似乎无法(再次)构建新的桥接。 如果有人能为解决问题做出贡献,我们将非常感谢任何帮助。 [更新:]似乎NewWork桥接器是使用一个驱动程序实现的,该驱动程序随后绑定到两个设备。我还不能充分利用这些信息,因此仍然非常感谢您的帮助。,c#,windows,winapi,networking,C#,Windows,Winapi,Networking,不幸的是,没有记录在案的建立网桥的方法 执行此操作的代码位于hnetcfg.dll内,仅由Windows资源管理器调用。它安装网桥驱动程序,并配置网桥接口 您可以自己调用它(使用COM),但这需要反向工程,并且可能会在任何系统更新时中断,因此我建议不要这样做。实际上可以通过SetupAPI创建和连接网桥。 使用该工具,销毁它们就像这样简单 devcon.exe remove ms_bridgemp …在建造桥梁时,可以使用以下命令: devcon.exe install "C:\Windows

不幸的是,没有记录在案的建立网桥的方法

执行此操作的代码位于hnetcfg.dll内,仅由Windows资源管理器调用。它安装网桥驱动程序,并配置网桥接口


您可以自己调用它(使用COM),但这需要反向工程,并且可能会在任何系统更新时中断,因此我建议不要这样做。

实际上可以通过SetupAPI创建和连接网桥。
使用该工具,销毁它们就像这样简单

devcon.exe remove ms_bridgemp
…在建造桥梁时,可以使用以下命令:

devcon.exe install "C:\Windows\inf\netbrdgm.inf" ms_bridgemp

,因此您可以深入了解源代码,了解它是如何实现这些命令的(DevCon工具本质上是SetupAPI的CLI)。


请注意:这些命令与Windows 7相关。据说这种方法适用于XP,我想它也适用于其他Windows版本,但是.INF文件可能有不同的名称,或者设备ID可能不同。

在Internet上多次搜索失败后,我编写并成功地使用了以下Windows脚本主机脚本“BridgeConnections.vbs”在Windows XP上创建网桥(此方法也适用于Windows 7和Windows 8,只需稍作修改)。可以从命令提示符或批处理文件运行,如下所示:

C:\Temp> cscript BridgeConnections.vbs
文件BridgeConnections.vbs:

' This VBScript opens the "Network Connections" control panel window,
' sends Ctrl+A ("Select All") and Alt+N ("Advanced" menu) and
' C ("Bridge Connections" menu command) keystrokes to it and then waits
' until the splash window "Please wait while Windows bridges the connections..."
' disappears from the screen

Dim WshShell, Count
Set WshShell = WScript.CreateObject("WScript.Shell")

WshShell.Exec("rundll32.exe shell32.dll,Control_RunDLL ncpa.cpl")

Count = 0
Do While Not WshShell.AppActivate("Network Connections") And Count < 10
    Count = Count + 1
    WScript.Sleep 1000
    WScript.Echo "Waiting for the 'Network Connections' window... " & CStr(Count) & "s"
Loop

WshShell.SendKeys "^(a)"
WshShell.SendKeys "%(n)"
WshShell.SendKeys "c"

Count = 0
Do While Not WshShell.AppActivate("Network Bridge") And Count < 10
    Count = Count + 1
    WScript.Sleep 1000
    WScript.Echo "Waiting for the 'Network Bridge' splash window... " & CStr(Count) & "s"
Loop

Count = 0
Do While WshShell.AppActivate("Network Bridge") And Count < 120
  Count = Count + 1
  WScript.Sleep 1000
  WScript.Echo "Waiting for the 'Network Bridge' splash window to disappear... " & CStr(Count) & "s"
Loop 
在此之前发布的方法是,它将创建一个没有适配器的空“半背”桥。因此,在Windows GUI真正可用之前,您仍然需要手动一个接一个地“添加”适配器

唯一一个真正适合我的全自动解决方案是上面的脚本


从C++或C代码中执行相同的操作,而不需要知道脚本,并调用无文档的shell网络接口(NETShell .DLL)函数,当用户通过Windows GUI中的列表视图项选择和上下文菜单命令启动操作时,该功能又被Explorer外壳调用。可以看到调用shell网络接口的C++示例,用于编程禁用/启用网络适配器。不幸的是,目前还没有创建/删除网桥适配器的示例。因此,在它可用之前,我将继续使用脚本。

基于bindview示例,我建立了一个名为bindbridge的实用程序,其工作原理如下:

Usage: bindbridge <deviceId> <bind|unbind>
用法:bindbridge 源代码可以在中找到,它假设桥接设备已经存在-根据前面的回答,可以使用devcon创建-其名称为ms_bridge,可以在源代码中轻松更改

我使用它以编程方式将tap接口添加到桥接器,因此我的命令行如下所示:


bindbridge ROOT\NET\0001 bind

我找到了一个既适用于网桥服务又适用于网桥适配器驱动程序的解决方案。我没有像devcon那样为PlugandPlay设备使用
UpdatedDriver,而是使用
DiInstallDevice

但是,在非交互模式(无用户交互)下首次安装驱动程序是不可能的。这是因为内置网桥.inf文件没有相应的.cat文件。
UpdatedDriverforPlugandPlayDevices
DiInstallDevice
以及
DiInstallDriver
都不适用于手动驱动程序安装,其中.inf文件已包含在%SystemRoot%\inf中,但尚未包含在%SystemRoot%\System32\DriverStore

文件应位于分发介质上或供应商创建的目录中,而不是位于系统位置,如%SystemRoot%\inf

所有提到的安装方法都将创建.inf文件的OEM副本,并将其安装在驱动程序存储中。由于此OEM副本最初不是驱动程序存储的一部分,windows将显示一个提示对话框,并要求用户进行交互,强制安装驱动程序或取消。顺便说一下,后续的驱动程序安装不需要任何用户交互。另外,可以在非交互模式下安装预安装的驱动程序(参见pnputil-a)

这就是我的解决方案:

  • 首先,在
    SetupDiCreateDeviceInfo的帮助下,在HKLM\System\CurrentControlSet\Enum\Root中创建一个设备条目,该条目使用给定的硬件id作为设备名称(ms_bridge,ms_bridgemp)
  • 硬件id分配有
    SetupDiSetDeviceRegistryProperty
  • 驱动程序列表是在
    SetupDiSetDeviceInstallParams
  • 使用
    SetupDiSetSelectedDriver
  • 使用SetupDiCallClassInstaller(DIF_REGISTERDEVICE…)注册设备Usage: bindbridge <deviceId> <bind|unbind>
  • HRESULT InstallDriver(const wchar_t* DriverInfFile, const wchar_t* HardwareId) {
        HRESULT Hr = S_OK;
    
        GUID ClassGUID;
        wchar_t ClassName[MAX_CLASS_NAME_LEN] = {0};
    
        if (SetupDiGetINFClass(DriverInfFile, &ClassGUID, ClassName, sizeof(ClassName) / sizeof(wchar_t), nullptr) == FALSE) {
            Hr = HRESULT_FROM_SETUPAPI(GetLastError());
            return Hr;
        }
    
        HDEVINFO DeviceInfoSet = SetupDiCreateDeviceInfoList(&ClassGUID, nullptr);
    
        if (DeviceInfoSet == INVALID_HANDLE_VALUE) {
            Hr = HRESULT_FROM_SETUPAPI(GetLastError());
            return Hr;
        }
    
        SP_DEVINFO_DATA DeviceInfoData = {
            sizeof(SP_DEVINFO_DATA), 0
        };
    
        if (SetupDiCreateDeviceInfo(DeviceInfoSet, HardwareId, &ClassGUID, nullptr, nullptr, DICD_GENERATE_ID, &DeviceInfoData) == FALSE) {
            Hr = HRESULT_FROM_SETUPAPI(GetLastError());
            SetupDiDestroyDeviceInfoList(DeviceInfoSet);
            return Hr;
        }
    
        if (SetupDiSetDeviceRegistryProperty(DeviceInfoSet, &DeviceInfoData, SPDRP_HARDWAREID, (LPBYTE) HardwareId, (DWORD) (wcslen(HardwareId) + 1) * sizeof(wchar_t)) == FALSE) {
            Hr = HRESULT_FROM_SETUPAPI(GetLastError());
            SetupDiDestroyDeviceInfoList(DeviceInfoSet);
            return Hr;
        }
    
        SP_DEVINSTALL_PARAMS InstallParams = {sizeof(SP_DEVINSTALL_PARAMS), 0};
    
        InstallParams.FlagsEx = DI_FLAGSEX_ALLOWEXCLUDEDDRVS | DI_FLAGSEX_ALWAYSWRITEIDS;
        InstallParams.Flags = DI_QUIETINSTALL | DI_ENUMSINGLEINF;
        wcscpy_s(InstallParams.DriverPath, DriverInfFile);
    
        if (SetupDiSetDeviceInstallParams(DeviceInfoSet, &DeviceInfoData, &InstallParams) == FALSE) {
            Hr = HRESULT_FROM_SETUPAPI(GetLastError());
            SetupDiDestroyDeviceInfoList(DeviceInfoSet);
            return Hr;
        }
    
        SP_DRVINFO_DATA DriverInfoData = {sizeof(SP_DRVINFO_DATA), 0};
    
        if (SetupDiBuildDriverInfoList(DeviceInfoSet, &DeviceInfoData, SPDIT_COMPATDRIVER) == FALSE) {
            Hr = HRESULT_FROM_SETUPAPI(GetLastError());
            SetupDiDestroyDriverInfoList(DeviceInfoSet, &DeviceInfoData, SPDIT_COMPATDRIVER);
        }
    
        // Use first best driver (since specified by inf file)
    
        if (SetupDiEnumDriverInfo(DeviceInfoSet, &DeviceInfoData, SPDIT_COMPATDRIVER, 0, &DriverInfoData)) {
            SetupDiSetSelectedDriver(DeviceInfoSet, &DeviceInfoData, &DriverInfoData);
        }
    
        if (SetupDiCallClassInstaller(DIF_REGISTERDEVICE, DeviceInfoSet, &DeviceInfoData) == FALSE) {
            Hr = HRESULT_FROM_SETUPAPI(GetLastError());
        }
    
        // TODO: Allow non interactive mode for drivers already contained in %SystemRoot%\inf directory
    
        //BOOL PreviousMode = SetupSetNonInteractiveMode(TRUE);
    
        if (Hr == S_OK) {
            if (DiInstallDevice(nullptr, DeviceInfoSet, &DeviceInfoData, &DriverInfoData, 0, nullptr) == FALSE) {
                Hr = HRESULT_FROM_SETUPAPI(GetLastError());
                // Ensure that the device entry in \ROOT\ENUM\ will be removed...
                SetupDiRemoveDevice(DeviceInfoSet, &DeviceInfoData);
            }
        }
    
        //SetupSetNonInteractiveMode(PreviousMode);
    
        SetupDiDestroyDeviceInfoList(DeviceInfoSet);
    
        return Hr;
    }
    
    bridgeutil.exe /attach "PCI\VEN_10EC&DEV_8169" /attach {5d624f94-8850-40c3-a3fa-a4fd2080baf3}\vwifimp
    
    bridgeutil.exe /detach 1