C#语言实现光盘刻录功能

最近在项目中遇到一个需求,需要实现光盘刻录功能,由于项目使用的是C#语言,网上查阅了很多资劳和伪代码,很多都不能跑通,很多都是是引入了DLL后找不到方法,猜测应该是不同的版本导致的,经过一天的资料查阅和编写调试,终于是调通了全部的功能,这里将关键的伪代码分享如下。代码中有注释,对照着看就可以。

第一步,生成IOS镜像格式的文件,用于刻录。注意,这里制作ISO文件用到了DiscUtils库,直接通过NuGet搜素DiscUtils,这里不需要添加全部的DiscUtils,只需要添加引用DiscUtils.Iso9660即可。

生成需要刻录的ISO格式的文件
        /// <summary>
        /// 生成ISO格式的文件
        /// </summary>
        /// <param name="sourceDirectory"></param>
        /// <param name="isoFilePath"></param>
        public static void GenerateIsoFromDirectory(string sourceFilePath, string isoFilePath)
        {
            // 创建一个内存流,用于存储ISO文件
            using (MemoryStream isoStream = new MemoryStream())
            {

                DiscUtils.Iso9660.CDBuilder builder = new CDBuilder();
                builder.UseJoliet = true;
                builder.VolumeIdentifier = "A_SAMPLE_DISK";
                builder.AddFile("DicomImage.dcm", sourceFilePath);
                //这里如果需要添加多个文件,可以传入一个文件全路径的列表,使用循环来处理,可以制作成多文件夹模式,伪代码如下
                //假设List<string> sourceFilePathList 是一个文件全路径的文件列表,这里采用文件的上一级目录作为文件夹目录创建
                //foreach (var sourceFilePath in sourceFilePathList)
                //{

                //    //向上拿一级
                //    FileInfo file = new FileInfo(sourceFilePath);
                //    string sourceLastDectory = Directory.GetParent(sourceFilePath).Name;
                //    string isoFileName = sourceLastDectory + "\\" + file.Name;

                //    builder.AddFile(isoFileName, sourceFilePath);
                //}

                builder.Build(isoFilePath);
            }
        }

第二步,刻录功能的代码,将生成的ISO文件制作成光盘,这里需要用到IMAPI2接口,至于什么是IMAPI2,用来做什么的,这个网上资料非常多,就是一个Windows特有的支持刻录用的API。这里的两个关键命名空间的引入是using System.Runtime.InteropServices;using IMAPI2;

刻录功能
        /// <summary>
        /// 刻录功能
        /// </summary>
        /// <param name="deviceID">这里如果不传值,默认取第一个</param>
        /// <param name="isoFilePath">ISO文件</param>
        public static void DiscBurn(string deviceID, string isoFilePath)
        {
            MsftDiscRecorder2 recorder = null;
            MsftDiscFormat2Data dataWriter = null;

            try
            {
                //找到刻录机
                MsftDiscMaster2 discMaster = new MsftDiscMaster2();
                deviceID = discMaster[0];  //这里直接取第一个刻录机,如果有多个可以让用户选择
                //这里可以优先添加下判断,是否有找到刻录机,以及光盘大小是否有足够的空间刻录。
                //通常CD的标准容量是700MB,DVD的标准容量是4.7GB

                recorder = new MsftDiscRecorder2();
                recorder.InitializeDiscRecorder(deviceID);

                // Prepare the burn
                dataWriter = new MsftDiscFormat2Data();
                dataWriter.Recorder = recorder;
                dataWriter.ClientName = "IMAPI2 Test";

                IMAPI2.IStream isoStream = null;
                //将文件内容转换成Stream
                CreateStreamOnHGlobalFromFileAlternative(isoFilePath, out isoStream);

                dataWriter.Write(isoStream);
            }
            catch (Exception ex)
            {
                Console.WriteLine($"An error occurred: {ex.Message}");
            }
            finally
            {
                // Clean up
                if (dataWriter != null)
                {
                    Marshal.ReleaseComObject(dataWriter);
                }
                if (recorder != null)
                {
                    Marshal.ReleaseComObject(recorder);
                }
                // Delete temporary ISO image file (if created)
                //if (File.Exists(isoFilePath))
                //{
                //    File.Delete(isoFilePath);
                //}
            }
        }

        [DllImport("Ole32.dll", PreserveSig = false)]
        static extern void CreateStreamOnHGlobal(IntPtr hglobal, bool fDeleteOnRelease, out IMAPI2.IStream ppstm);

        // 下面的方法是一个替代实现,它使用System.IO来读取文件内容并创建IStream。
        static void CreateStreamOnHGlobalFromFileAlternative(string filePath, out IMAPI2.IStream ppstm)
        {
            byte[] fileData = System.IO.File.ReadAllBytes(filePath);
            IntPtr hGlobal = Marshal.AllocHGlobal(fileData.Length);
            try
            {
                Marshal.Copy(fileData, 0, hGlobal, fileData.Length);
                CreateStreamOnHGlobal(hGlobal, true, out ppstm);
                //ppstm.Seek(0, SeekOrigin.Begin);
                // 定位流
                long position = 0;
                //Seek(ppstm, 0, 0, out position);
            }
            catch
            {
                Marshal.FreeHGlobal(hGlobal);
                throw;
            }
        }

还有就是如果我们想去判断刻录的光盘是什么类型以及光盘的大小实时检测的话,我们可以用使用Windows Management Instrumentation (WMI)来获取信息并加以判断。以下是判断的伪代码。using System.Management;

获取刻录盘的信息
        /// <summary>
        /// 识别刻录机,
        /// 即使用WMI枚举系统中的CD/DVD驱动器,并检查是否支持刻录
        /// </summary>
        public static List<string> GetDivers()
        {
            List<string> deviceIDList = new List<string>();
            string query = "SELECT * FROM Win32_CDROMDrive";
            using (ManagementObjectSearcher searcher = new ManagementObjectSearcher(query))
            {
                foreach (ManagementObject drive in searcher.Get())
                {
                    string deviceID = drive["DeviceID"].ToString();
                    Console.WriteLine("设备ID: {0}", drive["DeviceID"]);
                    Console.WriteLine("名称: {0}", drive["Name"]);
                    Console.WriteLine("驱动号: {0}", drive["Drive"]);
                    Console.WriteLine("介质ID: {0}", drive["MediaLoaded"]);
                     // 获取光盘的总容量(以字节为单位)
                    Console.WriteLine("Capabilities: {0}", drive["Capabilities"].ToString());
                    // 获取光盘的可用空间(以字节为单位),注意:对于只读光盘驱动器,这个值可能不准确或不可用
                    ulong freeSpace = (ulong)drive["FreeSpace"];
                    Console.WriteLine("-----------------------");
                    //string deviceID = drive["DeviceID"].ToString();
                    //string capabilities = drive["Capabilities"].ToString();

                    //bool isRecorder = capabilities.Contains("3") || capabilities.Contains("27"); // "3" for CD-R/RW, "27" for DVD±R/RW
                    //if (isRecorder)
                    //{
                    //    Console.WriteLine($"Recorder found: {deviceID}");
                    //    deviceIDList.Add(deviceID);
                    //    // You can use this deviceID to interact with IMAPI2

                    //}
                }
            }
            return deviceIDList;

        }

posted @ 2025-01-06 09:41  奔四的大龄码农  阅读(86)  评论(0编辑  收藏  举报