Что нового

[Сеть, интернет] Публичный IP через WMI

erlik

Продвинутый
Сообщения
317
Репутация
84
Нашел самый быстрый способ получить внешний IP (сравнивал с тремя найденными в AutoIT вариантами). Не зависит от доступности внешних web-ресурсов.
Правда, проверял пока только на XP.
В случае отсутствия соединения возвращает пустую строку.
Код:
Func _GetPublicIP()
Local $objWMIService, $oNetworkConfig, $sPublicIPAddress='', $Caption
    Switch @OsLang
	Case '0419'
	    $Caption='[00393219] Минипорт WAN (IP)'; для русской OS
	Case '0409'
	    $Caption='[00393219] Miniport WAN (IP)'; для английской OS
	Case Else
		Return SetError(1,-1, $sPublicIPAddress); а для прочих извиняйте - неизвестный язык
	EndSwitch
	$objWMIService = ObjGet('winmgmts:{impersonationLevel=impersonate}\\.\root\CIMV2')
    If Not IsObj($objWMIService) Then Return SetError(2,-1, $sPublicIPAddress)
	$oNetworkConfig= $objWMIService.ExecQuery("select IPAddress from Win32_NetworkAdapterConfiguration " & _
	"where IPEnabled=TRUE And Caption='" & $Caption & "'")
    If Not IsObj($oNetworkConfig) Then Return SetError(3,-1, $sPublicIPAddress)
	For $IPConfig In $oNetworkConfig
	    $sPublicIPAddress=$IPConfig.IPAddress(0)
	Next
    Return $sPublicIPAddress
EndFunc
 
Автор
E

erlik

Продвинутый
Сообщения
317
Репутация
84
CreatoR
Значит на Win 7 значение параметра caption похоже другое.
Проверьте в командной строке команду wmic nicconfig get caption - что выдает для всех сетевых интефейсов. Там у всех интерфейсов кроме активного соединения индексы идут по порядку от 1, а у активного PPoE должно быть отличное от них число.
Хотя может быть это критерий - caption - не абсолютный для выбора нужного WAN интерфейса. Тогда нужно искать другой критерий. Есть еще вариант по метрике выбирать нужный интерфейс.
Или попробовать вариант с перебором всей таблицы IP адресов:
Код:
Func GetPublicIP()
Local $objWMIService, $oNetworkConfig, $sPublicIPAddress='', $Caption
    Switch @OsLang
	Case '0419'
	    $Caption='[00393219] Минипорт WAN (IP)'; для русской OS
	Case '0409'
	    $Caption='[00393219] Miniport WAN (IP)'; для английской OS
	Case Else
		Return SetError(1,-1, $sPublicIPAddress); а для прочих извиняйте - неизвестный язык
	EndSwitch
	$objWMIService = ObjGet('winmgmts:{impersonationLevel=impersonate}\\.\root\CIMV2')
    If Not IsObj($objWMIService) Then Return SetError(2,-1, $sPublicIPAddress)
	$oNetworkConfig= $objWMIService.ExecQuery("select IPAddress from Win32_NetworkAdapterConfiguration where IPEnabled=TRUE And Caption='" & $Caption & "'")
    If Not IsObj($oNetworkConfig) Then Return SetError(3,-1, $sPublicIPAddress)
	For $IPConfig In $oNetworkConfig
	    For $i=0 to UBound($IPConfig.IPAddress)-1
		$sPublicIPAddress=$IPConfig.IPAddress($i)
		Next
    Next
    Return $sPublicIPAddress
EndFunc
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
erlik [?]
Значит на Win 7 значение параметра caption похоже другое.
У меня это [00000008] WAN Miniport (IP).
Сработало вот так:

Код:
ConsoleWrite(GetPublicIP() & @LF)

Func GetPublicIP()
	Local $objWMIService, $oNetworkConfig, $sPublicIPAddress = ''
	
	$objWMIService = ObjGet('winmgmts:{impersonationLevel=impersonate}\\.\root\CIMV2')
	If Not IsObj($objWMIService) Then Return SetError(2, -1, $sPublicIPAddress)
	$oNetworkConfig = $objWMIService.ExecQuery("select IPAddress from Win32_NetworkAdapterConfiguration where IPEnabled=TRUE")
	If Not IsObj($oNetworkConfig) Then Return SetError(3, -1, $sPublicIPAddress)
	
	For $IPConfig In $oNetworkConfig
		$sPublicIPAddress = $IPConfig.IPAddress(0)
	Next
	
	Return $sPublicIPAddress
EndFunc


но чем тогда оно отличается от @IPAddress2? :stars:
 
Автор
E

erlik

Продвинутый
Сообщения
317
Репутация
84
CreatoR
В данному случае ничем. Класс Wiin32_NetworkAdapterConfiguration возвращает в том числе и IP самого сетевого адаптера, то есть внутренний. Интерфейс под индексом 8 как раз к самой сетевой карте и относится(у меня, по крайней мере, так). Правда у меня там имя сетевого адаптера, а не WAN Miniport (IP). Видимо, у тебя выдаются данные твоего адаптера - при твоем варианте запроса. Либо само соединение у тебя через роутер (или еще как) идет. И тогда получается непонятно к какому интерфейсу обращаться, чтобы получить публичный IP.
Внешний IP нужно получать через WAN интерфейс - какой на Win 7 у него заголовок (Caption) нужно еще повыяснять.
----------------------------
Второй вариант - во втором посте тоже самое выдает?
 

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4,020
Репутация
626
erlik
если выход в интернет осуществляется через один или сеть роутеров, то исключительно средствами самой машины этот адрес не выцепить. относительно надежный способ, это запрос на сайты определения IP типа http://2ip.ru и потом парсить его ответ.
 
Автор
E

erlik

Продвинутый
Сообщения
317
Репутация
84
Kaster
если выход в интернет осуществляется через один или сеть роутеров, то исключительно средствами самой машины этот адрес не выцепить
Мне тоже такая мысль в голову пришла. Значит все таки с WMI облом. А жаль. :(
-----------------------------------------------------------------------------
Если кому интересно, то вот так получаем массив всех IP компа - и локальные IP и внешний. Какая инфа будет на компе который выходит в сеть через роутер - пока не знаю.

Код:
$aIP= _GetArrayIP()
ConsoleWrite(_ArrayDisplay($aIP))

Func _GetArrayIP()
Local $objWMIService, $oNetworkConfig, $aIP[1], $iCount=0
    $objWMIService = ObjGet('winmgmts:{impersonationLevel=impersonate}\\.\root\CIMV2')
    If Not IsObj($objWMIService) Then Return SetError(2,-1, $aIP)
	$oNetworkConfig= $objWMIService.ExecQuery("select IPAddress from Win32_NetworkAdapterConfiguration where IPEnabled=TRUE")
    If Not IsObj($oNetworkConfig) Then Return SetError(3,-1, $aIP)
	For $IPConfig In $oNetworkConfig
	    For $i=0 to UBound($IPConfig.IPAddress)-1
		ReDim $aIP[$iCount + 1]
        $aIP[$iCount]=$IPConfig.IPAddress($i)
		$iCount+=1
		Next
    Next
	Return $aIP
EndFunc
 

_dron_

Знающий
Сообщения
84
Репутация
8
Если Юзер сидит за роутерами (98% так как Ip на всех не хватит) то знать свой внешний IP бесполезно!!! А если нужно установить p2p соединение (как uTorrent или Skype) то нужно долбить stun и только через Udp сокет и держать открытым его, тогда будет создан Udp мост через все роутеры на время до 3 сек с последней передачи, а stun сервер вернет все данные! Что такое stun можно прочитать в http://ru.wikipedia.org/wiki/STUN ;D

и еще здесь ;D
http://www.autoitscript.com/forum/topic/161713-your-public-ip-stun-protocol/


Добавлено:
Сообщение автоматически объединено:

Вот вам вдогонку 4 функции для конвертации big-engine чисел в little-engine и наоборот :smile:
Мое творение ;D


Добавлено:
Сообщение автоматически объединено:


Код:
#include-once

;====================================================================================================================
; Author ........: _dron_
;uint32_t htonl(uint32_t hostlong);long little-engine to big-engine
;uint16_t htons(uint16_t hostshort);short little-engine to big-engine
;uint32_t ntohl(uint32_t netlong);long big-engine to little-engine 
;uint16_t ntohs(uint16_t netshort);short big-engine to little-engine
; ===============================================================================================================================

OnAutoItExitRegister("__Close_handle_Ws2_32")

Global $__hWs2_32 = DllOpen("Ws2_32.dll")

;uint32_t htonl(uint32_t hostlong); — конвертирует 32-битную беззнаковую величину из локального порядка байтов в сетевой парядок байт;
Func htonl($hostlong)
    Local $iResult = DllCall($__hWs2_32,"ulong","htonl","ulong",$hostlong)
    If @error Then Return SetError(@error, @extended, -1)
    Return __NormalizeInt($iResult[0])
EndFunc

;uint16_t htons(uint16_t hostshort); — конвертирует 16-битную беззнаковую величину из локального порядка байтов в сетевой парядок байт;
Func htons($hostshort)
    Local $iResult = DllCall($__hWs2_32,"ushort","htons","ushort",$hostshort)
    If @error Then Return SetError(@error, @extended, -1)
    Return __NormalizeShort($iResult[0])
EndFunc

;uint32_t ntohl(uint32_t netlong); — конвертирует 32-битную беззнаковую величину из сетевого порядка байтов в локальный парядок байт;
Func ntohl($netlong)
    Local $iResult = DllCall($__hWs2_32,"ulong","ntohl","ulong",$netlong)
    If @error Then Return SetError(@error, @extended, -1)
    Return __NormalizeInt($iResult[0])
EndFunc

;uint16_t ntohs(uint16_t netshort); — конвертирует 16-битную беззнаковую величину из сетевого порядка байтов в локальный парядок байт;
Func ntohs($netshort)
    Local $iResult = DllCall($__hWs2_32,"ushort","ntohs","ushort",$netshort)
    If @error Then Return SetError(@error, @extended, -1)
    Return __NormalizeShort($iResult[0])
EndFunc

;Приводит значение к нормальному виду обрубая последнии байты
Func __NormalizeInt($long)
	$result = BitAND($long,0xffffffff)
	return int($result,1)
EndFunc

;Приводит значение к нормальному виду обрубая последнии байты
Func __NormalizeShort($short)
	$result = BitAND($short,0xffff)
	return $result
EndFunc

Func __Close_handle_Ws2_32()
	DllClose($__hWs2_32)
EndFunc
 

Вложения

  • Big2little.au3
    1.5 КБ · Просмотры: 6

C2H5OH

AutoIT Гуру
Сообщения
1,473
Репутация
333
OffTopic:

_dron_

Что ты влез со своими числами? Ты название темы видел? Ты правила курил?

и ещё покури здесь по поводу "конверКтации" и "наобороДа"
http://www.rusgram.narod.ru/
 
Верх