文件数量较多的情况下如何提高刻录速度(调用IMAPI2实现DVD刻录功能)
在调用IMAPI2实现DVD刻录功能时,如果文件数量较多时,刻录占用的时间也较长,因此考虑先将刻录文件制作成ISO files,然后再刻录到DVD中。以此来优化刻录功能。
调用IMAPI2的方法在www.codeproject.com 有例子可以参考,网址为http://www.codeproject.com/KB/winsdk/IMAPI2.aspx 。在此就不再班门弄斧,下面讲讲Creating ISO files的方法。
1. 创建镜像文件
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using IMAPI2.Interop;
//Import this legacy Win32API...
[DllImport("shlwapi.dll", CharSet = CharSet.Unicode)] static internal extern uint SHCreateStreamOnFile (string pszFile, uint grfMode, out IStream ppstm);
//Create
IFileSystemImage ifsi = new MsftFileSystemImage();
ifsi.ChooseImageDefaultsForMediaType(IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_DISK);
ifsi.FileSystemsToCreate =
FsiFileSystems.FsiFileSystemJoliet | FsiFileSystems.FsiFileSystemISO9660;
ifsi.VolumeName = "YourVolume";
ifsi.Root.AddTree("c:\\YourDirToArchive", true);//use a valid folder
//this will implement the Write method for the formatter
IStream imagestream = ifsi.CreateResultImage().ImageStream;
if (imagestream != null)
{
System.Runtime.InteropServices.ComTypes.STATSTG stat;
imagestream.Stat(out stat, 0x01);
IStream newStream;
if (0 == SHCreateStreamOnFile
("C:\\YourImage.iso", 0x00001001, out newStream) && newStream != null)
{
IntPtr inBytes = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(long)));
IntPtr outBytes = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(long)));
try
{
imagestream.CopyTo(newStream, stat.cbSize, inBytes, outBytes);
Marshal.ReleaseComObject(imagestream);
imagestream = null;
newStream.Commit(0);
}
finally
{
Marshal.ReleaseComObject(newStream);
Marshal.FreeHGlobal(inBytes);
Marshal.FreeHGlobal(outBytes);
if (imagestream != null)
Marshal.ReleaseComObject(imagestream);
}
}
}
Marshal.ReleaseComObject(ifsi);
2. 增加单独的文件到镜像中
使用IFsiDirectoryItem记录文件的原始路径,使用Update事件跟踪进程。
private void CreateFSIFile(FileInfo file, IFsiDirectoryItem diritem)
{
string realpath = UniqueListFileSystemInfo.GetPhysicalPath(file.FullName);
int index = realpath.IndexOf(":\\") + 1;
if (_sysImage.Exists(realpath.Substring(index)) == FsiItemType.FsiItemNotFound)
{
IFsiDirectoryItem crtdiritem = diritem as IFsiDirectoryItem;
string name = Path.GetFileName(realpath);
if (string.Compare(diritem.FullPath,
Path.GetDirectoryName(realpath).Substring(index), true) != 0)
{
string fsipath = Path.GetDirectoryName(realpath).Substring
(index + 1 + diritem.FullPath.Length);
string[] dirs = fsipath.Split('\\');
//create the subdirs one by one
foreach (string dir in dirs)
{
if (dir.Length == 0)
continue;//in the root like C:\
try
{
string newpath = string.Format("{0}\\{1}", crtdiritem.FullPath, dir);
if (_sysImage.Exists(newpath) != FsiItemType.FsiItemDirectory)
crtdiritem.AddDirectory(dir);
}
catch
{
Cancel = true;
throw;
}
crtdiritem = crtdiritem[dir] as IFsiDirectoryItem;
}
}
System.Runtime.InteropServices.ComTypes.IStream newStream = null;
try
{
newStream = LoadCOMStream(realpath);
crtdiritem.AddFile(name, newStream);
}
finally
{
Marshal.ReleaseComObject(newStream);
}
_actualSize += ((FileInfo)file).Length;
if (Update != null && Update.GetInvocationList().Length > 0)
Update(file.FullName, ((FileInfo)file).Length);
}
else
throw new IOException("invalid file or folder");
}
参考文章:http://www.codeproject.com/KB/miscctrl/ISOImage.aspx?msg=2464574
更多的ISO制作的功能请参考How to Create Optical File Images using IMAPIv2.0 和 How to Burn Optical File Images with IMAPI 2.0 from Managed Code