.net 下直接读分区数据,并生成ISO光盘镜像文件,含DEMO
ISO文件格式被很多虚拟光驱软件和刻录软件支持,比较典型的有WinISO ,Alcohol 120%这些软件.有的时候需要自己制作一个ISO文件的话,则需要找专门的工具;其实要做一个ISO的文件可以很简单,就是把光盘的所有数据映射到文件,只要你可以读光盘的数据就可以生成它.但是,它不是单纯的把光盘上的文件都读入,而是要把整个磁盘信息读入,那么你必须访问磁盘数据,而不是文件;
在WINDOWS下读取磁盘的方法很简单,按该方法也可以读取引导区信息;具体如下:
 CreateFile("\\\\.\\"+driverName, GENERIC_READ, FILE_SHARE_READ, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero);
CreateFile("\\\\.\\"+driverName, GENERIC_READ, FILE_SHARE_READ, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero);在.net 下,要作到这种模式的访问,使用FileStream可行不通,程序运行的时候会直接报个异常,阻止你访问Win32 设备磁盘.那么只能使用原始的做法,声明API.通过SafeFileHandle将文件句柄传递给托管的流进行读写操作.具体做法如下:

 使用 SafeFileHandle 类和非托管 CreateFile 函数打开 Win32 设备
使用 SafeFileHandle 类和非托管 CreateFile 函数打开 Win32 设备1

 /**//// <summary>
    /**//// <summary>2
 /// 使用 SafeFileHandle 类和非托管 CreateFile 函数打开 Win32 设备
    /// 使用 SafeFileHandle 类和非托管 CreateFile 函数打开 Win32 设备3
 /// </summary>
    /// </summary>4
 class UnmanagedDriverLoader
    class UnmanagedDriverLoader5

 
     {
{6
 public const short FILE_ATTRIBUTE_NORMAL = 0x80;
        public const short FILE_ATTRIBUTE_NORMAL = 0x80;7
 public const short INVALID_HANDLE_VALUE = -1;
        public const short INVALID_HANDLE_VALUE = -1;8
 public const uint GENERIC_READ = 0x80000000;
        public const uint GENERIC_READ = 0x80000000;9
 public const uint GENERIC_WRITE = 0x40000000;
        public const uint GENERIC_WRITE = 0x40000000;10
 public const uint FILE_SHARE_READ = 0x00000001;
        public const uint FILE_SHARE_READ = 0x00000001;11
 public const uint CREATE_NEW = 1;
        public const uint CREATE_NEW = 1;12
 public const uint CREATE_ALWAYS = 2;
        public const uint CREATE_ALWAYS = 2;13
 public const uint OPEN_EXISTING = 3;
        public const uint OPEN_EXISTING = 3;14

15
 [DllImport("kernel32.dll", SetLastError = true)]
        [DllImport("kernel32.dll", SetLastError = true)]16
 static extern SafeFileHandle CreateFile(string lpFileName, uint dwDesiredAccess,
        static extern SafeFileHandle CreateFile(string lpFileName, uint dwDesiredAccess,17
 uint dwShareMode, IntPtr lpSecurityAttributes, uint dwCreationDisposition,
          uint dwShareMode, IntPtr lpSecurityAttributes, uint dwCreationDisposition,18
 uint dwFlagsAndAttributes, IntPtr hTemplateFile);
          uint dwFlagsAndAttributes, IntPtr hTemplateFile);19

20
 private SafeFileHandle handleValue = null;
        private SafeFileHandle handleValue = null;21

22
 public UnmanagedDriverLoader(string driverName)
        public UnmanagedDriverLoader(string driverName)23

 
         {
{24
 Load(driverName);
            Load(driverName);25
 }
        }26

27
 public void Load(string driverName)
        public void Load(string driverName)28

 
         {
{29
 if (driverName == null && driverName.Length == 0)
            if (driverName == null && driverName.Length == 0)30

 
             {
{31
 throw new ArgumentNullException("driverName");
                throw new ArgumentNullException("driverName");32
 }
            }33

34
 handleValue = CreateFile("\\\\.\\"+driverName, GENERIC_READ, FILE_SHARE_READ, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero);
            handleValue = CreateFile("\\\\.\\"+driverName, GENERIC_READ, FILE_SHARE_READ, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero);35

36
 if (handleValue.IsInvalid)
            if (handleValue.IsInvalid)37

 
             {
{38
 Marshal.ThrowExceptionForHR(Marshal.GetLastWin32Error());
                Marshal.ThrowExceptionForHR(Marshal.GetLastWin32Error());39
 }
            }40
 }
        }41

42
 public SafeFileHandle Handle
        public SafeFileHandle Handle43

 
         {
{44
 get
            get45

 
             {
{46
 if (!handleValue.IsInvalid)
                if (!handleValue.IsInvalid)47

 
                 {
{48
 return handleValue;
                    return handleValue;49
 }
                }50
 else
                else51

 
                 {
{52
 return null;
                    return null;53
 }
                }54
 }
            }55
 }
        }56
 }
    }首先确定磁盘的大小,再建立一个缓冲区,和一个目标文件用于写入;我建立的缓冲区是10兆,因为光驱比较快,内存也够用。

 /**////10兆一个块
            /**////10兆一个块 int bufferSize = 10240;
            int bufferSize = 10240; byte[] buffer = new byte[bufferSize];
           byte[] buffer = new byte[bufferSize];剩下的事情就简单多了;只需要按块读入,并写到目标文件内:

 /**////计算块的分页大小
            /**////计算块的分页大小 long icount = (long)(GetCDROMSize(driverName) / bufferSize);
            long icount = (long)(GetCDROMSize(driverName) / bufferSize); if ((GetCDROMSize(driverName) % bufferSize) != 0)
            if ((GetCDROMSize(driverName) % bufferSize) != 0) icount++;
                icount++; long length = bufferSize;
            long length = bufferSize;
 hDriver.Seek(0, SeekOrigin.Begin);
            hDriver.Seek(0, SeekOrigin.Begin); hIso.Seek(0, SeekOrigin.Begin);
            hIso.Seek(0, SeekOrigin.Begin);

 /**////遍历块写到文件
            /**////遍历块写到文件 for (long i = 0; i < icount; i++)
            for (long i = 0; i < icount; i++)
 
             {
{ hDriver.Read(buffer, 0, (int)length);
                hDriver.Read(buffer, 0, (int)length); hIso.Write(buffer, 0, (int)length);
                hIso.Write(buffer, 0, (int)length);
 length = GetCDROMSize(driverName) - hDriver.Position;
                length = GetCDROMSize(driverName) - hDriver.Position;
 if (OnProgress != null)
                if (OnProgress != null)
 
                 {
{ OnProgress(this, 0, GetCDROMSize(driverName), hIso.Length);
                    OnProgress(this, 0, GetCDROMSize(driverName), hIso.Length); }
                } if (length > bufferSize)
                if (length > bufferSize) length = bufferSize;
                    length = bufferSize; }
            }
 hDriver.Close();
            hDriver.Close(); hIso.Close();
            hIso.Close();OK,一个磁盘的镜像文件就建立好了,那么可以试试用 WinRar 或 Daemon Tools 装入试试;一切很正常。
根据以上的代码,我作了个DEMO,用于对光盘创建ISO镜像.一样很简单,可以先看看界面.
以下是它的源码,直接下载
/Files/Chinasf/ISO.NET.rar
2006年4月29日
 
                    
                     
                    
                 
                    
                
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号