“System.UnauthorizedAccessException” - 我已经在屏幕上看到这条消息 2 天了,只是想不通为什么。 我已经检查了我所知的所有可能的原因,使其工作但失败。以下是我检查过的摘要:
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();
这是一个权限问题,但我无法弄清楚问题出在哪里。这是调试细节:
<块引用>System.UnauthorizedAccessException
<块引用>HResult=0x80070005
<块引用>Message=拒绝访问路径“H:\OrderFiles\21\21003\2100337\PS2100337.pdf”。
<块引用>源=mscorlib
<块引用>堆栈跟踪:
<块引用>在 System.IO.__Error.WinIOError(Int32 errorCode, String MaybeFullPath)
<块引用>在 System.IO.File.InternalDelete(String path, Boolean checkHost)
<块引用>在 System.IO.File.Delete(String path)
<块引用>在 OpenOrder.PSForm.crystalReportViewer1_Load(Object sender, EventArgs e) 在 C:\SG100sys\Source Codes\OpenOrder\OpenOrder\PSForm.cs:line 188
<块引用>这个异常最初是在这个调用栈上抛出的: 【外码】 PSForm.cs 中的 OpenOrder.PSForm.crystalReportViewer1_Load(object, System.EventArgs)
答案 0 :(得分:2)
可能是题外话,但以防万一。 我记得不久前在尝试替换必须与该机器和其他网络位置交互的机器中映射驱动器上的文件时遇到了这种头痛,通常使用不同的凭据。我最终使用自定义 impersonation 上下文并每次都传递域和凭据。我的 FileUtil 库中有这个方法:
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();
}
在你的情况下,你会像这样使用它:
FileUtil.InteractWithNetworkFolder(() => File.Delete(PathToYourFile), Domain, Username, Password)
模拟上下文 (credit to it's creator) 如下所示:
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;
}
}
在跳到这个之前,请尝试检查不太复杂的解决方案。