C# 如何确定 System.IO.IOException 的 HResult?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/991537/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I determine the HResult for a System.IO.IOException?
提问by Cheeso
The System.Exception.HResult property is protected. How can I peek inside an exception and get the HResult without resorting to reflection or other ugly hacks?
System.Exception.HResult 属性受到保护。如何在不诉诸反射或其他丑陋黑客的情况下窥视异常并获得 HResult?
Here's the situation:
I want to write a backup tool, which opens and reads files on a system.
I open the file with FileAccess.Read and FileShare.ReadWrite, according to this guidance, because I don't care if the file is open for writing at the time I read it.
情况是这样的:
我想编写一个备份工具,它可以打开和读取系统上的文件。我根据此指南使用 FileAccess.Read 和 FileShare.ReadWrite 打开文件,因为我不关心文件在我阅读时是否打开以进行写入。
In some cases, when a file I am reading is open by another app, the System.IO.FileStream.Read() method throws a System.IO.IOException, "The process cannot access the file because another process has locked a portion of the file". This is error 33, or I think HResult 0x80070021. [EDIT: I believe this can be returned when another process calls LockFileExto lock a byte range within a file.]
在某些情况下,当我正在读取的文件被另一个应用程序打开时,System.IO.FileStream.Read() 方法会抛出 System.IO.IOException,“该进程无法访问该文件,因为另一个进程已锁定的一部分文件”。这是错误 33,或者我认为 HResult 0x80070021。[编辑:我相信当另一个进程调用LockFileEx以锁定文件中的字节范围时,可以返回此值。]
I'd like to pause and retry when I get this error. I think this is the appropriate action to take here. If the locking process releases the byte-range lock quickly, then I can proceed reading the file.
当我收到此错误时,我想暂停并重试。我认为这是在这里采取的适当行动。如果锁定过程快速释放字节范围锁定,那么我可以继续读取文件。
How can I distinguish an IOException for this reason, from others? I can think of these ways:
出于这个原因,我如何将 IOException 与其他异常区分开来?我可以想到这些方法:
- private reflection - don't wanna do that. Perf will stink.
- call Exception.ToString() and parse the string. Feels hacky. Won't work in i18n versions.
- 私人反思 - 不想那样做。Perf 会发臭。
- 调用 Exception.ToString() 并解析字符串。感觉很鸡肋。不适用于 i18n 版本。
I don't like these options. Isn't there a better, cleaner way?
我不喜欢这些选项。没有更好、更清洁的方法吗?
I just searched around and found System.Runtime.InteropServices.Marshal.GetHRForException. Will that return a uint like 0x80070021?
我只是四处搜索,发现System.Runtime.InteropServices.Marshal.GetHRForException。那会返回一个像 0x80070021 这样的 uint 吗?
采纳答案by JaredPar
For .Net Framework 4.5 and above, you can use the Exception.HResult
property:
对于 .Net Framework 4.5 及更高版本,您可以使用该Exception.HResult
属性:
int hr = ex.HResult;
For older versions, you can use Marshal.GetHRForException
to get back the HResult, but this has significant side-effects and is not recommended:
对于旧版本,您可以使用Marshal.GetHRForException
来取回 HResult,但这具有显着的副作用,不推荐使用:
int hr = Marshal.GetHRForException(ex);
回答by shahkalpesh
Does CanRead
property help in this case?
i.e. call CanRead
, if that returns true, call Read()
请问CanRead
物业的帮助在这种情况下?
即调用CanRead
,如果返回true,调用Read()
回答by Kevin Pullin
Have you profiled either of these cases? I'd imagine that the reflection method isn't all that slow, especially relative to all the other works your app will be doing and how often this exception will be likely to occur.
你有没有分析过这些案例中的任何一个?我想反射方法并不是那么慢,尤其是相对于您的应用程序将要执行的所有其他工作以及此异常可能发生的频率。
If it turns out to be a bottleneck you can look into caching some of the reflection operations or generate dynamic IL to retrieve the property.
如果事实证明这是一个瓶颈,您可以考虑缓存一些反射操作或生成动态 IL 来检索属性。
回答by UweBaemayr
For what it's worth, System.Exception.HResultis no longer protected in .NET 4.5 -- only the setter is protected. That doesn't help with code that might be compiled with more than one version of the framework.
就其价值而言,System.Exception.HResult在 .NET 4.5 中不再受保护——只有 setter 受到保护。这对可能使用多个版本的框架编译的代码没有帮助。
回答by Maxence
You can also use the ISerializable
interface:
您还可以使用该ISerializable
接口:
static class IOExceptionExtensions
{
public static int GetHResult(this IOException ex)
{
var info = new SerializationInfo(typeof (IOException), new FormatterConverter());
ex.GetObjectData(info, new StreamingContext());
return info.GetInt32("HResult");
}
}
回答by Stefan Steiger
Necromancing.
Or you can just fetch the protected property by reflection:
死灵法术。
或者您可以通过反射获取受保护的属性:
private static int GetHresult(System.Exception exception)
{
int retValue = -666;
try
{
System.Reflection.PropertyInfo piHR = typeof(System.Exception).GetProperty("HResult", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Public);
if (piHR != null)
{
object o = piHR.GetValue(exception, null);
retValue = System.Convert.ToInt32(o);
}
}
catch (Exception ex)
{
}
return retValue;
}