Iam trying to build an iso file from a directory with discutils. This code works fine with a couple of files but after a while i throws an exception stating that "An object with the same key already exists" at "isoBuilder.AddFile(fileOnIso,br.BaseStream);". I don't understand why this happens can someone please shed some light?
public void AddtoISO(string directory,string isoFile)
{
BinaryReader br;
long bytesRemain = 0;
long totalBytesWritten = 0;
DirectoryInfo rootDirToAdd = new DirectoryInfo(sourceName);
DirectoryInfo currentDirToAdd = new DirectoryInfo(directory);
try
{
foreach (FileInfo file in currentDirToAdd.GetFiles())
{
string fileFullPath = file.FullName;
string fileOnIso = fileFullPath.Substring(fileFullPath.IndexOf(rootDirToAdd.Name) + rootDirToAdd.Name.Length + 1);
Console.WriteLine(fileOnIso);
br = new BinaryReader(file.OpenRead());
while(totalBytesWritten < file.Length)
{
bytesRemain = file.Length - totalBytesWritten;
br.ReadBytes(blockSize);
isoBuilder.AddFile(fileOnIso,br.BaseStream);
if(bytesRemain<blockSize)
{
totalBytesWritten += bytesRemain;
totalBytesAdded += bytesRemain;
}
else
{
totalBytesWritten += blockSize;
totalBytesAdded += blockSize;
}
}
itemsAdded++;
totalBytesWritten = 0;
}
foreach (DirectoryInfo subdir in currentDirToAdd.GetDirectories())
{
string folderFullPath = subdir.FullName;
string folderOnIso = folderFullPath.Substring(folderFullPath.IndexOf(rootDirToAdd.Name) + rootDirToAdd.Name.Length + 1);
isoBuilder.AddDirectory(folderOnIso);
itemsAdded++;
AddtoISO(subdir.FullName,isoFile,ctoken);
}
isoBuilder.Build(isoFile);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Console.WriteLine(ex.StackTrace);
}
}
Update An other possible implementation avoiding streams, the drawback is that it takes too much time (over 30 mins) on a 3GB iso which when built with ultraiso for example, it takes aprox 4 mins.. any ideas?
public void AddtoISO(string directory,string isoFile)
{
try
{
DirectoryInfo rootDirToAdd = new DirectoryInfo(sourceName);
DirectoryInfo currentDirToAdd = new DirectoryInfo(directory);
foreach (FileInfo file in currentDirToAdd.GetFiles())
{
string fileOnHdd = file.FullName;
string fileOnIso = fileOnHdd.Substring(fileOnHdd.IndexOf(rootDirToAdd.Name) + rootDirToAdd.Name.Length + 1);
Console.WriteLine(fileOnIso);
isoBuilder.AddFile(fileOnIso,fileOnHdd);
itemsAdded++;
}
foreach (DirectoryInfo subdir in currentDirToAdd.GetDirectories())
{
itemsAdded++;
AddtoISO(subdir.FullName,isoFile,ctoken);
}
isoBuilder.Build(isoFile);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Console.WriteLine(ex.StackTrace);
}
}
Update:
The exception is thrown when ever the directory structure is the following:
\boot\boot
It seems like it creates the key for boot directory and when it encounters boot.ext file it falsely thinks that it is a double addition. In other words when the files contains the name of its containing directory.
Test building dsl-4.11.rc1.iso
index.html boot boot\isolinux boot\isolinux\boot.cat boot\isolinux\boot.msg boot\isolinux\f2 boot\isolinux\f3 boot\isolinux\german.kbd boot\isolinux\isolinux.bin boot\isolinux\isolinux.cfg boot\isolinux\linux24 boot\isolinux\logo.16 boot\isolinux\minirt24.gz KNOPPIX KNOPPIX\KNOPPIX Problem on KNOPPIX\KNOPPIX
Update 2
At last some progress.. the error is not in any of the given paths but im my assumption that i had to keep calling isobuilder.Addfile() until the filestream has been added to the iso entirely.
I just had to move:
isoBuilder.AddFile(fileOnIso,br.BaseStream);
Before the foreach closing bracket. This way it will no have to be added again and again in the iso.
One final problem is at the line
isoBuilder.Build(isoFile);
Where it complains about the file being closed. I tried to correct it with:
FileInfo fi = new FileInfo(isoFile);
isoBuilder.Build(fi.OpenWrite());
But it didnt help. Please someone give me the final push to solve it.