[英]Can't delete files from a shared folder with File.Delete()
"System.UnauthorizedAccessException" - I've seen this message on my screen for 2 days and just couldn't figured out why. “System.UnauthorizedAccessException” - 我已经在屏幕上看到这条消息 2 天了,只是不知道为什么。 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:
这是我检查过的内容的摘要:
fdname = inipath + Convert.ToString(ynum); 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();
It is a permission issue but I just couldn't figure out where the problem is.这是一个权限问题,但我就是不知道问题出在哪里。 Here is the debugging details:
以下是调试详细信息:
System.UnauthorizedAccessException
System.UnauthorizedAccessException
HResult=0x80070005
H结果=0x80070005
Message=Access to the path 'H:\OrderFiles\21\21003\2100337\PS2100337.pdf' is denied.
消息=拒绝访问路径“H:\OrderFiles\21\21003\2100337\PS2100337.pdf”。
Source=mscorlib
源=mscorlib
StackTrace:
堆栈跟踪:
at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
在 System.IO.__Error.WinIOError(Int32 错误代码,字符串可能全路径)
at System.IO.File.InternalDelete(String path, Boolean checkHost)
在 System.IO.File.InternalDelete(字符串路径,Boolean checkHost)
at System.IO.File.Delete(String path)
在 System.IO.File.Delete(字符串路径)
at OpenOrder.PSForm.crystalReportViewer1_Load(Object sender, EventArgs e) in C:\SG100sys\Source Codes\OpenOrder\OpenOrder\PSForm.cs:line 188
在 C:\SG100sys\Source Codes\OpenOrder\OpenOrder\PSForm.cs:line 188 中的 OpenOrder.PSForm.crystalReportViewer1_Load(Object sender, EventArgs e)
This exception was originally thrown at this call stack: [External Code] OpenOrder.PSForm.crystalReportViewer1_Load(object, System.EventArgs) in PSForm.cs
此异常最初是在此调用堆栈中引发的:PSForm.cs 中的 [外部代码] OpenOrder.PSForm.crystalReportViewer1_Load(object, System.EventArgs)
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:
我的 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();
}
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.在进入这个之前,请尝试检查不太复杂的解决方案。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.