-2

"System.UnauthorizedAccessException" - I've seen this message on my screen for 2 days and just couldn't figured out why. I've checked all the possible reasons in my knowledge to make it work but fail. Here is the summary of what I have checked:

  1. The file in the shared drive (mapped drive in the local network) is not ready only and the full access permissions are granted to everyone. The folders in the file path are also been set to grant full access permissions to everyone.
  2. I can delete the file manually
  3. the file was created by the same user (me) and I need to delete it when there is a revision. (delete the old one and put the new one in)
  4. when I change the destination folder to local drive (c:..), everything works well. No problems to delete files. But it won't work (System.UnauthorizedAccessException) when I change it to the shared drive (H: drive).
  5. Here are the codes related to the exception:

fdname = inipath + Convert.ToString(ynum);

        if (! Directory.Exists(fdname))
            System.IO.Directory.CreateDirectory(fdname);
        fdname = inipath + Convert.ToString(ynum) + "\\" + Convert.ToString(fpathnum);
        if (!Directory.Exists(fdname))
            System.IO.Directory.CreateDirectory(fdname);
        fdname = inipath + Convert.ToString(ynum) + "\\" + Convert.ToString(fpathnum) + "\\" + Convert.ToString(salodrnum);
        if (!Directory.Exists(fdname))
        {
            System.IO.Directory.CreateDirectory(fdname);
            File.SetAttributes(fdname, FileAttributes.Normal);
            // File.SetAttributes(fdname, File.GetAttributes(fdname) & ~FileAttributes.ReadOnly);  //remove read ony
        }
        if (File.Exists(fdname + @"\PS" + salodrnum + ".pdf"))
        {
            File.SetAttributes(fdname + @"\PS" + salodrnum + ".pdf", FileAttributes.Normal);
            File.Delete(fdname + @"\PS" + salodrnum + ".pdf");
        }

        doc.ExportToDisk(CrystalDecisions.Shared.ExportFormatType.PortableDocFormat, fdname + @"\PS" + salodrnum + ".pdf");
        File.SetAttributes(fdname + @"\PS" + salodrnum + ".pdf", FileAttributes.Normal);
        procForm.Close();

enter image description here enter image description here

It is a permission issue but I just couldn't figure out where the problem is. Here is the debugging details:

System.UnauthorizedAccessException

HResult=0x80070005

Message=Access to the path 'H:\OrderFiles\21\21003\2100337\PS2100337.pdf' is denied.

Source=mscorlib

StackTrace:

at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)

at System.IO.File.InternalDelete(String path, Boolean checkHost)

at System.IO.File.Delete(String path)

at OpenOrder.PSForm.crystalReportViewer1_Load(Object sender, EventArgs e) in C:\SG100sys\Source Codes\OpenOrder\OpenOrder\PSForm.cs:line 188

This exception was originally thrown at this call stack: [External Code] OpenOrder.PSForm.crystalReportViewer1_Load(object, System.EventArgs) in PSForm.cs

Greg Lin
  • 21
  • 4

1 Answers1

2

Probably off-topic, but in case it helps. I remember having that headache a while ago while trying to replace files on a mapped drive in a machine that had to interact with that and other network locations, often with different credentials. I ended up using a custom impersonation context and passing the domain and credentials each time. I have this method in my FileUtil lib:

public static void InteractWithNetworkFolder(Action MethodThatInteractsWithTheFolder, string Domain, string Username, string Password)
{
    var ImpersonationContext = new WrappedImpersonationContext(Domain, Username, Password);
    ImpersonationContext.Enter();
    MethodThatInteractsWithTheFolder.Invoke();
    ImpersonationContext.Leave();
}

In your case, you'd use it like this:

FileUtil.InteractWithNetworkFolder(() => File.Delete(PathToYourFile), Domain, Username, Password)

And the impersonation context (credit to it's creator) looks like this:

public sealed class WrappedImpersonationContext
{
    public enum LogonType : int
    {
        Interactive = 2,
        Network = 3,
        Batch = 4,
        Service = 5,
        Unlock = 7,
        NetworkClearText = 8,
        NewCredentials = 9
    }

    public enum LogonProvider : int
    {
        Default = 0,  // LOGON32_PROVIDER_DEFAULT
        WinNT35 = 1,
        WinNT40 = 2,  // Use the NTLM logon provider.
        WinNT50 = 3   // Use the negotiate logon provider.
    }

    [DllImport("advapi32.dll", EntryPoint = "LogonUserW", SetLastError = true, CharSet = CharSet.Unicode)]
    public static extern bool LogonUser(String lpszUsername, String lpszDomain,
        String lpszPassword, LogonType dwLogonType, LogonProvider dwLogonProvider, ref IntPtr phToken);

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

    private string _domain, _password, _username;
    private IntPtr _token;
    private WindowsImpersonationContext _context;

    private bool IsInContext
    {
        get { return _context != null; }
    }

    public WrappedImpersonationContext(string domain, string username, string password)
    {
        _domain = String.IsNullOrEmpty(domain) ? "." : domain;
        _username = username;
        _password = password;
    }

    // Changes the Windows identity of this thread. Make sure to always call Leave() at the end.
    [PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")]
    public void Enter()
    {
        if (IsInContext)
            return;

        _token = IntPtr.Zero;
        bool logonSuccessfull = LogonUser(_username, _domain, _password, LogonType.NewCredentials, LogonProvider.WinNT50, ref _token);
        if (!logonSuccessfull)
        {
            throw new Win32Exception(Marshal.GetLastWin32Error());
        }
        WindowsIdentity identity = new WindowsIdentity(_token);
        _context = identity.Impersonate();

        Debug.WriteLine(WindowsIdentity.GetCurrent().Name);
    }

    [PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")]
    public void Leave()
    {
        if (!IsInContext)
            return;

        _context.Undo();

        if (_token != IntPtr.Zero)
        {
            CloseHandle(_token);
        }
        _context = null;
    }
}

Please try to check for less convoluted solutions before jumping into this one.