كيف يمكنني قراءة القرص مباشرة باستخدام .Net؟

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

  •  09-06-2019
  •  | 
  •  

سؤال

هل من الممكن قراءة القرص مباشرة باستخدام .Net؟أعني مباشرة عبر الجهاز الذي يتجاوز نظام الملفات.أعتقد أنني سأفعل ذلك عن طريق فتح الجهاز بطريقة ما "\Device\Ide\IdeDeviceP2T0L0-1" على سبيل المثال.

إذا لم أتمكن من فتح الجهاز باستخدام واجهة برمجة تطبيقات .NET، فإن معرفة واجهة برمجة تطبيقات Win32 التي يجب استخدامها سيكون مفيدًا.

هل كانت مفيدة؟

المحلول

إنشاء ملف لديه دعم للوصول المباشر إلى القرص.اقرأ الملاحظات الموجودة ضمن "الأقراص ووحدات التخزين الفعلية".يجب أن تكون قادرًا على P/استدعاء المكالمة.

لاحظ أن نظامي التشغيل Vista وServer 2008 لديهما مقيدة بشدة هذا.

نصائح أخرى

رائع، شكرًا لك مارك، لقد نسيت أن CreateFile يفتح الأشياء أيضًا.كنت أبحث في واجهة برمجة تطبيقات إدارة الحجم ولا أرى كيفية فتح الأشياء.

هنا فصل صغير يختتم الأمور.قد يكون من الممكن/الصحيح أيضًا تمرير 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();
        }

تنطبق إخلاءات المسؤولية القياسية، وقد يكون هذا الرمز خطيرًا على صحتك.

رجل.مع كل هذا التنظيم والأشياء، لماذا لا تكتب ملف dll في لغة C وتتخلى عن .NET

يمكنك بعد ذلك استدعاء ملف dll الخاص بك والحصول على وقت أسهل بكثير

أتفق مع إجابة مارك.لاحظ أنه إذا تم تمكين التحكم في حساب المستخدم (وهو الإعداد الافتراضي في نظام التشغيل Windows Vista والإصدارات الأحدث)، فيجب أن يعمل برنامجك بشكل مرتفع (مع امتيازات إدارية).إذا كان برنامجك يستخدم لعدد قليل فقط من المستخدمين، فيمكنك أن تطلب من المستخدم النقر بزر الماوس الأيمن فوق الملفات القابلة للتنفيذ واختيار "تشغيل كمسؤول".بخلاف ذلك، يمكنك تجميع ملف بيان في البرنامج، وفي البيان، حدد أن البرنامج يحتاج إلى تشغيل مرتفع (ابحث عن "requestedExecutionLevel requireAdministrator" للحصول على مزيد من المعلومات).

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top