Программно отключить / включить сетевой интерфейс
Я пытаюсь найти решение для программного включения / выключения сетевой карты - я провел массу исследований, и ничто не кажется работоспособным решением как в средах XP, так и в Vista. Я говорю о том, что если вы зашли в панель управления "Сетевые подключения", щелкнули по ней правой кнопкой мыши и выбрали "включить" или "отключить". В идеале я хотел бы использовать библиотеку, но если хуже станет хуже, я предположил, что могу обратиться к приложению командной строки, но это абсолютно худший случай. Вот что я пробовал до сих пор и где / почему они потерпели неудачу:
Этот предыдущий пост:
Как программно включить / отключить сетевые интерфейсы? (Windows XP)
Перечисляет несколько методов - первый использует netsh, что похоже на использование функции IPHelper SetIfEntry(). Проблема в том, что он устанавливает интерфейс как включенный или отключенный административно, а не как включенный / отключенный обычным образом, поэтому он фактически не закрывает сетевой адаптер.
Другое предлагаемое решение заключается в использовании WMI и, в частности, класса Win32_NetworkAdapter, который имеет метод Enable и Disable:
http://msdn.microsoft.com/en-us/library/aa394216(VS.85).aspx
Отлично верно? Работает нормально в Vista, эти методы не существуют в обычной установке XP...
Другое предложение заключается в использовании DevCon, который действительно использует SetupAPI, в частности SetupDiSetClassInstallParams() с DICS_ENABLE. Проведя бесчисленные часы с этим замечательным классом и попытавшись отключить / включить устройство как на глобальном уровне, так и на определенном уровне конфигурации (и каждой комбинации), оно также не всегда работает стабильно - иногда работает нормально, но иногда отключение устройства в диспетчере устройств, но при этом оставление его работоспособным в сетевых подключениях.
Затем я попытался использовать интерфейс INetConnection, в частности INetConnection-> Connect / Disconnect:
http://msdn.microsoft.com/en-us/library/aa365084(VS.85).aspx
Но я так и не смог добиться того, чтобы это оказало какое-либо влияние на соединения в моих тестовых системах Vista или XP.
Наконец, я нашел этот C# скрипт с именем ToggleNic:
http://channel9.msdn.com/playground/Sandbox/154712/
Похоже, что он как-то проходит через Shell, чтобы эффективно вызывать поведение правой кнопки мыши. Ограничение (по крайней мере, в этой реализации) состоит в том, что он не работает (без модификации) на неанглийских системах, с которыми мне нужно работать. Если честно, это решение выглядит наиболее жизнеспособным, но мое знакомство с C# низкое, и я не смог найти, доступен ли API, который он использует, в C++.
Будем весьма благодарны за любую помощь или идеи - или за идеи о том, как выполнить то, что делает скрипт togglenic в C++. Спасибо!
7 ответов
После тестирования на большем количестве платформ и новых подходов я в основном отказался от этой функции (по крайней мере, для моих целей). Проблема для меня в том, что я хочу иметь что-то, что работает в 90%+ ситуаций, и реальность такова, что со всем, что я могу придумать, это ближе к 70%. Ирония заключается в том, что на самом деле все так же плохо при обычном методе Windows. Для тех, кто все еще хочет пойти по этому опасному пути, вот что я нашел:
Из методов прямого API, описанных выше, наиболее последовательно работающий использовал SetupAPI (SetupDiSetClassInstallParams) - самая большая проблема, с которой я столкнулся, заключается в том, что иногда он попадает в состояние, когда требуется перезагрузка, и никаких изменений не происходит. работать, пока это не произошло. Единственное, о чем следует помнить при его использовании, - это наличие двух профилей для устройств, поэтому в некоторых случаях вам необходимо переключать их оба. В DDK содержится исходный код инструмента devcon, который показывает, как именно все делать. В конечном итоге это выглядело так, как будто это было самое близкое к щелчку правой кнопкой мыши, но все же демонстрировалось странное поведение, которого не было у сетевых подключений. Этот подход, казалось, работал около 70% времени (как в тестах, так и в тестовых системах).
Из общего подхода к взлому, лучшее, что я обнаружил, - это не использовать технику, которую использовал ToggleNIC, а вместо этого использовать материал IShellFolder - это позволяет вам использовать GetCommandString, которая не зависит от языка. Проблема в том, что под XP GetCommandString ничего не возвращает (о, радость), но казалось, что идентификаторы меню для 'enable' и 'disable' были согласованы (16 и 17 соответственно), поэтому, если мне не удалось получить GetCommandString Я просто вернулся к идентификаторам меню. Чтобы переключить, просто вызовите InvokeCommand со строкой, если она вернула, или с идентификатором меню, если это не так. Проблема с этим заключалась в том, что, как и в обычном Windows-режиме, иногда он не работает и не дает никаких сведений о том, что происходит или почему он потерпел неудачу. Этот подход, похоже, тоже работал примерно в 70% случаев, но было гораздо сложнее сказать, если что-то пошло не так, плюс выскочил обычный текст "Включающий интерфейс...".
Надеюсь, это поможет кому-то еще - и если кому-то удастся найти другой способ, который работает в большем количестве ситуаций, я хотел бы услышать это!
ManagementClass managementClass = new ManagementClass("Win32_NetworkAdapter");
ManagementObjectCollection mgmtObjectColl = managementClass.GetInstances();
ManagementObject myObject = null;
foreach (ManagementObject mgmtObject in mgmtObjectColl)
{
if (mgmtObject["NetConnectionID"] != null && mgmtObject["NetConnectionID"].Equals("Local Area Connection"))
{
Console.WriteLine("found");
myObject = mgmtObject;
object result = mgmtObject.InvokeMethod("Disable", null);
}
//Console.WriteLine("{0}, {1}", mgmtObject["Name"], mgmtObject["NetConnectionID"]);
}
object result3 = myObject.InvokeMethod("Enable", null);
'==========================================================================
' NAME: 1unconnectedNIC.vbs
'
' COMMENT: This file will disable and rename the unconnected NIC on the
' local server.
'
' Usage:
' cscript 1unconnectedNIC.vbs
' Alex John
'==========================================================================
strComputer = "."
Set objShell = CreateObject("WScript.Shell")
Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set colAdapters = objWMIService.ExecQuery("SELECT * FROM Win32_NetworkAdapter where NetConnectionStatus = '7'" )
'For every adapter that is disconnected (has a red X by it)
For Each objAdapter in colAdapters
Wscript.Echo "Net Connection ID: " & objAdapter.NetConnectionID
Wscript.Echo "....Disabling NIC"
'Disable the NIC
objShell.Run "netsh interface set interface name=" & chr(34) & objAdapter.NetConnectionID & chr(34) & " admin=disabled", 0, true
Wscript.Echo "....NIC Disabled"
WScript.Sleep 10000
'Rename the NIC
Wscript.Echo "....Renaming NIC to 'Not Used'"
objShell.Run "netsh interface set interface name=" & chr(34) & objAdapter.NetConnectionID & chr(34) & " newname=" & chr(34) & "Not Used" & n & chr(34), 0, true
Next
Wscript.Echo "Finished"
После долгих поисков я начал копаться в DEVCON. Поняв, что эти методы должны быть привязаны, я немного поискал и нашел это: http://www.codeproject.com/KB/cs/HardwareHelper.aspx
Это помогло решить мою проблему включения и отключения адаптера TAP из OpenVPN как минимум.
Попробуйте C++- код "Сетевые интерфейсы оболочки" здесь. Это должно работать под XP и выше.
Нашел это решение, которое в основном автоматизирует щелчок правой кнопкой мыши: http://www.wilderssecurity.com/showthread.php?t=265836 Работает как в Windows XP, так и в Windows 7
Существует также один, написанный Novell, который является надстройкой над DevCon: http://www.novell.com/communities/node/2338/network-configuration-command-line-control
ToggleNic использует Shell32 через COM. В c этим используются стандартные библиотеки "SHLOBJ.H", "SHELLAPI.H" и класс IShellDispatch.