简体   繁体   中英

Can't access the network drive while running the windows service

I'm trying to create a windows service in C# that will copy all the files from a network drive and paste it into a local drive (let's say in C drive). When I run the test case, the program runs successfully but when I install and run the windows service, the ' Access is denied ' error comes in the log file.

I triedMap Network Drive (API) solution but that solution didn't work. either.

Here's the sample code that I've used to get all the files from a network drive and paste it into the local drive folder


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;
    }

    }

The complete code can be found on the gist here . Would really appreciate if someone reviews the code and provides any feedback/solution to this problem.

Running a service under the default Local System Account , will have no concept of the share. These are set up under user accounts.

Your 2 options

  1. Run your service under a User Account which has those shares mapped
  2. Access your share via and ip address instead of the drive letter. However, you will need to set the file/folder permissions accordingly.

The service does run as Local System (as previously named). If you have a mapped network drive to a local drive letter, the service cannot use it (because a mapped network drive is always only mapped for the user context, not the whole computer/system). However the service can access the share by UNC \\\\server\\share. You can view the UNC path if you only have a mapped network drive by typing 'net use' inside a command prompt.

If you run your program as a user Windows does automatically authenticate you at the remote share (if not already done by adding a mapped network drive). Therefor Local System is the computer account you need to set the access permissions of the target share to the computername eg workstation1$ (only available inside a domain cause a workgroup does not know the other computers). This has to be done for the file permissions and the share permissions because both are independent and can restrict you from the access.

As an alternative you can authenticate at the remote network share with an user and password - there is an excellent thread in stackoverflow which you can find here which does show how you can achieve this.

Naturally you can also set the service to a user/password in the services manager (services.msc - double click your service and go to the logon tab) who has access to the share. By doing this, the user will be granted the 'login as service' permission which is necessary for this.

if the network file is shared with the local system account then you need to Log In as "Local System Account",

The advantage of running your services as the "Local System account" is that the service has complete unrestricted access to local resources.
But there are some disadvantages also, as to be careful to not install unauthorized services as service gets full unrestricted access. And also if the service has some bugs then may lead to performance issues.

本地系统帐户选项

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM