.Net을 사용하여 디스크를 직접 읽으려면 어떻게 해야 합니까?

StackOverflow https://stackoverflow.com/questions/38190

  •  09-06-2019
  •  | 
  •  

문제

.Net으로 직접 디스크를 읽을 수 있습니까?직접적으로는 파일 시스템을 우회하는 장치를 통해 의미합니다.예를 들어 "\Device\Ide\IdeDeviceP2T0L0-1" 방식으로 장치를 열어서 이 문제를 해결할 것이라고 생각합니다.

.NET API로 장치를 열 수 없는 경우 사용할 Win32 API를 아는 것이 도움이 될 것입니다.

도움이 되었습니까?

해결책

파일 생성 직접 디스크 액세스를 지원합니다."물리적 디스크 및 볼륨" 아래의 참고 사항을 읽어보세요.통화를 P/Invoke할 수 있어야 합니다.

Vista와 Server 2008에는 엄격하게 제한됨 이것.

다른 팁

좋아요, 감사합니다 Mark. CreateFile도 열 수 있다는 사실을 잊어버렸습니다.볼륨 관리 API를 보고 있었는데 여는 방법이 보이지 않았습니다.

다음은 모든 것을 마무리하는 작은 수업입니다.SafeFileHandle을 FileStream에 전달하는 것도 가능/정확할 수도 있습니다.

using System;
using System.Runtime.InteropServices;
using System.IO;
using Microsoft.Win32.SafeHandles;

namespace ReadFromDevice
{
    public class DeviceStream : Stream, IDisposable
    {
        public const short FILE_ATTRIBUTE_NORMAL = 0x80;
        public const short INVALID_HANDLE_VALUE = -1;
        public const uint GENERIC_READ = 0x80000000;
        public const uint GENERIC_WRITE = 0x40000000;
        public const uint CREATE_NEW = 1;
        public const uint CREATE_ALWAYS = 2;
        public const uint OPEN_EXISTING = 3;

        // Use interop to call the CreateFile function.
        // For more information about CreateFile,
        // see the unmanaged MSDN reference library.
        [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
        private static extern IntPtr CreateFile(string lpFileName, uint dwDesiredAccess,
          uint dwShareMode, IntPtr lpSecurityAttributes, uint dwCreationDisposition,
          uint dwFlagsAndAttributes, IntPtr hTemplateFile);

        [DllImport("kernel32.dll", SetLastError = true)]
        private static extern bool ReadFile(
            IntPtr hFile,                        // handle to file
            byte[] lpBuffer,                // data buffer
            int nNumberOfBytesToRead,        // number of bytes to read
            ref int lpNumberOfBytesRead,    // number of bytes read
            IntPtr lpOverlapped
            //
            // ref OVERLAPPED lpOverlapped        // overlapped buffer
            );

        private SafeFileHandle handleValue = null;
        private FileStream _fs = null;

        public DeviceStream(string device)
        {
            Load(device);
        }

        private void Load(string Path)
        {
            if (string.IsNullOrEmpty(Path))
            {
                throw new ArgumentNullException("Path");
            }

            // Try to open the file.
            IntPtr ptr = CreateFile(Path, GENERIC_READ, 0, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero);

            handleValue = new SafeFileHandle(ptr, true);
            _fs = new FileStream(handleValue, FileAccess.Read);

            // If the handle is invalid,
            // get the last Win32 error 
            // and throw a Win32Exception.
            if (handleValue.IsInvalid)
            {
                Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
            }
        }

        public override bool CanRead
        {
            get { return true; }
        }

        public override bool CanSeek
        {
            get { return false; }
        }

        public override bool CanWrite
        {
            get { return false; }
        }

        public override void Flush()
        {
            return;
        }

        public override long Length
        {
            get { return -1; }
        }

        public override long Position
        {
            get
            {
                throw new NotImplementedException();
            }
            set
            {
                throw new NotImplementedException();
            }
        }
        /// <summary>
        /// </summary>
        /// <param name="buffer">An array of bytes. When this method returns, the buffer contains the specified byte array with the values between offset and 
        /// (offset + count - 1) replaced by the bytes read from the current source. </param>
        /// <param name="offset">The zero-based byte offset in buffer at which to begin storing the data read from the current stream. </param>
        /// <param name="count">The maximum number of bytes to be read from the current stream.</param>
        /// <returns></returns>
        public override int Read(byte[] buffer, int offset, int count)
        {
            int BytesRead =0;
            var BufBytes = new byte[count];
            if (!ReadFile(handleValue.DangerousGetHandle(), BufBytes, count, ref BytesRead, IntPtr.Zero))
            {
                Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
            }
            for (int i = 0; i < BytesRead; i++)
            {
                buffer[offset + i] = BufBytes[i];
            }
            return BytesRead;
        }
        public override int ReadByte()
        {
            int BytesRead = 0;
            var lpBuffer = new byte[1];
            if (!ReadFile(
            handleValue.DangerousGetHandle(),                        // handle to file
            lpBuffer,                // data buffer
            1,        // number of bytes to read
            ref BytesRead,    // number of bytes read
            IntPtr.Zero
            ))
            { Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error()); ;}
            return lpBuffer[0];
        }

        public override long Seek(long offset, SeekOrigin origin)
        {
            throw new NotImplementedException();
        }

        public override void SetLength(long value)
        {
            throw new NotImplementedException();
        }

        public override void Write(byte[] buffer, int offset, int count)
        {
            throw new NotImplementedException();
        }

        public override void Close()
        {
            handleValue.Close();
            handleValue.Dispose();
            handleValue = null;
            base.Close();
        }
        private bool disposed = false;

        new void Dispose()
        {
            Dispose(true);
            base.Dispose();
            GC.SuppressFinalize(this);
        }

        private new void Dispose(bool disposing)
        {
            // Check to see if Dispose has already been called.
            if (!this.disposed)
            {
                if (disposing)
                {
                    if (handleValue != null)
                    {
                        _fs.Dispose();
                        handleValue.Close();
                        handleValue.Dispose();
                        handleValue = null;
                    }
                }
                // Note disposing has been done.
                disposed = true;

            }
        }

    }
}

그리고 클래스 사용의 예

static void Main(string[] args)
        {
            var reader = new BinaryReader(new DeviceStream(@"\\.\PhysicalDrive3"));
            var writer = new BinaryWriter(new FileStream(@"g:\test.dat", FileMode.Create));
            var buffer = new byte[MB];
            int count;
            int loopcount=0;
            try{
                while((count=reader.Read(buffer,0,MB))>0)
                {
                    writer.Write(buffer,0,count);
                    System.Console.Write('.');
                    if(loopcount%100==0)
                    {
                        System.Console.WriteLine();
                        System.Console.WriteLine("100MB written");
                        writer.Flush();
                    }
                    loopcount++;
                }
            }
            catch(Exception e)
            {
                Console.WriteLine(e.Message);
            }
            reader.Close();
            writer.Flush();
            writer.Close();
        }

표준 면책 조항이 적용되며 이 코드는 건강에 해로울 수 있습니다.

남성.그 모든 마샬링과 관련하여 C로 dll을 작성하고 .NET을 사용하지 않는 것이 어떨까요?

그런 다음 DLL을 p/invoke하고 훨씬 쉽게 시간을 보낼 수 있습니다.

Mark의 답변에 동의하십시오.사용자 계정 컨트롤이 활성화된 경우(Windows Vista 이상에서는 기본값) 프로그램은 관리자 권한으로 실행되어야 합니다.프로그램을 소수의 사용자만 사용하는 경우 사용자에게 실행 파일을 마우스 오른쪽 버튼으로 클릭하고 "관리자 권한으로 실행"을 선택하도록 요청할 수 있습니다.그렇지 않은 경우 매니페스트 파일을 프로그램으로 컴파일하고 매니페스트에서 프로그램을 높은 수준으로 실행해야 함을 지정할 수 있습니다(자세한 정보를 얻으려면 "requestedExecutionLevel requireAdministrator" 검색).

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top