C#光盘刻录

摘要:
1、 背景:最近,该公司的一个旧项目需要添加将数据导出到CD的功能。添加此功能有点矛盾。光盘

一.背景介绍

最近公司一个老项目需要添加导出数据到光盘的功能.开始对这功能添加有点抵触的.光盘?都啥年代了.

光盘一种即将淘汰的存储媒介.就像当年的随身听,Mp3,Mp4一样,即将退出历史舞台.领导让加,发牢骚归发牢骚,活还是得干哈.

从网上找了一些资料,都是特别古老的文档了.很多方法用起来并不是特别的方便.

1.CodePlex Archive https://archive.codeplex.com/?p=csimapi2samples 其中的例子功能不全,参数都使用dynamic类型,刚开始不了解那些基础概念时,理解起来比较难.可以参考学习.

2.博客:https://blog.csdn.net/huanghunjiuba/article/details/12967463 中的例子BurnCdDemo.

里面的BurnCdDemo对ImApi2做了封装.其实例子里面的封装做的挺不错的.注释也特别全.

在做测试的时候发现刻录功能在本机运行的非常好.在公司的测试机上却获取不到光盘大小,取到的大小是负数.对着Demo的源代码检查了半天,没找到原因.╮( ̄▽ ̄")╭,脑袋好大的.后来找到原因了,在下面的过程中会描述下.

C#光盘刻录第1张

PS:个人不喜欢啥都做抽象.抽象,意味着要多写代码,查找问题也不方便.抽象,依赖注入,控制反转是个好东西,就是要多写许多代码.

个人觉得,很多技术还是要看实际项目情况而使用,没有必要去为了追求使用而滥用.看起来高大上,实际多写了代码维护也不方便.

So,自己搞个简单点的.因为就那么几个功能:获取光驱设备列表,获取光盘信息,添加媒体文件,刻录,进度通知.

二.工欲善其事必先利其器

 因工作电脑没有光驱,测试非常不方便.那我们就安装一个虚拟光驱.

推荐一个比较好用的虚拟光驱软件PhantomBurner,带注册码.下载地址:https://download.csdn.net/download/zjhaag/10909339

安装过程就不说了.选下安装路径,一路Next.安装完成后提示重启.其实不重启也可以用.

C#光盘刻录第2张

安装完成后界面如下.在About中输入注册码激活.点击Create,选择Dvd+RW创建Virtual Disc Image.在资源管理器中就可以看到我们创建的虚拟光驱了.

C#光盘刻录第3张

 三.开工

1.设备列表获取

(1)首先添加一个RecorderHelper.在RecorderHelper类中添加一个静态方法GetRecorderList用于获取光驱设备列表.

C#光盘刻录第4张C#光盘刻录第5张
 1         /// <summary>
 2         /// 获取光驱设备列表
 3         /// </summary>
 4         /// <returns></returns>
 5         public static List<Recorder> GetRecorderList()
 6         {
 7             List<Recorder> recordList = new List<Recorder>();
 8 
 9             // Create a DiscMaster2 object to connect to optical drives.
10             MsftDiscMaster2 discMaster = new MsftDiscMaster2();
11             for (int i = 0; i < discMaster.Count; i++)
12             {
13                 if (discMaster[i] != null)
14                 {
15                     Recorder recorder = new Recorder(discMaster[i]);
16                     recordList.Add(recorder);
17                 }
18             }
19             return recordList;
20         }
View Code

此时,需要Recorder光驱对象主要属性如下

C#光盘刻录第4张C#光盘刻录第7张
 1         MsftDiscRecorder2 msRecorder = null;    //Recorder
 2 
 3         /// <summary>
 4         /// 当前磁盘标签
 5         /// </summary>
 6         public string RecorderName { get; private set; }    
 7 
 8         /// <summary>
 9         /// 是否支持当前刻录机
10         /// </summary>
11         public bool IsRecorderSupported { get; private set; }
12 
13         /// <summary>
14         /// 是否支持当前磁盘媒体
15         /// </summary>
16         public bool IsCurrentMediaSupported { get; private set; }
17 
18         /// <summary>
19         /// 当前磁盘可用大小
20         /// </summary>
21         public long FreeDiskSize { get; private set; }
22 
23         /// <summary>
24         /// 当前磁盘总大小
25         /// </summary>
26         public long TotalDiskSize { get; private set; }
27 
28         /// <summary>
29         /// 当前媒体状态
30         /// </summary>
31         public IMAPI_FORMAT2_DATA_MEDIA_STATE CurMediaState { get; private set; }
32 
33         /// <summary>
34         /// 当前媒体状态
35         /// </summary>
36         public string CurMediaStateName { get; private set; }
37 
38         /// <summary>
39         /// 当前媒体类型
40         /// </summary>
41         public IMAPI_MEDIA_PHYSICAL_TYPE CurMediaType { get; private set; }
42 
43         /// <summary>
44         /// 当前媒体类型
45         /// </summary>
46         public string CurMediaTypeName { get; private set; }
47 
48         /// <summary>
49         /// 是否可以刻录
50         /// </summary>
51         public bool CanBurn {get;private set;}
View Code

(2)对Recorder各属性进行初始化,赋值.主要方法如下

C#光盘刻录第4张C#光盘刻录第9张
 1         /// <summary>
 2         /// Recorder Ctor
 3         /// </summary>
 4         /// <param name="uniqueId">标识Id</param>
 5         public Recorder(string uniqueId)
 6         {
 7             this.uniqueId = uniqueId;
 8             msRecorder = new MsftDiscRecorder2();
 9             msRecorder.InitializeDiscRecorder(uniqueId);
10             InitRecorder();
11 
12             this.BurnMediaList = new List<BurnMedia>();
13             this.BurnMediaFileSize = 0;
14         }
15 
16         /// <summary>
17         /// 初始化Recorder
18         /// 更新Recorder信息,更新光盘后可重试.
19         /// </summary>
20         public void InitRecorder()
21         {
22             try
23             {
24                 if (msRecorder.VolumePathNames != null && msRecorder.VolumePathNames.Length > 0)
25                 {
26                     foreach (object mountPoint in msRecorder.VolumePathNames)
27                     {   //挂载点 取其中一个
28                         RecorderName = mountPoint.ToString();
29                         break;
30                     }
31                 }
32                 // Define the new disc format and set the recorder
33                 MsftDiscFormat2Data dataWriter = new MsftDiscFormat2Data();
34                 dataWriter.Recorder = msRecorder;
35 
36                 if (!dataWriter.IsRecorderSupported(msRecorder))
37                 {
38                     return;
39                 }
40                 if (!dataWriter.IsCurrentMediaSupported(msRecorder))
41                 {
42                     return;
43                 }
44                 if (dataWriter.FreeSectorsOnMedia >= 0)
45                 {   //可用大小
46                     FreeDiskSize = dataWriter.FreeSectorsOnMedia * 2048L;
47                 }
48 
49                 if (dataWriter.TotalSectorsOnMedia >= 0)
50                 {   //总大小
51                     TotalDiskSize = dataWriter.TotalSectorsOnMedia * 2048L;
52                 }
53                 CurMediaState = dataWriter.CurrentMediaStatus;  //媒体状态
54                 CurMediaStateName = RecorderHelper.GetMediaStateName(CurMediaState);
55                 CurMediaType = dataWriter.CurrentPhysicalMediaType; //媒介类型
56                 CurMediaTypeName = RecorderHelper.GetMediaTypeName(CurMediaType);
57                 CanBurn = RecorderHelper.GetMediaBurnAble(CurMediaState);   //判断是否可刻录
58             }
59             catch (COMException ex)
60             {
61                 string errMsg = ex.Message.Replace("
", ""); //去掉异常信息里的

62                 this.CurMediaStateName = $"COM Exception:{errMsg}";
63             }
64             catch (Exception ex)
65             {
66                 this.CurMediaStateName = $"{ex.Message}";
67             }
68         }
View Code

(3)测试代码如下

C#光盘刻录第4张C#光盘刻录第11张
 1                     #region 查找光驱设备
 2                     Console.Clear();
 3                     Console.WriteLine("正在查找光驱设备..");
 4                     List<Recorder> recorderList = RecorderHelper.GetRecorderList();
 5                     if (recorderList.Count <= 0)
 6                     {
 7                         Console.WriteLine("没有可以使用的光驱,请检查.");
 8                         Console.WriteLine("请连接光驱后,按任意键重试...");
 9                         Console.ReadKey();
10                         continue;
11                     }
12                     for (int i = 0; i < recorderList.Count; i++)
13                     {
14                         Recorder tempRecorder = recorderList[i];
15                         Console.WriteLine($"发现光驱设备:[{i+1}]  {tempRecorder.RecorderName}");
16                         Console.WriteLine($"媒体类型:{tempRecorder.CurMediaTypeName}");
17                         Console.WriteLine($"媒体状态:{tempRecorder.CurMediaStateName}");
18                         Console.WriteLine("支持刻录:" + (tempRecorder.CanBurn ? "" : "×"));
19                         Console.WriteLine($"可用大小:{FormatFileSize(tempRecorder.FreeDiskSize)}");
20                         Console.WriteLine($"总大小:{FormatFileSize(tempRecorder.TotalDiskSize)}");
21                     }
22                     if (!recorderList.Any(r=>r.CanBurn))
23                     {
24                         Console.WriteLine("没有可以用于刻录的光驱设备,请检查后,按任意键重试.");
25                         Console.ReadKey();
26                         continue;
27                     }
28                     #endregion        
View Code

 测试结果:

C#光盘刻录第12张

至此,我们完成了对于光驱设备列表的获取及Recorder对象各属性的初始化工作.

说明下,对光驱设备操作需要有管理员权限,没有管理员权限会导致获取失败.对于C#应用程序设置以管理员身份启动请参照https://www.cnblogs.com/babycool/p/3569183.html

2.添加刻录文件

(1)我们为Recorder对象添加待刻录媒体对象列表待刻录媒体文件大小两个属性

C#光盘刻录第4张C#光盘刻录第14张
1         /// <summary>
2         /// 待刻录媒体对象List
3         /// </summary>
4         public List<BurnMedia> BurnMediaList {get;set;}
5 
6         /// <summary>
7         /// 待刻录媒体文件大小
8         /// </summary>
9         public long BurnMediaFileSize { get; set; }
View Code

待刻录媒体对象定义如下

C#光盘刻录第4张C#光盘刻录第16张
 1     /// <summary>
 2     /// 刻录媒体
 3     /// </summary>
 4     public class BurnMedia
 5     {
 6         /// <summary>
 7         /// 路径
 8         /// </summary>
 9         public string MediaPath { get; set; }
10 
11         /// <summary>
12         /// 名称
13         /// </summary>
14         public string MediaName { get; set; }
15 
16         /// <summary>
17         /// 是否是文件夹
18         /// </summary>
19         public bool IsDirectory { get; set; }
20 
21         /// <summary>
22         /// 大小
23         /// </summary>
24         public long Size { get; set; }
25     }
View Code

(2)为Recorder对象添加AddBurnMedia方法

C#光盘刻录第4张C#光盘刻录第18张
 1         /// <summary>
 2         /// 添加刻录媒体对象
 3         /// </summary>
 4         public BurnMedia AddBurnMedia(string path)
 5         {
 6             BurnMedia media = null;
 7             if(string.IsNullOrEmpty(path))
 8             {
 9                 throw new Exception("文件路径不能为空.");
10             }
11             if(!CanBurn)
12             {
13                 throw new Exception("当前磁盘状态不支持刻录.");
14             }
15             media = new BurnMedia();
16             long fileSize = 0;
17             if (Directory.Exists(path))
18             {
19                 DirectoryInfo dirInfo = new DirectoryInfo(path);
20                 fileSize = GetDirectorySize(path);
21                 media.MediaName = dirInfo.Name;
22                 media.MediaPath = dirInfo.FullName;
23                 media.Size = fileSize;
24                 media.IsDirectory = true;
25             }
26             else if (File.Exists(path))
27             {
28                 FileInfo fileInfo = new FileInfo(path);
29                 fileSize = fileInfo.Length;
30                 media.MediaName = fileInfo.Name;
31                 media.MediaPath = fileInfo.FullName;
32                 media.Size = fileSize;
33                 media.IsDirectory = false;
34             }
35             else
36             {
37                 throw new Exception("文件不存在");
38             }
39             if (BurnMediaFileSize + fileSize >= FreeDiskSize)
40             {
41                 throw new Exception("剩余空间不足");
42             }
43             if (BurnMediaList.Any(m => m.MediaName.ToLower() == media.MediaName.ToLower()))
44             {
45                 throw new Exception($"已存在媒体名称为{media.MediaName}的对象");
46             }
47             BurnMediaList.Add(media);
48             BurnMediaFileSize += fileSize;
49             return media;
50         }
View Code

(3)测试代码如下

C#光盘刻录第4张C#光盘刻录第20张
 1                     while (true)
 2                     {
 3                         Console.WriteLine("添加文件:请输入待刻录文件或文件夹路径. 0完成 1查看已添加文件");
 4                         string filePath = Console.ReadLine();
 5                         if (string.IsNullOrEmpty(filePath))
 6                         {
 7                             continue;
 8                         }
 9                         else if (filePath == "0")
10                         {
11                             break;
12                         }
13                         else if (filePath == "1")
14                         {
15                             ShowBurnMediaListInfo(recorder);
16                         }
17                         else
18                         {
19                             try
20                             {
21                                 BurnMedia media = recorder.AddBurnMedia(filePath);
22                                 Console.WriteLine($"添加成功:{filePath}");
23                                 Console.WriteLine("文件大小:" + FormatFileSize(media.Size));
24                                 Console.WriteLine("已添加文件总大小:" + FormatFileSize(recorder.BurnMediaFileSize));
25                             }
26                             catch (Exception ex)
27                             {
28                                 Console.WriteLine($"添加失败:{ex.Message}");
29                             }
30                         }
31                     }
View Code

运行结果:

C#光盘刻录第21张

3.刻录及刻录进度通知

 为Recorder对象添加Burn方法.同时,添加刻录进度通知.

(1)添加BurnProgressChanged委托用于通知刻录进度

C#光盘刻录第4张C#光盘刻录第23张
1     /// <summary>
2     /// 刻录进度delegate
3     /// </summary>
4     public delegate void BurnProgressChanged(BurnProgress burnProgress);
View Code

刻录进度通知对象定义如下(其属性为根据需求添加):

C#光盘刻录第4张C#光盘刻录第25张
 1     /// <summary>
 2     /// 刻录进度对象
 3     /// </summary>
 4     public class BurnProgress
 5     {
 6         /// <summary>
 7         /// 当前操作
 8         /// 对应IMAPI2.IMAPI_FORMAT2_DATA_WRITE_ACTION枚举
 9         /// 4 正在写入数据 5完成数据写入 6 刻录完成
10         /// </summary>
11         public int CurrentAction { get; set; }
12 
13         /// <summary>
14         /// 当前操作Name
15         /// </summary>
16         public string CurrentActionName { get; set; }
17 
18         /// <summary>
19         /// 已用时间单位S
20         /// </summary>
21         public int ElapsedTime { get; set; }
22 
23         /// <summary>
24         /// 预计总时间单位S
25         /// </summary>
26         public int TotalTime { get; set; }
27 
28         /// <summary>
29         /// 数据写入进度
30         /// </summary>
31         public decimal Percent { get; set; }
32 
33         /// <summary>
34         /// 数据写入进度%
35         /// </summary>
36         public string PercentStr { get { return Percent.ToString("0.00%"); } }
37     }
View Code

(2)为Recorder对象添加委托属性

C#光盘刻录第4张C#光盘刻录第27张
1         /// <summary>
2         /// 刻录进度变化通知
3         /// </summary>
4         public BurnProgressChanged OnBurnProgressChanged { get; set; }
View Code

(3)为Recorder添加Burn方法

C#光盘刻录第4张C#光盘刻录第29张
  1         /// <summary>
  2         /// 刻录
  3         /// </summary>
  4         public void Burn(string diskName = "SinoUnion")
  5         {
  6             if(!CanBurn)
  7             {
  8                 throw new Exception("当前磁盘状态不支持刻录");
  9             }
 10             if (string.IsNullOrEmpty(diskName))
 11             {
 12                 throw new Exception("DiskName不能为空");
 13             }
 14             if (BurnMediaList.Count <= 0)
 15             {
 16                 throw new Exception("待刻录文件列表不能为空");
 17             }
 18             if(BurnMediaFileSize<=0)
 19             {
 20                 throw new Exception("待刻录文件大小为0");
 21             }
 22 
 23             try
 24             {   //说明
 25                 //1.fsi.ChooseImageDefaults用的是IMAPI2FS的,我们定义的msRecorder是IMAPI2的.所以必须用动态类型
 26                 //2.dataWriter也要使用动态类型,要不然Update事件会出异常.
 27                 // Create an image stream for a specified directory.
 28                 dynamic fsi = new IMAPI2FS.MsftFileSystemImage();  // Disc file system
 29                 IMAPI2FS.IFsiDirectoryItem dir = fsi.Root;                 // Root directory of the disc file system                
 30                 dynamic dataWriter = new MsftDiscFormat2Data(); //Create the new disc format and set the recorder
 31 
 32                 dataWriter.Recorder = msRecorder;
 33                 dataWriter.ClientName = "SinoGram";
 34                 //不知道这方法不用行不行.用的参数是IMAPI2FS的.
 35                 //所以学官网的例子,把fsi改成了动态的.使用msRecorder作为参数
 36                 fsi.ChooseImageDefaults(msRecorder);
 37 
 38                 //设置相关信息
 39                 fsi.VolumeName = diskName;   //刻录磁盘名称
 40                 for (int i = 0; i < BurnMediaList.Count; i++)
 41                 {
 42                     dir.AddTree(BurnMediaList[i].MediaPath, true);
 43                 }
 44                 // Create an image from the file system
 45                 IStream stream = fsi.CreateResultImage().ImageStream;
 46                 try
 47                 {
 48                     dataWriter.Update += new DDiscFormat2DataEvents_UpdateEventHandler(BurnProgressChanged);
 49                     dataWriter.Write(stream);// Write stream to disc
 50                 }
 51                 catch (System.Exception ex)
 52                 {
 53                     throw ex;
 54                 }
 55                 finally
 56                 {
 57                     if (stream != null)
 58                     {
 59                         Marshal.FinalReleaseComObject(stream);
 60                     }
 61                 }
 62             }
 63             catch (Exception ex)
 64             {
 65                 Console.WriteLine($"刻录失败:{ex.Message}");
 66             }
 67         }
 68 
 69         /// <summary>
 70         /// 刻录进度通知
 71         /// </summary>
 72         /// <param name="object"></param>
 73         /// <param name="progress"></param>
 74         void BurnProgressChanged(dynamic @object, dynamic progress)
 75         {
 76             BurnProgress burnProgress = new BurnProgress();
 77             try
 78             {
 79                 burnProgress.ElapsedTime = progress.ElapsedTime;
 80                 burnProgress.TotalTime = progress.TotalTime;
 81                 burnProgress.CurrentAction = progress.CurrentAction;
 82                 if (burnProgress.ElapsedTime > burnProgress.TotalTime)
 83                 {   //如果已用时间已超过预估总时间.则将预估总时间设置为已用时间
 84                     burnProgress.TotalTime = burnProgress.ElapsedTime;
 85                 }
 86                 string strTimeStatus;
 87                 strTimeStatus = "Time: " + progress.ElapsedTime + " / " + progress.TotalTime;
 88                 int currentAction = progress.CurrentAction;
 89                 switch (currentAction)
 90                 {
 91                     case (int)IMAPI2.IMAPI_FORMAT2_DATA_WRITE_ACTION.IMAPI_FORMAT2_DATA_WRITE_ACTION_CALIBRATING_POWER:
 92                         burnProgress.CurrentActionName = "Calibrating Power (OPC)";
 93                         break;
 94                     case (int)IMAPI2.IMAPI_FORMAT2_DATA_WRITE_ACTION.IMAPI_FORMAT2_DATA_WRITE_ACTION_COMPLETED:
 95                         burnProgress.CurrentActionName = "Completed the burn";
 96                         burnProgress.Percent = 1;
 97                         burnProgress.TotalTime = burnProgress.ElapsedTime;  //刻录完成,将预估用时,修正为已用时间
 98                         break;
 99                     case (int)IMAPI2.IMAPI_FORMAT2_DATA_WRITE_ACTION.IMAPI_FORMAT2_DATA_WRITE_ACTION_FINALIZATION:
100                         burnProgress.CurrentActionName = "Finishing the writing";
101                         burnProgress.Percent = 1;
102                         burnProgress.TotalTime = burnProgress.ElapsedTime;  //写入完成,将预估用时,修正为已用时间
103                         break;
104                     case (int)IMAPI2.IMAPI_FORMAT2_DATA_WRITE_ACTION.IMAPI_FORMAT2_DATA_WRITE_ACTION_FORMATTING_MEDIA:
105                         burnProgress.CurrentActionName = "Formatting media";
106                         break;
107                     case (int)IMAPI2.IMAPI_FORMAT2_DATA_WRITE_ACTION.IMAPI_FORMAT2_DATA_WRITE_ACTION_INITIALIZING_HARDWARE:
108                         burnProgress.CurrentActionName = "Initializing Hardware";
109                         break;
110                     case (int)IMAPI2.IMAPI_FORMAT2_DATA_WRITE_ACTION.IMAPI_FORMAT2_DATA_WRITE_ACTION_VALIDATING_MEDIA:
111                         burnProgress.CurrentActionName = "Validating media";
112                         break;
113                     case (int)IMAPI2.IMAPI_FORMAT2_DATA_WRITE_ACTION.IMAPI_FORMAT2_DATA_WRITE_ACTION_VERIFYING:
114                         burnProgress.CurrentActionName = "Verifying the data";
115                         break;
116                     case (int)IMAPI2.IMAPI_FORMAT2_DATA_WRITE_ACTION.IMAPI_FORMAT2_DATA_WRITE_ACTION_WRITING_DATA:
117                         dynamic totalSectors;
118                         dynamic writtenSectors;
119                         dynamic startLba;
120                         dynamic lastWrittenLba;
121                         totalSectors = progress.SectorCount;
122                         startLba = progress.StartLba;
123                         lastWrittenLba = progress.LastWrittenLba;
124                         writtenSectors = lastWrittenLba - startLba;                        
125                         burnProgress.CurrentActionName = "Writing data";
126                         burnProgress.Percent = Convert.ToDecimal(writtenSectors)/ Convert.ToDecimal(totalSectors);
127                         break;
128                     default:
129                         burnProgress.CurrentActionName = "Unknown action";
130                         break;
131                 }
132             }
133             catch (Exception ex)
134             {
135                 burnProgress.CurrentActionName = ex.Message;
136             }
137             if (OnBurnProgressChanged != null)
138             {
139                 OnBurnProgressChanged(burnProgress);
140             }
141         }
View Code

(4)测试代码如下

C#光盘刻录第4张C#光盘刻录第31张
 1                     if (recorder.BurnMediaList.Count <= 0)
 2                     {
 3                         Console.WriteLine($"未添加任何刻录文件.已退出刻录过程.");
 4                     }
 5                     else
 6                     {
 7                         #region 刻录前确认
 8                         bool confirmBurn = false;
 9                         Console.Clear();
10                         ShowBurnMediaListInfo(recorder);
11                         while (true)
12                         {
13                             Console.WriteLine();
14                             Console.ForegroundColor = ConsoleColor.DarkGreen;//设置颜色.
15                             Console.WriteLine($"刻录过程一旦开始,终止可能会造成磁盘损坏.确认要开始刻录(y/n)?");
16                             Console.ForegroundColor = colorFore;//还原颜色.
17                             string confirmStr = Console.ReadLine();
18                             if (confirmStr.ToLower() == "n")
19                             {
20                                 break;
21                             }
22                             else if (confirmStr.ToLower() == "y")
23                             {
24                                 confirmBurn = true;
25                                 break;
26                             }
27                         }
28                         if (!confirmBurn)
29                         {
30                             Console.WriteLine($"本次刻录过程已退出");
31                             continue;
32                         }
33                         #endregion
34                         Console.CursorVisible = false;    //隐藏光标
35                         ShowBurnProgressChanged(recorder);
36                         recorder.Burn();    //刻录
37                         Console.WriteLine();
38                     }
View Code

(5)输出刻录进度变化,添加ShowBurnProgressChanged方法

在查找如何输出进度数据的时候,看到了控制台输出进度条的功能.带颜色的还挺漂亮的,看到好的功能就想加到我们的项目里.

C#光盘刻录第4张C#光盘刻录第33张
 1         /// <summary>
 2         /// 输出刻录进度通知
 3         /// </summary>
 4         /// <param name="recorder"></param>
 5         static void ShowBurnProgressChanged(Recorder recorder)
 6         {
 7             Console.Clear();
 8 
 9             #region 搭建输出显示框架
10             Console.WriteLine();
11             Console.WriteLine($"**********************刻录中,请稍候**********************");
12             Console.WriteLine();
13             Console.WriteLine("  当前操作:"); //第4行当前操作
14             Console.WriteLine();
15 
16             // 第6行绘制进度条背景
17             Console.Write("  ");
18             Console.BackgroundColor = ConsoleColor.DarkCyan;
19             for (int i = 1; i <= 50; i++)
20             {   //设置50*1的为总进度
21                 Console.Write(" ");
22             }
23 
24             Console.WriteLine();
25             Console.BackgroundColor = colorBack;
26 
27             Console.WriteLine();    //第7行输出空行
28             Console.WriteLine();    //第8行输出进度
29             Console.WriteLine($"*********************************************************");  //第9行
30             Console.WriteLine();    //第10行输出空行
31             #endregion
32 
33             //进度变化通知时,更新相关行数据即可.
34             recorder.OnBurnProgressChanged += (burnProgress) => {
35                 if (burnProgress.CurrentAction == 6)
36                 {   //刻录完成
37                     Console.SetCursorPosition(0, 1);
38                     Console.WriteLine($"*************************刻录完成************************");
39                 }
40                 //第4行 当前操作
41                 Console.SetCursorPosition(0, 3);
42                 Console.Write($"  当前操作:{burnProgress.CurrentActionName}");
43                 Console.Write("                  ");    //填充空白区域
44                 Console.ForegroundColor = colorFore;
45 
46                 // 第6行 绘制进度条进度(进度条前预留2空格)
47                 Console.BackgroundColor = ConsoleColor.Yellow; // 设置进度条颜色
48                 Console.SetCursorPosition(2, 5); // 设置光标位置,参数为第几列和第几行
49                 for (int i = 0; i <burnProgress.Percent*50; i++)
50                 {   //每个整数写入1个空格
51                     Console.Write(" "); // 移动进度条
52                 }
53                 Console.BackgroundColor = colorBack; // 恢复输出颜色
54                 
55                 //第8行 已用时间,总时间
56                 Console.ForegroundColor = ConsoleColor.Green;// 更新进度百分比,原理同上.
57                 Console.SetCursorPosition(0, 7);
58                 Console.Write($"  进度:{burnProgress.PercentStr}  " +
59                     $"已用时间:{FormatTime(0, 0, burnProgress.ElapsedTime)}  " +
60                     $"剩余时间:{FormatTime(0, 0, burnProgress.TotalTime - burnProgress.ElapsedTime)}");
61                 Console.Write("      ");    //填充空白区域
62                 Console.ForegroundColor = colorFore;
63 
64                 Console.SetCursorPosition(0, 9);    //光标 定位到第10行
65             };
66         }
View Code

运行结果如下,剩余时间为IMAPI2提供.并不一定准确.

C#光盘刻录第34张

四.BurnCdDemo获取磁盘大小为负数bug

在开始的时候,我们说了使用BurnCdDemo获取光盘大小为负数.在实际开发的过程中,也碰到了.因为我们买的光盘太大了?达到8G,实际模拟刻录时,没那么大.所以没啥问题.

我们看BurnCdDemo里Recorder对象的代码:

1 private long m_nDiskSize = 0;
2 private long m_nUseableSize = 0;
3 
4 //可用的
5 m_nUseableSize = msFormat.FreeSectorsOnMedia * 2048;
6 //总大小
7 m_nDiskSize = msFormat.TotalSectorsOnMedia * 2048;

msFormat.FreeSectorsOnMediamsFormat.TotalSectorsOnMedia类型为int.大家想到原因了吧.int溢出了.所以把后面的2048改为2048L就可以了.看似正常的代码,以后在碰到类型转换时要多注意些.

五.总结

总结写点啥呢.当然是最重要的哈.上源码:https://github.com/279328316/RecorderHelper

如有问题,欢迎留言.

免责声明:文章转载自《C#光盘刻录》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇php操作redis和memcache过期时间Remoting异常处理:在客户端获取服务器内部错误下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章