Search code examples
c#windowswindows-servicesaccess-deniednetwork-drive

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 tried Map 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.


Solution

  • 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.