Быстро определить, если монтирование файла недоступно в 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
Функция устанавливает соединение с сетевым ресурсом. Функция может перенаправить локальное устройство на сетевой ресурс.