Тема: AHK: Оповещание об отключении/появлении интернета
Тема для обсуждения "Оповещание об отключении/появлении интернета".
http://forum.script-coding.com/viewtopi … 71#p157071
Вы не вошли. Пожалуйста, войдите или зарегистрируйтесь.
Страницы 1
Чтобы отправить ответ, вы должны войти или зарегистрироваться
Тема для обсуждения "Оповещание об отключении/появлении интернета".
http://forum.script-coding.com/viewtopi … 71#p157071
А какой именно интернет имеется в виду? Я подключен провайдером к большой локальной сети, у которой может быть выход в глобальный интернет, а может не быть в случае неполадок. Будет ли в последнем варианте считаться, что я подключен к интернету?
Ещё при запуске хорошо бы знать, есть интернет, или нет.
Тут надо проверять.
В msdn об этом мутно написано.
https://learn.microsoft.com/en-us/windo … agerevents
Судя по описанию флагов должен определять именно наличие интернета.
NLM_CONNECTIVITY_IPV4_INTERNET
Value: 0x40
There is connectivity to the Internet using the IPv4 protocol.NLM_CONNECTIVITY_IPV6_INTERNET
Value: 0x400
There is connectivity to the Internet using the IPv6 protocol.
https://learn.microsoft.com/en-us/windo … nnectivity
При запуске статус интернета определяется в колбеке:
if (NetworkListManager.GetConnectivity & 0x40) or (NetworkListManager.GetConnectivity & 0x400) ; NLM_CONNECTIVITY_IPV4_INTERNET or NLM_CONNECTIVITY_IPV6_INTERNET
InternetExist := 1
else
InternetExist := 0
Можно туда добавить msgbox.
Тут надо проверять
Как в следующий раз отключат, проверю.
А ты не собираешься на v2 переходить? Там с новым синтаксисом с ком-интерфейсами более внятно получается, вроде.
Меня пока останавливают 2 момента:
1) Малое количество библиотек для ahk v2.
2) Незаконченные скрипты на ahk v1.
Так что, наверное, если и перейду, то нескоро.
Убрал получение статуса интернета при запуске скрипта из колбека.
Понадобилось для реального проекта, спасибо, использовал твою наработку.
Как в следующий раз отключат, проверю.
Сработало, по крайней мере в том конкретном случае.
objrelease(pSink)
Здесь у тебя освобождается память буфера, но не освобождается для каждого RegisterCallback(). Вроде не обязательно создавать буфер через GlobalAlloc(), работает и просто с VarSetCapacity().
Сделал вариант под v2:
#Requires AutoHotkey v2
Persistent
ConnectionWatcher := INetworkListManagerEvents(WatchInternetConnection)
WatchInternetConnection(ConnectionWatcher.IsConnection)
WatchInternetConnection(isConnection) { ; when the internet goes down, a notification appears
static wnd := '', ExStyles := (WS_EX_NOACTIVATE := 0x8000000) | (WS_EX_TRANSPARENT := 0x00000020)
if !wnd {
wnd := Gui('+LastFound -Caption +AlwaysOnTop +Owner +E' . ExStyles)
WinSetTransparent 210
wnd.BackColor := 'Red'
wnd.SetFont('s20', 'Calibri')
wnd.MarginX := wnd.MarginY := 20
wnd.AddText(, 'No Internet connection!')
}
wnd.%isConnection ? 'Hide' : 'Show'%(isConnection ? unset : 'NA y0')
}
class INetworkListManagerEvents
{
ipv4 := NLM_CONNECTIVITY_IPV4_INTERNET := 0x0040
ipv6 := NLM_CONNECTIVITY_IPV6_INTERNET := 0x0400
CLSID_NetworkListManager := '{DCB00C01-570F-4A9B-8D69-199FDBA5723B}'
IID_INetworkListManagerEvents := '{DCB00001-570F-4A9B-8D69-199FDBA5723B}'
IID_IConnectionPointContainer := '{B196B284-BAB4-101A-B69C-00AA00341D07}'
IID_IUnknown := '{00000000-0000-0000-C000-000000000046}'
__New(callback) {
this.callback := callback
this.CreateVTable()
this.NetworkListManager := ComObject(this.CLSID_NetworkListManager)
IConnectionPointContainer := ComObjQuery(this.NetworkListManager, this.IID_IConnectionPointContainer)
DllCall('Ole32\CLSIDFromString', 'Str', this.IID_INetworkListManagerEvents, 'Ptr', CLSID := Buffer(16))
ComCall(FindConnectionPoint := 4, IConnectionPointContainer, 'Ptr', CLSID,
'PtrP', IConnectionPoint := ComValue(VT_UNKNOWN := 0xD, pIConnectionPoint := 0))
ComCall(Advise := 5, IConnectionPoint, 'Ptr', this.vtable.ptr, 'UIntP', &cookie := 0)
this.IConnectionPoint := IConnectionPoint, this.cookie := cookie
}
IsConnection => ( NLM_CONNECTIVITY := this.NetworkListManager.GetConnectivity(),
NLM_CONNECTIVITY & this.ipv4) || (NLM_CONNECTIVITY & this.ipv6 )
CreateVTable() {
static S_OK := 0
, Methods := [{name: 'QueryInterface' , paramCount: 3},
{name: 'AddRef' , paramCount: 1},
{name: 'Release' , paramCount: 1},
{name: 'ConnectivityChanged', paramCount: 2}]
this.vtable := Buffer(A_PtrSize * (Methods.Length + 1))
NumPut('Ptr', this.vtable.Ptr + A_PtrSize, this.vtable)
for k, v in Methods {
NumPut('Ptr', CallbackCreate(%v.name%, 'F', v.paramCount), this.vtable, A_PtrSize * k)
}
QueryInterface(self, riid, pObj) {
DllCall('Ole32\StringFromGUID2', 'Ptr', riid, 'Ptr', buf := Buffer(78), 'Int', 39)
str := StrGet(buf)
if !(str = this.IID_IUnknown || str = this.IID_INetworkListManagerEvents)
return E_NOINTERFACE := 0x80004002
else {
NumPut('Ptr', self, pObj)
return S_OK
}
}
AddRef(self) => 1
Release(self) => 1
ConnectivityChanged(self, NLM_CONNECTIVITY) {
isInternetConnection := (NLM_CONNECTIVITY & this.ipv4) || (NLM_CONNECTIVITY & this.ipv6)
SetTimer this.callback.Bind(isInternetConnection), -10
return S_OK
}
}
__Delete() {
ComCall(Unadvise := 6, this.IConnectionPoint, 'UInt', this.cookie)
this.IConnectionPoint := ''
Loop 4 {
CallbackFree NumGet(this.vtable, A_PtrSize * A_Index, 'Ptr')
}
}
}
Здесь у тебя освобождается память буфера, но не освобождается для каждого RegisterCallback().
А разве это необходимо делать?
В справке явно об этом не написано.
Each use of RegisterCallback() allocates a small amount of memory (32 bytes plus system overhead). Since the OS frees this memory automatically when the script exits, any script that allocates a small, fixed number of callbacks does not have to explicitly free the memory. By contrast, a script that calls RegisterCallback() an indefinite/unlimited number of times should explicitly call the following on any unused callbacks:
DllCall("GlobalFree", "Ptr", Address, "Ptr")
Ну, так-то можно и после GlobalAlloc не вызывать.
Если ты про это:
else if (A_EventInfo = 2)
{
if (refCount > 0)
{
refCount--
if (refCount = 0)
DllCall("GlobalFree", "ptr", this, "ptr")
}
return refCount
}
то, думаю, можно смело не вызывать и не посчитывать refcount.
Добавил твою версию для ahk v2 в пост со скриптом.
думаю, можно смело не вызывать и не посчитывать refcount.
Ну да. Это если весь код вызывается только один раз при запуске скрипта. Если может вызываться несколько раз, тогда лучше освобождать ресурсы.
Не сильно вникал в код, просто хочу узнать, почему он такой мудрёный? Типа скрипт спрашивает у Windows о наличии интернета? Мне казалось, что всё проще: пингуем несколько стабильных популярных сайтов (или пытаемся скачать с них веб-страницу при помощи UrlDownloadToFile); если все отзываются - значит интернет есть; если все не отзываются - значит интернета нет. Если отзываются, но не все - значит "интернет работает частично".
Скрипт не спрашивает у виндовса.
Скрипт подписывается на уведомления от виндовса.
пингуем несколько стабильных популярных сайтов (или пытаемся скачать с них веб-страницу при помощи UrlDownloadToFile)
Представь, что скрипт ожидает каких-то сообщений из сети. Как понять, нет сообщений, потому что интернета нет, или потому, что ещё не пришли?
Скрипт подписывается на уведомления от виндовса.
А это надёжный способ узнавать об отключении/появлении интернета?
Представь, что скрипт ожидает каких-то сообщений из сети. Как понять, нет сообщений, потому что интернета нет, или потому, что ещё не пришли?
Если все популярные сайты доступны, но сообщений нет, значит сообщений нет по причине того, что они не пришли. Если же хоть один популярный сайт недоступен, значит с высокой степенью вероятности проблемы у моего местного (или у магистрального) интернет-провайдера (проще говоря, сообщений нет из-за того, что "интернет поломался").
А это надёжный способ узнавать об отключении/появлении интернета?
Это официальное апи, поэтому, думаю, да.
https://learn.microsoft.com/en-us/previ … -windows-7
Мне встречалось, что Windows 7 (или даже Windows XP) при подключении к сети, в которой IP-адреса раздаёт роутер, вылезало сообщение в трее что-то типа "интернет есть" или "Найдено подключение к интернету". Хотя в WAN-порт роутера вообще не было ничего подключено. Либо туда был воткнуть провод, в котором не было интернета. Поэтому я не доверяю Windows в этом плане.
Ну вы можете, если не лень, потестировать скрипт и опубликовать здесь результаты теста.
Писать готовый скрипт я не хочу, всего лишь подал идею. Autohotkey, насколько помню, умеет STDIN-STDOUT, следовательно она может запустить в фоне команду ping, получить результат её работы, и по результатам оценить, работает ли интернет или поломался.
Если все популярные сайты доступны
То-есть, придётся пинговать "популярные сайты" постоянно?
Писать готовый скрипт я не хочу, всего лишь подал идею
Я имел в виду потестировать скрипт, обсуждаемый в этом топике.
teadrinker, ну да, пинговать, либо UrlDownloadToFile каждые, N секунд.
Malcev, я в принципе не доверяю такого рода уведомлениям от виндовса.
ну да, пинговать, либо UrlDownloadToFile каждые, N секунд.
Ну, а не проще ли подписаться на события отключения/подключения интернета, и не выполнять ненужную работу?
teadrinker, то же самое скажу: я в принципе не доверяю такого рода уведомлениям от виндовса. Помню, были прецеденты, когда виндусу казалось, что интернет есть, хотя в WAN-порт роутера вообще не было ничего воткнуто. Такое мне встречалось на Wndows XP и Windows 7, на других ОС не пробовал.
Помню, были прецеденты, когда виндусу казалось, что интернет есть, хотя в WAN-порт роутера вообще не было ничего воткнуто.
Ну так ты можешь протестировать этот код для такого случая, и поделиться результатами.
Попробовал на Windows XP и Windows 7. То, что интернет пропал, скрипт понимает секунд за 15-20; то, что интернет опять стал доступен, понимает секунд за 40-50. Или наоборот, уже подзабыл. Для оператора ПК пойдёт. А когда надо быстро продиагностировать, это долговато.
Попробовал на Windows XP
Не уверен, что тест был корректным. Дело в том, что эта фича была только на Vista была добавлена.
В WinXP это может называлось "шлюз интернета"? Просто моё предположение. https://rykovodstvo.ru/pars_docs/refs/1 … 9c7bca.jpg
А как вы на xp смогли этот скрипт запустить?
По идее там этого апи еще не было.
На xp надо так отлавливать:
https://learn.microsoft.com/en-us/previ … 7(v=vs.85)
На XP я скрипт не запускал. Просто обрывал интернет и ждал, пока пропадёт иконка "Шлюз интернета" в Сетевых подключениях.
Как в "7", так и в "XP" пинг гораздо быстрее Винды даст знать, что происходит в моменты отвала интернета.
Не надо что-либо замерять.
Запустите скрипт на win-7 и отключите интернет.
Я тестировал скрипт на 7 и на 10. У меня оба уведомления приходят моментально и там, и там.
Вопрос: приходят моментально после чего?
На семёрке я отключал сеть из папки сетевых подключений, на десятке включал airplane mode.
Скрипт потестировал сегодня несколько раз на Windows 7. К роутеру подключал свитч, к свитчу подключал компьютер. Далее запускал скрипт.
Я отключал свитч от роутера и засекал, как быстро скрипт поймёт, что интернет пропал. Потом свитч обратно подключал к роутеру и засекал, как быстро скрипт поймёт, что интернет вернулся.
Короче говоря, скрипт в точности повторял показания Windows. А Windows в половине случаев ошибался. В лучшем случае Windows и скрипт замечали пропадание интернета спустя 2-3 минуты. Бывало и так, что скрипт писал "Internet OK", в то время, когда я уже 10 минут как отключил свитч от роутера.
Ну а в худшем случае Windows и, соответственно, скрипт не замечали пропадание интернета в течение нескольких часов (дольше просто не было времени тестировать).
Ну и перезапуск скрипта, естественно, проблему не решает, поскольку он берёт информацию из Windows.
Ну, так это Windows как-то криво работает. У меня, если отключить кабель на семёрке, тоже не сразу реагирует, но через несколько мгновений, в точности, когда в трее показывается иконка с крестиком.
Кстати, возможно, что и пинг будет тупить в это же время.
Иконка с крестиком - это очень простой случай, когда вытыкнули провод компьютера. А в названии темы говорится об оповещении отключения-появления интернета. А отключение-появление интернета может происходить тихо-незаметно, диагностировать его сложнее.
Не удивлюсь если семёрка тупит.
ypppu, есть возможность проверить на современной ос?
У меня на win10 при вытаскивании сетевого кабеля - уведомление приходит мгновенно.
Потестировать на современной ОС для меня затруднительно. Но, даже если он на 10-ке или 11-ке заработает стабильно - это ограничение по версии ОС. А вот тестилка на базе команды ping была бы актуальна и для стареньких ОС.
Вот по какому алгоритму виндовс работает.
Может у вас NSCI отключен?
https://learn.microsoft.com/en-us/previ … dfrom=MSDN
Но, даже если он на 10-ке или 11-ке заработает стабильно - это ограничение по версии ОС.
Согласен. Я бы с семерок пользователей пересаживал в принудительном порядке.
NSCI я не трогал (и вообще только сейчас узнал о его существовании).
По моему мнению, юзеру важно достоверно узнать об отключении/появлении интернета. Пингование удовлетворяет этому требованию и работает надёжно, причём в разных ОС Windows. Ну а Autohotkey позволяет создать такой инструмент.
Страницы 1
Чтобы отправить ответ, вы должны войти или зарегистрироваться