File.Exists возвращает false с сетевого ресурса - PullRequest
6 голосов
/ 30 декабря 2008

Я работал над проектом ASP.NET, который собирается сохранить загруженные файлы в общий сетевой ресурс. Я подумал, что мог бы просто использовать виртуальный каталог и быть в порядке, но я боролся с разрешениями для Directory.CreateDirectory.

Мне удалось загрузить файлы, поэтому я решил изменить свой код, чтобы поместить все в один каталог, однако для этого необходимо использовать File.Exists, чтобы избежать перезаписи дубликатов.

Теперь, когда я обновил весь свой код, я обнаружил, что независимо от того, что я делаю, File.Exists всегда возвращает false (файл определенно существует), когда я тестирую сетевой ресурс.

Есть идеи? Я подхожу к самому концу моей веревки с сетевыми ресурсами.

Ответы [ 4 ]

8 голосов
/ 30 декабря 2008

File.Exist фактически не проверяет наличие файла. Вместо этого он проверяет наличие файлов, к которым у вас есть определенный доступ. Если вы знаете, что файл существует, вероятная проблема заключается в том, что у вас нет к нему доступа.

6 голосов
/ 30 декабря 2008

Я только недавно работал над очень похожим проектом, где я сохраняю файлы в сетевой папке. Два компьютера находятся в одной подсети, но не контролируются контроллером домена, поэтому у каждого компьютера есть свои пользователи.

Я создал пользователя с одинаковыми именем пользователя и паролем на обоих компьютерах. Затем я создал сетевой ресурс и установил для папки / общего ресурса разрешения на чтение и запись для пользователя.

Затем я создал следующий класс для управления олицетворением:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security.Principal;
using System.Security.Permissions;
using System.Text;

namespace MyProject.Business.Web
{
    public class SecurityManager
    {
        #region DLL Imports
        [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
        public static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken);

        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        public extern static bool CloseHandle(IntPtr handle);

        [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public extern static bool DuplicateToken(IntPtr ExistingTokenHandle, int SECURITY_IMPERSONATION_LEVEL, ref IntPtr DuplicateTokenHandle);
        #endregion

        public string Domain { get; set; }
        public string UserName { get; set; }
        public string Password { get; set; }

        private WindowsImpersonationContext m_CurrentImpersonationContext;

        [PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")]
        public void StartImpersonation()
        {
            const int LOGON32_PROVIDER_DEFAULT = 0;
            const int LOGON32_LOGON_INTERACTIVE = 2;

            IntPtr tokenHandle = IntPtr.Zero;
            IntPtr dupeTokenHandle = IntPtr.Zero;

            // obtain a handle to an access token
            bool wasLogonSuccessful = LogonUser(UserName, Domain, Password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref tokenHandle);

            if (!wasLogonSuccessful)
                throw new Exception(String.Format("Logon failed with error number {0}", Marshal.GetLastWin32Error()));

            // use the token handle to impersonate the user
            WindowsIdentity newId = new WindowsIdentity(tokenHandle);
            m_CurrentImpersonationContext = newId.Impersonate();

            // free the tokens
            if (tokenHandle != IntPtr.Zero)
                CloseHandle(tokenHandle);
        }
        public void EndImpersonation()
        {
            m_CurrentImpersonationContext.Undo();
        }
    }
}

Затем на странице ASP.NET я сделал следующее:

SecurityManager sm = new SecurityManager();
sm.UserName = ConfigurationManager.AppSettings["UserFileShareUsername"];
sm.Password = ConfigurationManager.AppSettings["UserFileSharePassword"];
sm.StartImpersonation();

if (!Directory.Exists(folderPath)) Directory.CreateDirectory(folderPath);

File.Move(sourcePath, destinationPath);

sm.EndImpersonation();
2 голосов
/ 28 июня 2010

Я использовал почти такой же код, но мой класс реализовал интерфейс IDisposable и добавил Undo () в метод Dispose (). Этот код работает нормально, если вы единственный разработчик, использующий его, и вы всегда будете делать все правильно, верно?

2 голосов
/ 30 декабря 2008

Возможно, ваш код (например, код сервера ASP.NET) работает как пользователь (например, пользователь IIS), у которого нет прав доступа к этой сетевой папке.

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

...