#c# #.net #asp.net #vb.net #vb6
#c# #.net #asp.net #vb.net #vb6
Вопрос:
Если вы зайдете в меню Пуск и щелкните Компьютер, а затем щелкните ссылку Сеть с левой стороны, вы увидите с правой стороны несколько категорий, одна из которых называется «Сетевая инфраструктура», в этой категории указан мой маршрутизатор, и в моем случае это "LINKSYS WAG160N Wireless-N ADSL2 Gateway"
и когда вы щелкаете правой кнопкой мыши и выбираете свойства, там отображается основная информация, такая как IP-адрес внутреннего / шлюза, у меня это "192.168.1.1"
Я хотел бы знать, как получить эту информацию в коде, предпочтительно с помощью Windows API, чтобы я мог вызвать его с помощью устаревшего приложения VB6. Кроме того, даже если вы просто знаете версию .NET или версию Delphi, пожалуйста, перечислите это, так как я могу кодировать на обоих. Однако ответ, который я в конечном итоге ищу, — это способ доступа к этому через VB6, так что, вероятно, это будет вызов WinAPI, однако, другие методы также приветствуются на случай, если я не могу найти устаревший метод.
Ответ №1:
Требуется немного больше кода, чем хотелось бы. Если есть более компактный подход, мне было бы интересно самому.
Насколько я понимаю, Windows получает информацию через UPnP. UPnP работает как своего рода веб-сервис поверх UDP. У него есть особенности, потому что он использует многоадресные рассылки UDP, поэтому его может быть сложно явно закодировать, но Windows предлагает вспомогательную библиотеку. Эта библиотека плохо «упакована» для использования в программе VB6, но с помощью нескольких хитростей вы можете получить доступ к большей части ее функциональности.
Приведенный ниже пример написан так, что его можно скомпилировать как в Win XP, так и в более поздних версиях Windows. В версии библиотеки для Win XP отсутствует важная информация о типе, которая не позволяет VB6 использовать все, что она предлагает. Это было исправлено в Vista, однако для этого приложения нам не нужны все возможности обратного вызова, которые оно предлагает. Вы могли бы использовать внешний typelib, если вам нужен полный доступ, или вы можете скомпилировать в Vista или более поздней версии. Программа, скомпилированная в Vista, отлично работает в XP.
Приведенный ниже код абстрагирован от более крупного класса, который я использую для сопоставления портов UPnP NAT на серверах VB6. Это подмножество может выполнять то, что вам требуется.
UPnPNAT.cls
Option Explicit
'Requires reference to:
'
' UPnP 1.0 Type Library (Control Point)
'
Private Const CONN_SVCTYPEID_URI As String = "urn:schemas-upnp-org:service:WANIPConnection:1"
Private Const CONN_ID_URI As String = "urn:upnp-org:serviceId:WANIPConn1"
Private UDFinder As UPNPLib.UPnPDeviceFinder
Private WithEvents UNCBs As UPnPNATCBs
Private findData As Long
Private blnSuccess As Boolean
Public Event Result(ByVal Success As Boolean, ByVal FriendlyName As String, ByVal IP As String)
Public Sub Fetch()
blnSuccess = False
Set UDFinder = New UPNPLib.UPnPDeviceFinder
Set UNCBs = New UPnPNATCBs
findData = CallByName(UDFinder, "CreateAsyncFind", VbMethod, CONN_SVCTYPEID_URI, 0, UNCBs)
UDFinder.StartAsyncFind findData
End Sub
Private Sub UNCBs_DeviceAdded(ByVal Device As UPNPLib.IUPnPDevice)
Dim Services As UPNPLib.UPnPServices
Dim Service As UPNPLib.UPnPService
Dim varInActionArgs, varOutActionArgs
Dim strFriendlyName As String
Dim strIP As String
strFriendlyName = Device.FriendlyName
On Error Resume Next
Set Services = Device.Services
If Err.Number = 0 Then
On Error GoTo 0
With Services
If .Count > 0 Then
On Error Resume Next
Set Service = .Item(CONN_ID_URI)
If Err.Number = 0 Then
On Error GoTo 0
ReDim varInActionArgs(0 To 0)
ReDim varOutActionArgs(0 To 0)
Service.InvokeAction "GetExternalIPAddress", _
varInActionArgs, _
varOutActionArgs
strIP = varOutActionArgs(0)
blnSuccess = True
Else
On Error GoTo 0
End If
End If
End With
Else
On Error GoTo 0
End If
UDFinder.CancelAsyncFind findData
RaiseEvent Result(blnSuccess, strFriendlyName, strIP)
Set UDFinder = Nothing
Set UNCBs = Nothing
End Sub
Private Sub UNCBs_SearchComplete()
If Not blnSuccess Then
RaiseEvent Result(False, "", "")
End If
End Sub
UPnPNATCBs.cls
Option Explicit
Public Event DeviceAdded(ByVal Device As UPNPLib.IUPnPDevice)
Public Event DeviceRemoved(ByVal UDN As String)
Public Event SearchComplete()
Public Sub IDispatchCallback( _
ByVal pDevice As Variant, _
ByVal bstrUDN As Variant, _
ByVal lType As Variant)
'NOTE: Must be dispID = 0, i.e. the default method of the class.
Select Case lType
Case 0
RaiseEvent DeviceAdded(pDevice)
Case 1
RaiseEvent DeviceRemoved(bstrUDN)
Case 2
RaiseEvent SearchComplete
End Select
End Sub
Form1.frm
Option Explicit
Private WithEvents UN As UPnPNAT
Private Sub Form_Load()
Set UN = New UPnPNAT
lblStatus.Caption = "Searching..."
UN.Fetch
End Sub
Private Sub UN_Result(ByVal Success As Boolean, ByVal FriendlyName As String, ByVal IP As String)
If Success Then
lblStatus.Caption = FriendlyName amp; " " amp; IP
Else
lblStatus.Caption = "Failed"
End If
End Sub
Возможно, вам придется немного изменить это, если у вас есть несколько устройств UPnP, обеспечивающих подключения в вашей сети.
Комментарии:
1. Я знал, что он старый, но не могли бы вы, пожалуйста, пролить свет на меня: почему этот код не обнаруживает более 1 сетевого адаптера (на моем КОМПЬЮТЕРЕ более 1 сетевой карты)?
2. Он запускает поиск
service:WANIPConnection:1
, но я полагаю, его можно было бы изменить для поиска по всем службам и перечисления подключений WANIP.3. @Bob77: Я изменил на ‘service: WANIPConnection: 2’, но результат был «сбой». Оба моих сетевых адаптера подключаются к двум разным маршрутизаторам, которые также имеют «upnp-enabled»?
4. Возможно, вам придется написать тестовую программу, которая перечисляет все, чтобы выяснить структуру, используемую на многосетевой машине. Как только вы разработаете шаблон, вы сможете увидеть, что нужно сделать, чтобы получить именно те результаты, которые вы хотите.
Ответ №2:
Вы могли бы попробовать захватить выходные данные команды «печать маршрута -4» и проанализировать ее для маршрута по умолчанию. Если вы используете IPv6, измените -4 на -6.
Ответ №3:
if (!NetworkInterface.GetIsNetworkAvailable())
return "Not connected.";
var networkDevices = NetworkInterface.GetAllNetworkInterfaces();
if (networkDevices.Length == 0)
return "No network devices.";
networkDevices = networkDevices
.Where(n => n.OperationalStatus == OperationalStatus.Up
|| n.OperationalStatus == OperationalStatus.Dormant)
.ToArray();
if (networkDevices.Length == 0)
return "Network not connected.";
networkDevices = networkDevices
.Where(n => n.Supports(NetworkInterfaceComponent.IPv4))
.ToArray();
if (networkDevices.Length == 0)
return "No IPv4 network found.";
var router = networkDevices.First().GetIPProperties()
.GatewayAddresses.First();
var routerIp = router.Address.ToString();
Ответ №4:
Комментарии:
1. спасибо, приятель, но как мне определить, какой из них является маршрутизатором, с которого пользователь получает подключение к Интернету? потому что я помню, что иногда там есть и другие вещи, которые не являются маршрутизаторами, предоставляющими доступ в Интернет (именно это я ищу) …?
2. также, просто чтобы добавить, я прошелся по объектам NetworkInterface в vs2010, и он показал такие вещи, как bluetooth, моя беспроводная карта и т.д. И тому подобное. ни один из них не показал ничего из того, что мне было нужно (маршрутизатор), а именно «LINKSYS WAG160N Wireless-N ADSL2 Gateway» — есть идеи? какой объект я должен вызывать для этого?
Ответ №5:
подключитесь к веб-странице http:[ip]. Заголовок этой веб-страницы в качестве имени устройства (модели устройства). Это работает с устройствами, которые отображают страницу входа в систему. Если устройство хочет получить имя пользователя и пароль вместе с запросом, возникает исключение WebException, и вы можете прочитать исключение WebException.Ответ.Заголовки[«WWW-Authenticate»], которые содержат строку: Basic realm=»X», где X — строка, описывающая устройство.
private string GetDeviceName(string ip)
{
WebClient myWebClient = new WebClient(1000);
try
{
System.IO.Stream s = myWebClient.OpenRead("http://" ip);
var sr = new System.IO.StreamReader(s);
while (!sr.EndOfStream)
{
var L = sr.ReadLine();
var sb = new StringBuilder();
var st = 0;
var end = 0;
if ((st = L.ToLower().IndexOf("<title>")) != -1)
{
sb.Append(L);
while ((end = L.ToLower().IndexOf("</title>")) == -1)
{
L = sr.ReadLine();
sb.Append(L);
}
sr.Close();
s.Close();
myWebClient.Dispose();
var title = sb.ToString().Substring(st 7, end - st - 7);
Regex r = new Regex("amp;#[^;] ;");
title = r.Replace(title, delegate (Match match)
{
string value = match.Value.ToString().Replace("amp;#", "").Replace(";", "");
int asciiCode;
if (int.TryParse(value, out asciiCode))
return Convert.ToChar(asciiCode).ToString();
else
return value;
});
return $"Router/AP ({title})";
}
}
sr.Close();
s.Close();
myWebClient.Dispose();
}
catch (System.Net.WebException ex)
{
var response = ex.Response as HttpWebResponse;
if (response == null)
return "";
var name = response.Headers?["WWW-Authenticate"]?.Substring(12).Trim('"');
myWebClient.Dispose();
return name;
}
return "";
}