本文介绍了C#BackupRead,BackupWrite-System.AccessViolationException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 http://pinvoke.net 来使BackupRead()BackupWrite()正常工作我的参考.我在Google中找到的大多数答案都在引用C ++甚至是Delphi ...我想用其ACL备份文件/文件夹.

I am trying to get BackupRead() and BackupWrite() to work using http://pinvoke.net as my reference. Most answers I find in google are referencing C++ or even Delphi... I want to backup a file/folder with their ACL.

这是我当前的代码(我正在为SE_BACKUP_NAMESE_RESTORE_NAMESE_TAKE_OWNERSHIP_NAME设置特权):

This is my current code (I am setting privileges for SE_BACKUP_NAME and SE_RESTORE_NAME and SE_TAKE_OWNERSHIP_NAME):

            var bReadHandle = ArchiveWinApi.CreateFile(sourcePath, (uint)(ArchiveWinApi.ACCESS_MASK.GENERIC_READ | ArchiveWinApi.ACCESS_MASK.READ_CONTROL | ArchiveWinApi.ACCESS_MASK.ACCESS_SYSTEM_SECURITY), 0, IntPtr.Zero, FileMode.Open, ArchiveWinApi.ExtendedFileAttributes.BackupSemantics, IntPtr.Zero);
            if (!IsValid(bReadHandle))
            {
                var error = GetLastWin32Error();
                throw new Exception("InvalidFileHandle");
            }

            var bWriteHandle = ArchiveWinApi.CreateFile(destPath, (uint)(ArchiveWinApi.ACCESS_MASK.GENERIC_WRITE | ArchiveWinApi.ACCESS_MASK.WRITE_OWNER | ArchiveWinApi.ACCESS_MASK.WRITE_DAC | ArchiveWinApi.ACCESS_MASK.ACCESS_SYSTEM_SECURITY), 0, IntPtr.Zero, FileMode.Create, ArchiveWinApi.ExtendedFileAttributes.BackupSemantics, IntPtr.Zero);
            if (!IsValid(bWriteHandle))
            {
                var error = GetLastWin32Error();
                throw new Exception("InvalidFileHandle");
            }


            var bufferSize = 4096;
            var buffer = Marshal.AllocHGlobal(bufferSize);

            var backupReadContext = IntPtr.Zero;
            var backupWriteContext = IntPtr.Zero;

            uint lpNumberOfBytesRead = 0;
            uint lpNumberOfBytesWritten = 0;

            while (true)
            {
                var result = ArchiveWinApi.BackupRead(bReadHandle, out buffer, (uint) bufferSize, out lpNumberOfBytesRead, false, true, ref backupReadContext);
                if (!result)
                {
                    var error = GetLastWin32Error();
                    throw new Exception("BackupRead failed");
                }

                if (lpNumberOfBytesRead == 0) break;

                result = ArchiveWinApi.BackupWrite(bWriteHandle, buffer, lpNumberOfBytesRead, out lpNumberOfBytesWritten, false, true, ref backupWriteContext);
                if (!result)
                {
                    var error = GetLastWin32Error();
                    throw new Exception("BackupWrite failed");
                }
            }

            ArchiveWinApi.BackupRead(bReadHandle, out buffer, 0, out lpNumberOfBytesRead, true, true, ref backupReadContext);
            ArchiveWinApi.CloseHandle(bReadHandle);

            ArchiveWinApi.BackupWrite(bWriteHandle, buffer, 0, out lpNumberOfBytesWritten, true, true, ref backupWriteContext);
            ArchiveWinApi.CloseHandle(bWriteHandle);

我收到System.AccessViolationException:'尝试读取或写入受保护的内存.这通常表明其他内存已损坏.'

I get a System.AccessViolationException: 'Attempted to read or write protected memory. This is often an indication that other memory is corrupt.'

  [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
  internal static extern bool BackupRead(IntPtr hFile, out IntPtr lpBuffer, [MarshalAs(UnmanagedType.U4)] uint nNumberOfBytesToRead, [MarshalAs(UnmanagedType.U4)] out uint lpNumberOfBytesRead, [MarshalAs(UnmanagedType.Bool)] bool bAbort, [MarshalAs(UnmanagedType.Bool)] bool bProcessSecurity, ref IntPtr lpContext);

  [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
  internal static extern bool BackupWrite(IntPtr hFile, IntPtr lpBuffer, [MarshalAs(UnmanagedType.U4)] uint nNumberOfBytesToWrite, [MarshalAs(UnmanagedType.U4)] out uint lpNumberOfBytesWritten, [MarshalAs(UnmanagedType.Bool)] bool bAbort, [MarshalAs(UnmanagedType.Bool)] bool bProcessSecurity, ref IntPtr lpContext);

 [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
      internal static extern IntPtr CreateFile([MarshalAs(UnmanagedType.LPWStr)] string lpFileName, [MarshalAs(UnmanagedType.U4)] uint dwDesiredAccess, [MarshalAs(UnmanagedType.U4)] FileShare dwShareMode, IntPtr lpSecurityAttributes, [MarshalAs(UnmanagedType.U4)] FileMode dwCreationDisposition, [MarshalAs(UnmanagedType.U4)] ExtendedFileAttributes dwFlagsAndAttributes, IntPtr hTemplateFile);

public enum ACCESS_MASK : uint
  {
     READ_CONTROL = 0x00020000,
     WRITE_DAC = 0x00040000,
     WRITE_OWNER = 0x00080000,

     ACCESS_SYSTEM_SECURITY = 0x01000000,

     GENERIC_READ = 0x80000000,
     GENERIC_WRITE = 0x40000000,
     GENERIC_ALL = 0x10000000,
  }

  [Flags]
  public enum ExtendedFileAttributes
  {
     BackupSemantics = 33554432,
  }

推荐答案

在P/Invoke声明中

In P/Invoke declaration

... BackupRead(IntPtr hFile, out IntPtr lpBuffer, ...

删除out.当然也在通话中.

remove the out. And during call of course too.

对于BackupRead和BackupWrite API,都提供了指向调用者提供的缓冲区的指针.该指针将按值传递,此处不应放置out参数.

For both BackupRead and BackupWrite API, a pointer to a caller-provided buffer is given. This pointer will be passed by value, no out parameter should be placed here.

这篇关于C#BackupRead,BackupWrite-System.AccessViolationException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-18 20:19