Не удается получить доступ к сетевому диску во время работы службы Windows

Я пытаюсь создать службу Windows в C#, которая будет копировать все файлы с сетевого диска и вставлять его на локальный диск (скажем, на диске C). Когда я запускаю тестовый пример, программа запускается успешно, но когда я устанавливаю и запускаю службу Windows, в файле журнала появляется ошибка "Доступ запрещен".

Я попробовал решение Map Network Drive (API), но это решение не сработало. или.

Вот пример кода, который я использовал, чтобы получить все файлы с сетевого диска и вставить его в папку локального диска


Service1.cs

    public partial class Service1 : ServiceBase
    {
        private Timer _timer;

        public Service1()
        {
            InitializeComponent();
        }

        protected override void OnStart(string[] args)
        {                
            try
            {

                DoWork();

            }
            catch (Exception e)
            {
                WriteErrorLog(e);
            }

        }

        private void DoWork()
        {
            _timer = new Timer();
            _timer.Interval = 5000;
            _timer.Enabled = true;
            _timer.Elapsed += _timer_Elapsed;
            Update();
        }

        private void Update()
        {
            RevidAddinController.Update_AutodeskAddinFolder_With_ArchcorpUpdatedAddinFiles(Configuration.AutodeskVersion, Configuration.AutodeskRevitAddinFolderPath);     

        }

        private void _timer_Elapsed(object sender, ElapsedEventArgs e)
        {
            Update();
        }

        private void WriteErrorLog(Exception ex)
        {
            StreamWriter sw = null;

            try
            {
                sw = new StreamWriter(AppDomain.CurrentDomain.BaseDirectory + "\\Logfile.txt", true);
                sw.WriteLine(DateTime.Now.ToString() + " ; " + ex.Source.ToString().Trim() + "; " + ex.Message.ToString().Trim());
                sw.Flush();
                sw.Close();

            }
            catch
            {

            }
        }

        protected override void OnStop()
        {
        }

    }

RevidAddinController.cs

    public static class RevidAddinController
    {

        public static IEnumerable<AddinStatus> Update_AutodeskAddinFolder_With_ArchcorpUpdatedAddinFiles(List<string> autoDeskVersion, string addinInstallationPath)
        {
            var networkDrive = ActivateNetworkDrive();
            var allAutodeskVersionPath = Util.GetAllAutodeskAddinLibraryFolderPaths(autoDeskVersion, addinInstallationPath);

            List<FileData> latestArchcorpAddins = new List<FileData>();

            foreach (var autodeskAddinFolder in allAutodeskVersionPath)
            {
                var archorpAddinFiles = Util.GetAllExternalRevitAddinFilesFromArchcorpAddinFolderPath(Configuration.ArchcorpAddinFolderPath);
                var autodeskAddinFiles = Util.GetAllExternalRevitAddinFilesLocationFromAutodeskAddinFolderPath(autodeskAddinFolder);

                var latestAddins = Util.GetUpdatedRevitAddinFromArchcorpFolderPath(autodeskAddinFolder, archorpAddinFiles, autodeskAddinFiles)
                                       .Where(addin => !addin.FileName.Contains(Configuration.DeleteAddinNamePrefix));

                latestArchcorpAddins.AddRange(latestAddins);
            }

            List<AddinStatus> addinCopyStatus = new List<AddinStatus>();
            foreach (var autodeskAddinPath in allAutodeskVersionPath)
            {
                foreach (var newArchcorpAddin in latestArchcorpAddins)
                {
                    addinCopyStatus.Add(Util.InstallNewAddinFile(newArchcorpAddin, autodeskAddinPath));
                }
            }

            return addinCopyStatus;
        }


    /// <summary>
    /// Map the network drive path
    /// </summary>
    /// <returns></returns>
    public static NetworkDrive ActivateNetworkDrive()
    {
        NetworkDrive oNetDrive = new aejw.Network.NetworkDrive();
        try
        {
            oNetDrive.LocalDrive = "O:";
            oNetDrive.ShareName = @"\\acdxbfs1\Organisation";
            oNetDrive.Force = true;
            oNetDrive.Persistent = true;
            oNetDrive.MapDrive();
        }
        catch (Exception err)
        {
            throw err;
        }
        return oNetDrive;
    }

    }

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

3 ответа

Решение

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

Ваши 2 варианта

  1. Запустите службу под учетной записью пользователя, которой сопоставлены эти акции.
  2. Получите доступ к своей папке через ip-адрес вместо буквы диска. Однако вам нужно будет соответственно установить права доступа к файлу / папке.

Служба работает как локальная система (как ранее называлось). Если у вас сопоставлен сетевой диск с буквой локального диска, служба не сможет его использовать (поскольку сопоставленный сетевой диск всегда отображается только для пользовательского контекста, а не для всего компьютера / системы). Однако служба может получить доступ к общему ресурсу с помощью UNC \\server\share. Вы можете просмотреть путь UNC, если у вас есть подключенный сетевой диск, набрав "net use" в командной строке.

Если вы запускаете программу как пользователь, Windows автоматически аутентифицирует вас на удаленном общем ресурсе (если это еще не сделано путем добавления подключенного сетевого диска). Таким образом, Локальная система - это учетная запись компьютера, для которой необходимо установить права доступа целевого общего ресурса для имени компьютера, например workstation1$ (доступно только внутри домена, поскольку рабочая группа не знает другие компьютеры). Это должно быть сделано для прав доступа к файлам и общего ресурса, поскольку оба они независимы и могут ограничить вас от доступа.

В качестве альтернативы вы можете аутентифицироваться на удаленном сетевом ресурсе с помощью имени пользователя и пароля - в stackru есть отличная нить, которая показывает, как это можно сделать.

Естественно, вы также можете установить для службы имя пользователя / пароль в диспетчере служб (services.msc - дважды щелкните свой сервис и перейти на вкладку входа в систему), который имеет доступ к общему ресурсу. Таким образом, пользователю будет предоставлено разрешение "Войти как сервис", которое необходимо для этого.

Если сетевой файл используется совместно с учетной записью локальной системы, вам необходимо войти в систему как «Учетная запись локальной системы»,

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

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