Конференция "WinAPI" » Проверить, подключен ли сетевой диск
 
  • Gu (30.01.11 04:21) [0]
    Есть винда, в ней подключено несколько сетевых дисков от сетевых файловых хранилищ, если устройство выключаем, винда в проводнике на диске рисует красный крестик.

    Для проверки использую такую функцию

    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 идеально подошла бы, еслиб не возвращала бы "нет ошибок" для отключенных дисков. Может еще как то можно?
  • Gu (30.01.11 04:45) [1]
    Есть еще момент, есть функция GetFileInfo, примерно

    var
     sfi: TSHFileInfo;
    begin
     GetFileInfo(Drive+':', 0, sfi, SHGFI_TYPENAME);
     Result := sfi.szTypeName;

    Вот она возвращает сразу "Отключенное сетевое устройство" (и "Сетевой диск" для подмапленых и включенных соответсвенно). Но кроме типа там больше вроде достать нельзя и на разных ОС он разный будет.
  • Gu (01.02.11 23:40) [2]
    Есть интересный вариант с пингом - вычленить имя сервера из сетевой строки (или его ип) и пингануть, на основе ответа принять решение о работоспособности. Но он не подходит:
    а) не все сетевые ресурсы отвечают на пинг (даже если доступна их файловая система)
    б) в вин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
    там где кусочек кода
  • brother © (02.02.11 05:40) [3]
    a: bool;
    ..

    if a:= DirectoryExists(dirName);


  • brother © (02.02.11 06:11) [4]
    но, я бы пробовал создать пустой файл в корне, для проверки доступа + права сразу проверим...
  • Gu (02.02.11 12:00) [5]
    :) а дальше?

    проверять этой функцией отключенные сетевые диски можно, но фича в том, чтобы выполнить проверку его активности, не трогая сам диск (или путь), как только выполняется обращение к нему чемто типа dir..exisists, chdir, disksize и тп - происходит зависание сек. на 30, только потом возвращается ответ от функции, прервать опрос в это время не возможно. нужна функция запроса данных у виндов по диску, типа как писал "Gu   (30.01.11 04:45) [1]", только чтобы true\false был ответ - диск подмаплен, понятно, а вот включен ли
  • brother © (02.02.11 14:09) [6]
    > а вот включен ли

    я не понял, что надо?
    если вернули правду, значит смонитрован и активен!
    иначе, в любом случае ложь..
  • Gu (02.02.11 20:42) [7]
    это понятно, меня интересует время опроса. опрос этими функциями _отключенных_ сетевых дисков - вешает прогу или поток опроса на 30-40 секунд, вот чего пытаюсь избежать. если диск подмаплен и устройство, которое его предоставляет включено - нет вопросов, опрос почти мгновенный, а вот если диск подмаплен и устройство отключено - опрос повесит функцию проверки, в конечном итоге она вернет результат, но через определенное время, а мне нужно сразу, как это делает винда, когда в проводнике видно, что диск отключен, в этом случае винда этот диск не опрашивает (размер и тп). перечитайте первое сообщене.
  • Gu (02.02.11 20:46) [8]
    вот потому и писал про
    DirectoryExistsTimeout("\\machine\folder", 5000);
    - опросить путь за 5 сек, если время опроса больше - вернуть false
    или нужна функция, которая бы у винды спрашивала про активность диска, не опрашивая сам диск
  • Дмитрий Белькевич (03.02.11 09:49) [9]
    Пинг?
  • han_malign (03.02.11 09:55) [10]

    > а мне нужно сразу, как это делает винда

    - а с чего ты взял, что проводник делает это мгновенно? Просто он свои 30 секунд уже подождал, и запомнил результат до первого удачного обращения инициированного пользователем... Причем когда пользователь туда тыркается - каждый раз будут те самые 30 секунд на попытку переподключения.
  • han_malign (03.02.11 09:57) [11]

    > Пинг?

    - ICMP может быть закрыт...
  • han_malign (03.02.11 10:08) [12]
    Можно поиграться с WNetRestoreConnectionW и WNetOpenEnum/WNetEnumResource... Ну и WNetGetResourceInformation не помешает помучать...
  • Gu (04.02.11 09:45) [13]
    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++ нет, чтобы перевели функцию о которой выше писал?
  • Дмитрий Белькевич (04.02.11 11:15) [14]
    Хорошо, может пробовать подключаться к удалённому порту, на котором шары висят? 139-й вроде бы, точно не помню.
  • Gu (04.02.11 14:01) [15]
    в прошлом сообщении забыл заголовок фунции:

    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');

    Еще идеи?
  • Gu (04.02.11 14:05) [16]
    445 порт тоже пробовал
  • Anatoly Podgoretsky © (04.02.11 19:07) [17]
    > Дмитрий Белькевич  (04.02.2011 11:15:14)  [14]

    Не стоит, в наше время этим портом не ограничивается, лучше просто пытаться
    подключиться, самое надежное.
  • i_vint © (02.10.12 11:46) [18]
    ААА мучает такой же вопрос как уменьшить время опроса.... по всякому пробовал.... идет задержка при обращении DirectoryExists('\\CompNet\c$') если компьютер не доступен. Ping то понятно дело использую, но нужно определить работает сервер (компьютер с Windows Server 2003) или нет, бывают ситуации что компьютер (сервер) пингуется а доступа к нему нету, видимо не доступнв файловая подсистема (такое редко но бывает у нас на терминальных серверах....)
  • DVM © (03.10.12 22:40) [19]

    > Gu   (04.02.11 09:45) [13]


    > И неужели тут знающих C++ нет, чтобы перевели функцию о
    > которой выше писал?

    там не С++, а C# (если конечно мы об одном коде говорим), для Delphi будет проще использовать доп поток.
 
Конференция "WinAPI" » Проверить, подключен ли сетевой диск
Есть новые Нет новых   [134430   +3][b:0][p:0.001]