Быстро определить, если монтирование файла недоступно в Windows

У нас есть веб-приложение, которое пытается использовать некоторые ресурсы для монтирования Samba. Если монтирование как-то не удалось, мне нужен способ быстро обнаружить и сообщить об ошибке, однако File.Exists и Directory.Exists требуют 30 секунд, чтобы вернуть false, когда монтирование завершается. Каков наилучший способ быстро определить, доступно ли монтирование в C#?

4 ответа

Решение

Сетевые функции Win32 Windows - единственный способ получить эту информацию. Вы должны быть в состоянии использовать WNetGetResourceInformation или WNetGetConnection. Я думаю, что WNetGetConnection может быть лучшим вариантом. Возвращаемые значения, которые вас больше всего интересуют:

ERROR_CONNECTION_UNAVAIL Устройство в данный момент не подключено, но это постоянное соединение. Для получения дополнительной информации см. Следующий раздел "Примечания".

ERROR_NO_NETWORK Сеть недоступна.

Помимо всего этого, я понимаю желание проявлять инициативу в возможности чтения / записи из резервной копии, но мне кажется, что это будет более правильно обрабатываться на стороне аппаратного обеспечения и / или операционной системы, а не приложения. Аппаратное обеспечение и / или операционная система с большей вероятностью смогут обнаружить, что произошла ошибка чтения / записи или произошло какое-либо другое событие, связанное с сетью, и предпринять соответствующие действия.

Если успешная проверка с File.Exists всегда завершается в течение 5 секунд (или более короткое время), вы можете предположить, что любой вызов, который занимает больше времени, завершится неудачей.

Вот псевдокод возможное решение:

const int CUSTOM_TIMEOUT = 5;
bool isMountedVar = false;

bool isMounted ( string path) {
   Thread mythread = executeNewThread(&isMountedThread, path);
   sleep(CUSTOM_TIMEOUT);
   if( mythread.finished() )
      return isMountedVar;
   // Otherwise
   mythread.kill();
   return false;
}

void isMountedThread(string path) {
   isMountedVar = File(path).Exists;
}

Проблема заключается в том, что базовая операционная система (Windows) всегда возвращает тот факт, что нет общего ресурса.

Самый быстрый способ, который я могу придумать, - это инициировать пинг, чтобы проверить, получен ли ответ от удаленного устройства, успешен ли пинг (который должен быть проверен в течение секунды), тогда теоретически вы должны получить ответ от горы достаточно быстро. Если удаленное устройство недоступно, то у вас возникнет какая-то идея, которая имеет место относительно быстро. Это грязно, но определенно даст вам более быстрые результаты, чем ожидание тайм-аута проверки Windows.

Это, конечно, не проверяет доступность общего ресурса на удаленном устройстве... У вас есть возможность запускать программное обеспечение на удаленном сервере? Если это так, вы могли бы написать дозорного, который мог бы проверить доступность общего ресурса, который вы могли бы пропинговать с именем общего ресурса. Затем он теоретически отреагирует намного быстрее, так как не будет необходимости в тайм-ауте - либо дозорный ответит истиной или ложью, либо не ответит немедленно. В любом случае у вас будет быстрый ответ.

Это все на данный момент... может быть, у меня будет еще немного мыслей в ближайшее время.

Я бы посоветовал заглянуть в WIN32 Сетевые функции Windows, потому что эта функция не доступна напрямую из .NET, Вероятной отправной точкой является WNetGetResourceInformation Функция с кодами возврата ошибок.

WNetGetResourceInformation

При наличии удаленного пути к сетевому ресурсу функция WNetGetResourceInformation идентифицирует сетевого провайдера, который владеет ресурсом, и получает информацию о типе ресурса. Если функция завершается ошибкой, возвращаемое значение представляет собой системный код ошибки, например одно из следующих значений.

Код возврата - Описание

ERROR_BAD_NET_NAME - входной элемент lpRemoteName не является существующим сетевым ресурсом ни для одной сети.

ERROR_BAD_DEV_TYPE -Входной член dwType не соответствует типу ресурса, указанного членом lpRemoteName.

ERROR_EXTENDED_ERROR - произошла ошибка сети. Вызовите WNetGetLastError, чтобы получить описание ошибки.

ERROR_MORE_DATA - буфер, на который указывает параметр lpBuffer, слишком мал.

ERROR_NO_NETWORK - сеть недоступна.

Для того, чтобы позвонить Wnet функции от .NET, ищите примеры на Pinvoke.net. Быстрый поиск не придумал WNetGetResourceInformation пример, но достаточно звонков другим Wnet функции. Смотрите WNetAddConnection2 для аналогичного использования.

WNetAddConnection2 Функция устанавливает соединение с сетевым ресурсом. Функция может перенаправить локальное устройство на сетевой ресурс.

Другие вопросы по тегам