Programmatically create / destroy network bridges using .NET on Windows 7

I am trying to programmatically create and destroy a network bridge in Windows 7.
Technologically, I would like to stay in the area of ​​.Net 4 (PInvokes is good, fromc), but using C ++ is an option.

My research has so far found out that the route is for configuring the netsh command. However, there seems to be no way to actually deploy a new bridge with them.
I am currently studying this program that uses the INetCfg API, but it looks like a program or, more specifically, an API that is not able (again) to build a new bridge.

If someone can contribute to solving the problem, then any help is greatly appreciated.

[Update:] It seems that Newtork bridges are implemented using a driver, which then binds to both devices. I still can not much of this information, so any help is welcome anyway.

+4
source share
5 answers

I found a solution that works for both the bridge service and the bridge adapter> . I do not use UpdateDriverForPlugAndPlayDevices as devcon , but instead I use DiInstallDevice .

However, installing drivers for the first time in non-interactive mode (without user interaction) is not possible. This is because there are no corresponding .cat files for embedded .inf files. Neither UpdateDriverForPlugAndPlayDevices , nor DiInstallDevice , nor DiInstallDriver are intended to be installed manually, where the .inf file is already contained in % SystemRoot% \ inf , but is not yet included in % SystemRoot% \ System32 \ DriverStore .

The files must be located on the distribution medium or in a directory created by the provider, and not in a system location such as% SystemRoot% \ inf

All of the installation methods mentioned will create a copy of the OEM .inf file and install it in the driver repository. Since this OEM copy is not initially part of the driver repository, windows will display a prompt dialog and request user interaction to either force the driver to be installed or to cancel it. Subsequent driver installations are possible without any user interaction. Also, pre-installed drivers (see Pnputil -a) can be installed silently.

So this is my solution:

  • First, a device entry in HKLM \ System \ CurrentControlSet \ Enum \ Root is created with this equipment identifier as the device name (ms_bridge, ms_bridgemp) using SetupDiCreateDeviceInfo
  • Hardware ID assigned by SetupDiSetDeviceRegistryProperty
  • The list of drivers is built with this single .inf file using SetupDiSetDeviceInstallParams
  • Enumerating and preselecting a driver using SetupDiSetSelectedDriver
  • Registering a device using SetupDiCallClassInstaller(DIF_REGISTERDEVICE...)
  • Installation using DiInstallDevice

This is the full code:

 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; } 

Todo: Find a way to install these bridge drivers from % SystemRoot% \ inf without creating OEM copies and without any user interaction.

You can read / write access to the subversion repository at Sourceforge

Any additional information or suggestions for improvements are appreciated! All please feel free to check / change the code.

The main teams :

  • bridgeutil.exe / install
  • bridgeutil.exe / uninstall
  • bridgeutil.exe / attach
  • bridgeutil.exe / detach

<strong> Examples:

 bridgeutil.exe /attach "PCI\VEN_10EC&DEV_8169" /attach {5d624f94-8850-40c3-a3fa-a4fd2080baf3}\vwifimp 

Attaches each Realtek 8169 network interface card and Microsoft Virtual Wifi adapter to connect the bridge. If the bridge is not already installed, it will be installed first.

 bridgeutil.exe /detach 1 

Disconnects adapter ID 1 from the bridge.

To view a list of bridge adapters, simply call the bridgeutil.exe file without any arguments.

+2
source

In fact, you can create network bridges through the SetupAPI.
Using the DevCon tool, destroying them is as simple as that ...

 devcon.exe remove ms_bridgemp 

... while creating bridges can be done with this command:

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


DevCon is open source , so you can delve into the sources to find out how it implements these commands (DevCon Tool is essentially a CLI for SetupAPI),

Please note: the commands apply to Windows 7. This approach is assumed to work on XP, and I believe that it works with other versions of Windows, but the .INF file may have a different name or the device identifier may differ.

+3
source

After long unsuccessful searches on the Internet, I wrote and successfully used the following Windows Script Host Script "BridgeConnections.vbs" to create a network bridge in Windows XP (this method also works on Windows 7 and Windows 8 with a few changes). It can be launched from the command line or from a batch file as follows:

 C:\Temp> cscript BridgeConnections.vbs 

BridgeConnections.vbs File :

 ' 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 

Similarly, it would be possible to change the Script to the "Delete" bridge, if necessary (make one choice with Shift and go through the keys and send another keystroke command). In my case, I just need to combine all the available network adapters from the batch file so that the method described above works fine.

In my experience, the β€œsmall” problem with

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

posted here earlier is that it will create an empty "semi-secure" bridge without adapters. Thus, you still have to manually go to the Windows GUI and manually β€œadd” adapters one by one before it becomes really useful.

The only fully automatic solution that really works for me is the above script.

To perform the same actions from C ++ or C # code without Script, you will need to know and call the undocumented functions of Shell Network Interfaces (NETSHELL.DLL), which, in turn, are called by Explorer when the user initiates actions by selecting an element list and context menu in the Windows GUI. A C ++ sample for calling the shell in the Network Interface for programmatically disabling / enabling the network adapter can be seen here . Unfortunately, there is still no sample for creating / removing a network bridge adapter. Therefore, until it becomes available, I will stick with the script.

+3
source

Based on the binding example, I use the bindlink utility, which works as follows:

 Usage: bindbridge <deviceId> <bind|unbind> 

The source can be found at https://github.com/OurGrid/OurVirt/tree/master/tools/win32/bindbridge , and it is assumed that the bridge device already exists - which can be created using devcon, according to the previous answers - and its name ms_bridge , which can be easily changed in the sources.

I use it to programmatically add crane interfaces to the bridge, so my command line has something in the lines:

bindbridge ROOT\NET\0001 bind

+2
source

It turns out that, unfortunately, there is no documented way to configure the network bridge.

The code inside hnetcfg.dll is called only by Windows Explorer. It installs the bridge driver and configures the bridge interface.

You could call it yourself (using COM), but this will require reverse engineering and may disrupt any system update, so I recommend not to do this.

+1
source

Source: https://habr.com/ru/post/1490863/


All Articles