最近公司一個老項目須要添加導出數據到光盤的功能.開始對這功能添加有點抵觸的.光盤?都啥年代了.html
光盤一種即將淘汰的存儲媒介.就像當年的隨身聽,Mp3,Mp4同樣,即將退出歷史舞臺.領導讓加,發牢騷歸發牢騷,活仍是得幹哈.git
從網上找了一些資料,都是特別古老的文檔了.不少方法用起來並非特別的方便.github
1.CodePlex Archive https://archive.codeplex.com/?p=csimapi2samples 其中的例子功能不全,參數都使用dynamic類型,剛開始不瞭解那些基礎概念時,理解起來比較難.能夠參考學習.api
2.博客:https://blog.csdn.net/huanghunjiuba/article/details/12967463 中的例子BurnCdDemo.框架
裏面的BurnCdDemo對ImApi2作了封裝.其實例子裏面的封裝作的挺不錯的.註釋也特別全.ide
在作測試的時候發現刻錄功能在本機運行的很是好.在公司的測試機上卻獲取不到光盤大小,取到的大小是負數.對着Demo的源代碼檢查了半天,沒找到緣由.╮( ̄▽ ̄")╭,腦殼好大的.後來找到緣由了,在下面的過程當中會描述下.學習
PS:我的不喜歡啥都作抽象.抽象,意味着要多寫代碼,查找問題也不方便.抽象,依賴注入,控制反轉是個好東西,就是要多寫許多代碼.測試
我的以爲,不少技術仍是要看實際項目狀況而使用,沒有必要去爲了追求使用而濫用.看起來高大上,實際多寫了代碼維護也不方便.this
So,本身搞個簡單點的.由於就那麼幾個功能:獲取光驅設備列表,獲取光盤信息,添加媒體文件,刻錄,進度通知.spa
因工做電腦沒有光驅,測試很是不方便.那咱們就安裝一個虛擬光驅.
推薦一個比較好用的虛擬光驅軟件PhantomBurner,帶註冊碼.下載地址:https://download.csdn.net/download/zjhaag/10909339
安裝過程就不說了.選下安裝路徑,一路Next.安裝完成後提示重啓.其實不重啓也能夠用.
安裝完成後界面以下.在About中輸入註冊碼激活.點擊Create,選擇Dvd+RW建立Virtual Disc Image.在資源管理器中就能夠看到咱們建立的虛擬光驅了.
(1)首先添加一個RecorderHelper.在RecorderHelper類中添加一個靜態方法GetRecorderList用於獲取光驅設備列表.
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 }
此時,須要Recorder光驅對象主要屬性以下
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;}
(2)對Recorder各屬性進行初始化,賦值.主要方法以下
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("\r\n", ""); //去掉異常信息裏的\r\n 62 this.CurMediaStateName = $"COM Exception:{errMsg}"; 63 } 64 catch (Exception ex) 65 { 66 this.CurMediaStateName = $"{ex.Message}"; 67 } 68 }
(3)測試代碼以下
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
測試結果:
至此,咱們完成了對於光驅設備列表的獲取及Recorder對象各屬性的初始化工做.
說明下,對光驅設備操做須要有管理員權限,沒有管理員權限會致使獲取失敗.對於C#應用程序設置以管理員身份啓動請參照http://www.javashuo.com/article/p-epoagggb-gg.html
(1)咱們爲Recorder對象添加待刻錄媒體對象列表和待刻錄媒體文件大小兩個屬性
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; }
待刻錄媒體對象定義以下
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 }
(2)爲Recorder對象添加AddBurnMedia方法
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 }
(3)測試代碼以下
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 }
運行結果:
爲Recorder對象添加Burn方法.同時,添加刻錄進度通知.
(1)添加BurnProgressChanged委託用於通知刻錄進度
1 /// <summary> 2 /// 刻錄進度delegate 3 /// </summary> 4 public delegate void BurnProgressChanged(BurnProgress burnProgress);
刻錄進度通知對象定義以下(其屬性爲根據需求添加):
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 }
(2)爲Recorder對象添加委託屬性
1 /// <summary> 2 /// 刻錄進度變化通知 3 /// </summary> 4 public BurnProgressChanged OnBurnProgressChanged { get; set; }
(3)爲Recorder添加Burn方法
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 }
(4)測試代碼以下
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 }
(5)輸出刻錄進度變化,添加ShowBurnProgressChanged方法
在查找如何輸出進度數據的時候,看到了控制檯輸出進度條的功能.帶顏色的還挺漂亮的,看到好的功能就想加到咱們的項目裏.
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 }
運行結果以下,剩餘時間爲IMAPI2提供.並不必定準確.
在開始的時候,咱們說了使用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.FreeSectorsOnMedia和msFormat.TotalSectorsOnMedia類型爲int.你們想到緣由了吧.int溢出了.因此把後面的2048改成2048L就能夠了.看似正常的代碼,之後在碰到類型轉換時要多注意些.
總結寫點啥呢.固然是最重要的哈.上源碼:https://github.com/279328316/RecorderHelper
若有問題,歡迎留言.