System.UnauthorizedAccessException - доступ к пути запрещен

Это немного сложно, так что медведь со мной...

У меня есть простой небольшой метод:

Public Overloads Shared Function DoStuff(ByVal path As String) As Boolean
        If Not IO.File.Exists(ipath) Then Throw New ArgumentException

        Dim result As Boolean
        Using fs As FileStream = New FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read)
            ' do stuff here, details are not important
            fs.Close()
        End Using

        Return result
    End Function

Я ценю, что метод не показывает, как используется поток, но детали неактуальны, как я объясню ниже.

Этот метод помещается в библиотеке классов; Помощник, который мы ссылаемся в целом ряде других проектов. Понятно, что в большинстве случаев этот код должен выглядеть хорошо в предположении, что путь действителен, доступен и т.д.

Теперь проблема. У меня есть сервисная библиотека WCF, которая ссылается и использует вышеупомянутый метод в сборке помощников. Библиотека обслуживания WCF размещается в службе Windows, которая, в свою очередь, находится на одном из наших серверов. Служба WCF имеет операцию, которая получает UNC-путь для файла, и во время обычного потока вызывает метод выше в классе помощников.

Путь, который я отправляю, предназначен для файла, на общем ресурсе, в нашей сети. Строка "Использование fs As..." завершается со следующим исключением:

System.UnauthorizedAccessException: доступ к пути "Мой путь к файлу указан здесь" отклонен. в System.IO.__ Error.WinIOError(Int32 errorCode, String maybeFullPath) в System.IO.FileStream.Init(путь String, режим FileMode, доступ к FileAccess, права Int32, логические значения useRights, общий ресурс FileShare, параметры Int32 bufferSize, FileOptions, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath) в System.IO.FileStream..ctor(путь String, режим FileMode, доступ к FileAccess, общий ресурс FileShare, параметры Int32 bufferSize, FileOptions, String msgPath, Boolean bFromProxy) в System.IO.FileStream..ctor(String path, FileMode mode) в MyHelperAssemblyName.DoStuff(String filePath) в остальной части исключения - это трассировка стека, указывающая на метод, сборку, службу wcf и т.д.

Теперь, список вещей, которые я пытался диагностировать проблему (включая тупо очевидные шаги):

  • Скопируйте и вставьте путь, указанный в трассировке стека, в проводник Windows (как на моем локальном компьютере, так и на сервере), чтобы убедиться, что файл существует и доступен → Доступ к файлу
  • Убедитесь, что учетная запись службы Windows имеет достаточное разрешение на чтение файла. → Эффективные разрешения перечисляют учетную запись службы как полнофункциональную.
  • Измените учетную запись службы Windows, чтобы использовать мою личную учетную запись администратора (временную меру) и, очевидно, перезапустите службу, чтобы изменения вступили в силу → Неисправна одна и та же строка кода.
  • Скопируйте каталог, содержащий файл, на мой локальный компьютер и запустите службу на моем локальном компьютере (мы хотели убедиться, что NAS, который размещает этот файл, не является причиной) → Неисправна одна и та же строка кода
  • Создайте быстрое консольное приложение, скопируйте код из метода вспомогательной сборки в приложение, введите тот же путь к файлу, запустите его локально, а затем на сервере (на сервере я имею в виду удаленное подключение к серверу, используя ту же самую учетную запись администратора, о которой я упоминал ранее, и запустить ее) → У приложения нет проблем с запуском кода
  • Создайте консольное приложение и используйте стандартный объем способа размещения библиотеки служб WCF в консольном приложении. Запустите приложение локально, а затем, используя WcfStorm по локальному адресу, указанному в качестве базового адреса для консольного приложения, вызовите тот же метод с тем же путем, что и нормальная служба не работает → Результаты WcfStorm подтверждают, что у кода не было проблем
  • Двойная проверка кода библиотеки службы WCF, чтобы убедиться, что нет никакой условной логики, которая могла бы повлиять на мои тесты. > Метод Помощника вызывается почти сразу после запуска Реализации Службы (сразу после проверки аргумента). Операция не может возвращать когерентные результаты без использования вспомогательного метода, поэтому, когда я получал ранее согласованные результаты и предполагал, что был запущен "странный" код доступа к файлу, он имел, infact был запущен
  • Повторно развернута Служба с чистыми перестроениями хоста Windows Service, WCF Service Library и сборки помощников (хотелось бы убедиться, что код на моем экране был проиндексирован кодом, который был запущен на сервере) → Без изменений
  • EDIT 2011-06-24 16: 32GMT- Используя консольное приложение, которое я создал ранее для размещения службы WCF, соответствующим образом настройте baseAddress и разверните его на сервере. Запустите приложение, используя указанную выше учетную запись администратора. Проверьте новое приложение на новом базовом адресе с помощью WcfStorm. → Код работает как ожидалось и возвращает хорошие результаты (я считаю, что на этом этапе сужение его до отказа в обслуживании Windows?)
  • EDIT 2011-06-27 10: 21GMT. Создал простую службу Windows, ссылаясь на вспомогательный класс. Установленная на сервере учетная запись службы установлена ​​так же, как и Live Server. → Новая служба смогла запустить код и получить доступ к файлу
  • EDIT 2011-06-27 10: 23GMT. Раздраженный тем, что служба работала, я вытащил WcfStorm, который у меня остался в течение выходных. Результаты показывались с пятницы, показывая, что живая служба потерпела неудачу. Я возмущаюсь тем же запросом → Он работал... Меня сейчас больше раздражает, потому что у меня нет реальных средств для отслеживания проблемы

    Итак, служба работает корректно. У кого-нибудь есть идеи, что могло бы вызвать такой прерывистый провал? Меня уверяют коллеги, что ничто не изменилось за выходные (по крайней мере, не вручную). Расстроенный...

Ответ 1

Попробуйте монитор процесса. Он покажет вам, какой пользователь обращается к файлу и к конкретному коду ошибки Windows, который возвращается. Затем вы сможете увидеть, почему он работает для некоторых файлов, а не других.

Ответ 2

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

Ответ 3

Использует ли ваша служба WCF олицетворение?

Это объясняет, почему новая служба Windows может выполнять действие, но служба WCF не может. Новая служба аутентифицируется непосредственно против NAS. Если в старой службе WCF выдавал себя за вызывающего абонента, клиентский компьютер аутентифицирует пользователя, их токен передается вашей службе WCF, которая, в свою очередь, передает токен безопасности NAS, и вы попадаете в double hop.

Вы можете заставить активный контекст безопасности вернуться к учетной записи службы, например this:

using (WindowsIdentity.Impersontate(IntPtr.Zero))
{
    DoStuff();
}

Конечно, это не объясняет, почему он мог работать с перерывами. Но это объясняет, что служба WCF работает при локальном вызове на машине, которая ее размещает, но не с удаленной клиентской машины.

Ответ 4

У меня есть несколько догадок.

Вы пытались установить 'FileAccess.Read' и/или 'FileShare.Read' в 'ReadWrite'?

Кроме того, возможно ли, что это предупреждение может быть фактором? Из http://msdn.microsoft.com/en-us/library/5h0z48dh.aspx:

Внимание!

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