1

在我将开发环境从 .Net 3.5 切换到 .Net 4.0 后,以下代码无法正常工作。我认为 Marshal.GetLastWin32Error() 的实现已经改变。

使用 .Net 3.5 返回 32,但使用 .Net 4.0 返回 0。

我该如何解决这个问题?有什么建议吗?

private StarterFile(string path, FileMode mode, FileAccess access, FileShare share, out bool isLocked)
    {
        isLocked = false;

        m_Path = path;
        m_Mode = mode;
        m_Access = access;
        m_Share = share;

        try
        {
            m_Stream = new FileStream(path, mode, access, share);
            m_Handle = m_Stream.SafeFileHandle;
        }
        catch (IOException)
        {
            int error = Marshal.GetLastWin32Error();
            if (!HandleFileIoError(error, "File locked") && error == ERROR_SHARING_VIOLATION)
            {
                isLocked = true;
            }
            else
                throw;
        }
    }
4

1 回答 1

1

FileStream 没有改变,它仍然使用 Marshal.GetLastWin32Error() 本身来生成相应的异常。

很可能已经改变的是位于FileStream代码和您的 catch 块之间的大量代码。在不更改错误代码的情况下,它们都不能调用 winapi 函数。

可以修复的,IOException对象其实存储了winapi的原始错误码。从异常对象中取出它有点尴尬, Exception.HResult 不幸的是一个受保护的属性。但是如果有后门,你可以用 Marshal.GetHRForException() 把它弄出来。您只需要处理已转换为 COM 错误代码的 winapi 错误代码,只需将 0x80070000 添加到该值即可。所以让它看起来像这样:

        catch (IOException ex) {
            var hr = (uint)Marshal.GetHRForException(ex);
            if (hr == 0x80070000 + ERROR_SHARING_VIOLATION) {
                // Report sharing violation
                //...
            }
        }
于 2013-10-08T16:49:13.877 回答