Windows 7 でネットワーク ブリッジをプログラムで作成および破棄しようとしています。
技術的には、.Net 4 領域内にとどまりたいと思っています (PInvokes は問題ありません) が、C++ を使用することもオプションです。
これまでの私の調査では、構成のためにnetsh
-commands が行くべきルートであることが判明しました。しかし、実際に彼らと新しい橋を紡ぐという選択肢はないようです。
私は現在、API を使用するこのプログラムを調査してINetCfg
いますが、プログラム、またはより具体的には API が (再び) 新しいブリッジを構築できないようです。
誰でも問題の解決に貢献できる場合は、どんな種類の助けも大歓迎です。
[更新:] newtork ブリッジは、両方のデバイスにバインドするドライバーを使用して実装されているようです。私はまだその情報を十分に活用できていません。
5 に答える
ブリッジ サービスとブリッジ アダプタードライバーの両方で機能するソリューションを見つけました。私はdevconUpdateDriverForPlugAndPlayDevices
のようには使用しませんが、代わりに使用しています。DiInstallDevice
ただし、非対話モード (ユーザーの操作なし) で初めてドライバーをインストールすることはできません。これは、組み込みのブリッジ.infファイルに対応する.catファイルがないためです。.infファイルが既に%SystemRoot%\infに含まれていて、まだ%SystemRoot%\System32\DriverStoreに含まれていない場合、ドライバーの手動インストールを意図したものでもありません。UpdateDriverForPlugAndPlayDevices
DiInstallDevice
DiInstallDriver
ファイルは、%SystemRoot%\inf などのシステムの場所ではなく、配布メディアまたはベンダーが作成したディレクトリにある必要があります。
上記のすべてのインストール方法では、 .infファイルの OEM コピーが作成され、ドライバー ストアにインストールされます。この OEM コピーは最初はドライバー ストアの一部ではないため、ウィンドウにプロンプト ダイアログが表示され、ドライバーを強制的にインストールするかキャンセルするかのユーザー操作が求められます。ちなみに、その後のドライバーのインストールは、ユーザーの操作なしで可能です。また、プリインストールされたドライバー (pnputil -a を参照) は、非対話モードでインストールできます。
これが私の解決策です:
- 最初に、HKLM\System\CurrentControlSet\Enum\Rootのデバイス エントリが、指定されたハードウェア ID をデバイス名 (ms_bridge、ms_bridgemp) として作成されます。
SetupDiCreateDeviceInfo
- ハードウェア ID が割り当てられます
SetupDiSetDeviceRegistryProperty
- ドライバー リストは、指定された単一の.infファイルによって正確に構築されます。
SetupDiSetDeviceInstallParams
- ドライバーの列挙と事前選択
SetupDiSetSelectedDriver
- でデバイスを登録しています
SetupDiCallClassInstaller(DIF_REGISTERDEVICE...)
- でインストール
DiInstallDevice
これは完全なコードです:
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's : このブリッジ ドライバーを%SystemRoot%\inf内からOEM コピーを作成せず、ユーザーの操作なしでインストールする方法を見つけてください。
Sourceforgeで Subversion リポジトリへの読み取り/書き込みアクセスを取得できます
改善のための追加情報や提案をいただければ幸いです。どなたでもお気軽にコードをチェックアウト/変更してください。
基本的なコマンド:
- bridgeutil.exe /インストール
- bridgeutil.exe /アンインストール
- bridgeutil.exe /アタッチ
- bridgeutil.exe /デタッチ
例:
bridgeutil.exe /attach "PCI\VEN_10EC&DEV_8169" /attach {5d624f94-8850-40c3-a3fa-a4fd2080baf3}\vwifimp
各 Realtek 8169 Network Interface Cards と Microsoft Virtual Wifi Adapter をブリッジに接続します。ブリッジがまだインストールされていない場合は、最初にインストールされます。
bridgeutil.exe /detach 1
ID 1 のアダプターをブリッジから切り離します。
ブリッジ可能なアダプターのリストを表示するには、引数を指定せずに bridgeutil.exe を呼び出します。
bindview の例に基づいて、次のように機能する bindbridge というユーティリティを作成しました。
Usage: bindbridge <deviceId> <bind|unbind>
ソースはhttps://github.com/OurGrid/OurVirt/tree/master/tools/win32/bindbridgeで見つけることができ、ブリッジデバイスが既に存在すると想定しています-これは、以前の回答に従ってdevconで作成できます-およびその名前はms_bridgeで、ソースで簡単に変更できます。
私はこれを使用してプログラムでタップ インターフェイスをブリッジに追加しているので、コマンド ラインは次のようなものです。
bindbridge ROOT\NET\0001 bind
残念ながら、ネットワーク ブリッジを設定する方法が文書化されていないことが判明しました。
これを行うコードはhnetcfg.dll内にあり、Windows Explorer によってのみ呼び出されます。ブリッジ ドライバをインストールし、ブリッジ インターフェイスを構成します。
(COM を使用して) 自分で呼び出すことは可能かもしれませんが、それにはリバース エンジニアリングが必要であり、システムの更新時に壊れる可能性があるため、そうしないことをお勧めします。