相关疑难解决方法(0)

如何确定System.IO.IOException的HResult?

System.Exception.HResult属性受保护.我怎样才能偷看异常并获得HResult而不诉诸于反思或其他丑陋的黑客攻击?


情况就是这样:
我想编写一个备份工具,它可以打开和读取系统上的文件.根据本指南,我使用FileAccess.Read和FileShare.ReadWrite打开文件,因为在我阅读文件时,我不在乎文件是否打开.

在某些情况下,当我读文件被打开另一个应用程序,该System.IO.FileStream.Read()方法引发System.IO.IOException,"该进程无法访问文件,因为另一个进程已锁定的一部分文件".这是错误33,或者我认为HResult 0x80070021.[ 编辑:我相信当另一个进程调用LockFileEx来锁定文件中的字节范围时,可以返回此值.]

当我收到此错误时,我想暂停并重试.我认为这是采取适当的行动.如果锁定进程快速释放字节范围锁,那么我可以继续读取该文件.

出于这个原因,我如何区分IOException?我可以想到这些方法:

  • 私人反思 - 不想那样做.Perf会发臭.
  • 调用Exception.ToString()并解析字符串.感觉hacky.在i18n版本中不起作用.

我不喜欢这些选择.是不是有更好,更清洁的方式?


我只是搜索并找到System.Runtime.InteropServices.Marshal.GetHRForException.那将返回像0x80070021这样的uint吗?

.net c# exception hresult

34
推荐指数
3
解决办法
2万
查看次数

如何判断IOException是否是由另一个进程使用该文件引起的?

我们来看看这个代码示例:

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)

.net c# io process ioexception

4
推荐指数
1
解决办法
3661
查看次数

当磁盘上没有可用空间时,Image.Save上没有抛出异常

我正在服务器上保存图像,我正在覆盖磁盘没有可用空间的情况.为了模拟这一点,我创建了一个几乎没有空间的虚拟硬盘驱动器,我试图将图像保存在那里.

我希望在尝试保存图像时收到异常,但是:

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).

c# system.drawing image out-of-memory

4
推荐指数
1
解决办法
394
查看次数

尽管有IOException catch块,但仍引发IOException

我们有一个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)

.net c#

2
推荐指数
1
解决办法
487
查看次数