System.Exception.HResult属性受保护.我怎样才能偷看异常并获得HResult而不诉诸于反思或其他丑陋的黑客攻击?
情况就是这样:
我想编写一个备份工具,它可以打开和读取系统上的文件.根据本指南,我使用FileAccess.Read和FileShare.ReadWrite打开文件,因为在我阅读文件时,我不在乎文件是否打开.
在某些情况下,当我读文件被打开另一个应用程序,该System.IO.FileStream.Read()方法引发System.IO.IOException,"该进程无法访问文件,因为另一个进程已锁定的一部分文件".这是错误33,或者我认为HResult 0x80070021.[ 编辑:我相信当另一个进程调用LockFileEx来锁定文件中的字节范围时,可以返回此值.]
当我收到此错误时,我想暂停并重试.我认为这是采取适当的行动.如果锁定进程快速释放字节范围锁,那么我可以继续读取该文件.
出于这个原因,我如何区分IOException?我可以想到这些方法:
我不喜欢这些选择.是不是有更好,更清洁的方式?
我只是搜索并找到System.Runtime.InteropServices.Marshal.GetHRForException.那将返回像0x80070021这样的uint吗?
我们来看看这个代码示例:
using System;
using System.IO;
namespace ConsoleApplication25
{
class Program
{
static void Main()
{
var bytes = new byte[] { 1, 2, 3 };
var trimChars = new[] { '"' };
var path = Environment.CommandLine.Trim().Trim(trimChars);
File.WriteAllBytes(path, bytes);
}
}
}
Run Code Online (Sandbox Code Playgroud)
运行此程序(程序试图覆盖自身)会导致抛出异常:
System.IO.IOException was unhandled
Message=The process cannot access the file 'F:\TEMP\ConsoleApplication25\ConsoleApplication25\bin\Debug\ConsoleApplication25.vshost.exe' because it is being used by another process.
Source=mscorlib
StackTrace:
at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, …
Run Code Online (Sandbox Code Playgroud) 我正在服务器上保存图像,我正在覆盖磁盘没有可用空间的情况.为了模拟这一点,我创建了一个几乎没有空间的虚拟硬盘驱动器,我试图将图像保存在那里.
我希望在尝试保存图像时收到异常,但是:
using (var ms = new MemoryStream(myPictureStream))
using (Image image = Image.FromStream(ms))
{
image.Save(fileName, ImageFormat.Jpeg);
}
Run Code Online (Sandbox Code Playgroud)
但事实并非如此,没有例外.而是保存一个空文件,所以我不知道错误.我想在尝试保存图像时收到一些错误,或者在抛出异常之前能够预测错误.
我已经考虑了一些可能的解决方案:
DriveInfo
,但是我没有驱动器号来检查生产,所以这个选项被丢弃了.Image.FromFile
然后OutOfMemoryException
抛出,但我知道这可能发生在其他情况下,我不知道这是否是检查磁盘没有可用空间的合法方式.所以......任何想法为什么Image.Save()在没有可用空间时不会抛出错误?关于如何处理这种情况的任何建议?
GetLastError
没有帮助(它是代码0,成功),所以似乎处理这种情况的最佳方法是将图像保存为时间MemoryStream
,然后将其写入文件,正如@Eldar和@nvoigt给出的答案所指出的那样.
这样做,IOException
抛出一个,你可以检查HResult
异常,看看它是否是一个不够空闲的磁盘空间(参见这个答案:https://stackoverflow.com/a/ 9294382/4067893).
我们有一个Windows Forms应用程序,该应用程序连接到某些Web服务。它列出了系统中的文档,当用户双击文档时,我们将文件下载到本地计算机,然后打开文档进行编辑。用户关闭文档后,我们会将其上传回系统。
在此过程中,我们一直在监视文档上的文件锁定。释放文件锁后,我们就会上载文档。
该IsFileLocked
方法如下所示:
private const int ErrorLockViolation = 33;
private const int ErrorSharingViolation = 32;
private static bool IsFileLocked(string fileName)
{
Debug.Assert(!string.IsNullOrEmpty(fileName));
try
{
if (File.Exists(fileName))
{
using (FileStream fs = File.Open(fileName, FileMode.Open, FileAccess.Read, FileShare.None))
{
fs.ReadByte();
}
}
return false;
}
catch (IOException ex)
{
// get the HRESULT for this exception
int errorCode = Marshal.GetHRForException(ex) & 0xFFFF;
return errorCode == ErrorSharingViolation || errorCode == ErrorLockViolation;
}
}
Run Code Online (Sandbox Code Playgroud)
我们将其称为循环,两次尝试之间有5秒钟的睡眠时间。在大多数情况下,这似乎效果很好,但有时我们会IOException
从这种方法中看到一个。我看不到有可能引发此异常。
例外是:
IOException: The process cannot …
Run Code Online (Sandbox Code Playgroud)