-
Есть винда, в ней подключено несколько сетевых дисков от сетевых файловых хранилищ, если устройство выключаем, винда в проводнике на диске рисует красный крестик. Для проверки использую такую функцию Function NetDTest(Drive:Char;var NetPath:String):boolean; var Path:string;MaxPath:dword; begin MaxPath:=MAX_PATH;SetLength(Path,MAX_PATH);NetPath:='';Result:=False; if WNetGetConnection(PChar(Drive+':'),PChar(Path),MaxPath)=NO_ERROR then begin result:=true;NetPath:=Trim(Path);end; end; она нормально работает для подключенных дисков - выдает true и сетевой путь к девайсу. Но онаже почемуто работает и для отключенных устройств (т.е. диск подмаплен, устройство выключено, в проводнике рисуется крестик), а она все равно возвращает что соединение есть и путь тоже, ну поть ладно, а вот почему NO_ERROR срабатывает, когда должно ERROR_NOT_CONNECTED выдавать? нашел еще вот тут примеры, но в тех функциях тоже определяется, что подключение есть: http://www.sql.ru/forum/actualthread.aspx?tid=681580Определять подключение чемто типа {$I-} ChDir(Drive+':\') не хочу, потому как прога надолго задумывается и потом соответствено пишет, что папку сменить не может. Что надо: не прибегая к опросу сетевого диска определить, есть подключение или нет. WNetGetConnection идеально подошла бы, еслиб не возвращала бы "нет ошибок" для отключенных дисков. Может еще как то можно?
-
Есть еще момент, есть функция GetFileInfo, примерно
var sfi: TSHFileInfo; begin GetFileInfo(Drive+':', 0, sfi, SHGFI_TYPENAME); Result := sfi.szTypeName;
Вот она возвращает сразу "Отключенное сетевое устройство" (и "Сетевой диск" для подмапленых и включенных соответсвенно). Но кроме типа там больше вроде достать нельзя и на разных ОС он разный будет.
-
Есть интересный вариант с пингом - вычленить имя сервера из сетевой строки (или его ип) и пингануть, на основе ответа принять решение о работоспособности. Но он не подходит: а) не все сетевые ресурсы отвечают на пинг (даже если доступна их файловая система) б) в вин7 теперь для пинга нужны права администратора, что очень плохо Пробовал определение делать через directoryexists, загоняя ее в отдельный поток, и терминируя его через 5 секунд после запуска, но при терминировании он все равно зависает, даже если убивать его TerminateThread(GuTh.Handle,0), а не родным GuTh.Terminate или ставить GuTh.FreeOnTerminate:=true; - при этом пока запрос не завершиться, процесс не будет освобожден и уничтожен. Винда тратит на запрос около 30 секунд на диск (сетевой путь), если он недоступен, может кто подскажет - где в системе можно изменить параметр, отвечающий за этот таймаут? Вот тут вот нашел похоже идеальное решение (bool a = DirectoryExistsTimeout("\\machine\folder", 5000);), но на C++, может кто сможет код на дельфи перевести? ссылка: http://stackoverflow.com/questions/1438923/faster-directoryexists-functionтам где кусочек кода
-
a: bool;
..
if a:= DirectoryExists(dirName);
-
но, я бы пробовал создать пустой файл в корне, для проверки доступа + права сразу проверим...
-
:) а дальше?
проверять этой функцией отключенные сетевые диски можно, но фича в том, чтобы выполнить проверку его активности, не трогая сам диск (или путь), как только выполняется обращение к нему чемто типа dir..exisists, chdir, disksize и тп - происходит зависание сек. на 30, только потом возвращается ответ от функции, прервать опрос в это время не возможно. нужна функция запроса данных у виндов по диску, типа как писал "Gu (30.01.11 04:45) [1]", только чтобы true\false был ответ - диск подмаплен, понятно, а вот включен ли
-
> а вот включен ли
я не понял, что надо? если вернули правду, значит смонитрован и активен! иначе, в любом случае ложь..
-
это понятно, меня интересует время опроса. опрос этими функциями _отключенных_ сетевых дисков - вешает прогу или поток опроса на 30-40 секунд, вот чего пытаюсь избежать. если диск подмаплен и устройство, которое его предоставляет включено - нет вопросов, опрос почти мгновенный, а вот если диск подмаплен и устройство отключено - опрос повесит функцию проверки, в конечном итоге она вернет результат, но через определенное время, а мне нужно сразу, как это делает винда, когда в проводнике видно, что диск отключен, в этом случае винда этот диск не опрашивает (размер и тп). перечитайте первое сообщене.
-
вот потому и писал про DirectoryExistsTimeout("\\machine\folder", 5000); - опросить путь за 5 сек, если время опроса больше - вернуть false или нужна функция, которая бы у винды спрашивала про активность диска, не опрашивая сам диск
-
Пинг?
-
> а мне нужно сразу, как это делает винда
- а с чего ты взял, что проводник делает это мгновенно? Просто он свои 30 секунд уже подождал, и запомнил результат до первого удачного обращения инициированного пользователем... Причем когда пользователь туда тыркается - каждый раз будут те самые 30 секунд на попытку переподключения.
-
> Пинг?
- ICMP может быть закрыт...
-
Можно поиграться с WNetRestoreConnectionW и WNetOpenEnum/WNetEnumResource... Ну и WNetGetResourceInformation не помешает помучать...
-
2 Дмитрий Белькевич
см. Gu (01.02.11 23:40) [2]
2 han_malign > - а с чего ты взял..
это если на откл. диск нажать, тогда да опрос будет 30 сек, а когда просто открываем проводник, там уже видно что диски отключены
> Можно поиграться ..
WNetRestoreConnectionW - не подходит, т.к. проблема не в востановлении подключения а в проверке его наличия, даже если использовать ее для проверки, для начала надо знать, что подключения нет
WNetOpenEnum/WNetEnumResource - только для получения списка сетевых подключений, никакой инфы о том, что они подключены\отключены тут нет
помучал WNetGetResourceInformation, никак нормальное описание не могу найти, пробовал разные варианты запросов, кроме того там есть еще аналог с W на конце, попробовал обе, нормально не работают
function WNetGetResourceInformation(lpNetResource: PNetResource; lpBuffer: Pointer; var cbBuffer: DWORD; var lplpSystem: PChar): DWORD; stdcall; external mpr name 'WNetGetResourceInformationA'; //W пробовал
procedure Gho; var NetResource : TNetResource; Size : DWORD; Result : DWORD; Res : PNetResource; Str : PChar; begin with NetResource do begin dwScope := RESOURCE_GLOBALNET; //RESOURCE_CONNECTED; //RESOURCE_REMEMBERED; dwType := RESOURCETYPE_DISK; //RESOURCETYPE_ANY; dwDisplayType := RESOURCEDISPLAYTYPE_SHARE; // RESOURCEDISPLAYTYPE_SERVER; dwUsage := RESOURCEUSAGE_CONNECTABLE; // RESOURCEUSAGE_CONTAINER; lpLocalName := nil; lpComment := nil; lpProvider := nil; //'Microsoft Windows Network'; end; NetResource.lpRemoteName:='\\192.168.0.2\d$'; Size := SizeOf(TNetResource);GetMem(Res, Size); Result := WNetGetResourceInformation(@NetResource, Res, Size, Str); case result of ERROR_BAD_NET_NAME:qq('BNN'); ERROR_BAD_DEV_TYPE:qq('BDT'); ERROR_EXTENDED_ERROR:qq('EE'); ERROR_MORE_DATA:qq('MD'); ERROR_NO_NETWORK:qq('NN'); NO_ERROR:qq('NE'); end; qq(inttostr(result)+' '+String(Str)); // qq - аналог showmessage end;
может кто проверит, может в описании функции ошибся?
короче пока остановился на варианте как писал выше, с анализом строки от GetFileInfo. И неужели тут знающих C++ нет, чтобы перевели функцию о которой выше писал?
-
Хорошо, может пробовать подключаться к удалённому порту, на котором шары висят? 139-й вроде бы, точно не помню.
-
в прошлом сообщении забыл заголовок фунции:
function WNetGetResourceInformation(lpNetResource: PNetResource; lpBuffer: Pointer; var lpBufferSize: DWORD; var lplpBuffer: Pointer): DWORD; stdcall; external mpr name 'WNetGetResourceInformationA';
__
2 Дмитрий
Забавно, но при попытке связываться по 139 порту происходит все таже задержка (ровно 21 секунда, замерял), даже несмотря на таймаут. И патом как то это не очень красиво получается, антивири могут косо смотреть..
Function isNBOn(Host:String):boolean; Var IdTCPClient1:TIdTCPClient; Begin Result:=true; IdTCPClient1:=TIdTCPClient.Create(nil); IdTCPClient1.ConnectTimeout:=5000; IdTCPClient1.ReadTimeout:=5000; // -1 тоже пробовал IdTCPClient1.Port:=139; IdTCPClient1.Host:=Host; Try IdTCPClient1.Connect; IdTCPClient1.Disconnect; Except Result:=false; End; IdTCPClient1.Free; End;
------- if isNBon('192.168.0.2') then qq('Yes');
Еще идеи?
-
445 порт тоже пробовал
-
> Дмитрий Белькевич (04.02.2011 11:15:14) [14]
Не стоит, в наше время этим портом не ограничивается, лучше просто пытаться подключиться, самое надежное.
-
ААА мучает такой же вопрос как уменьшить время опроса.... по всякому пробовал.... идет задержка при обращении DirectoryExists('\\CompNet\c$') если компьютер не доступен. Ping то понятно дело использую, но нужно определить работает сервер (компьютер с Windows Server 2003) или нет, бывают ситуации что компьютер (сервер) пингуется а доступа к нему нету, видимо не доступнв файловая подсистема (такое редко но бывает у нас на терминальных серверах....)
-
> Gu (04.02.11 09:45) [13]
> И неужели тут знающих C++ нет, чтобы перевели функцию о > которой выше писал?
там не С++, а C# (если конечно мы об одном коде говорим), для Delphi будет проще использовать доп поток.
|