【发布时间】:2015-03-31 23:21:57
【问题描述】:
好的,我正在开发一个游戏启动器。它检查更新,如果存在,它会被下载并解压缩。解压缩完成后,将新文件复制到需要的位置,然后删除 zip 和解压缩的文件。
问题是这样的:如果用户在解压缩时关闭了启动器,下次他们启动它时,我在解压缩时收到错误 - 文件已经存在。
所以我想做的是在退出时删除 Patch 文件夹。但是,如果后台工作人员正在运行,则无法删除该资源,因为它正在被另一个进程使用。
下载器类:
static void downloader_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
if (!Directory.Exists(Path.Combine(BASE_DIR, "Patch")))
Directory.CreateDirectory(Path.Combine(BASE_DIR, "Patch"));
string sFilePathToWriteFileTo = Path.Combine(BASE_DIR, "Patch", "patch.zip").ToString();
// first, we need to get the exact size (in bytes) of the file we are downloading
Uri url = new Uri(sUrlToReadFileFrom);
System.Net.HttpWebRequest request = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(url);
System.Net.HttpWebResponse response = (System.Net.HttpWebResponse)request.GetResponse();
response.Close();
// gets the size of the file in bytes
Int64 iSize = response.ContentLength;
// keeps track of the total bytes downloaded so we can update the progress bar
Int64 iRunningByteTotal = 0;
// use the webclient object to download the file
using (System.Net.WebClient client = new System.Net.WebClient())
{
// open the file at the remote URL for reading
using (System.IO.Stream streamRemote = client.OpenRead(new Uri(sUrlToReadFileFrom)))
{
// using the FileStream object, we can write the downloaded bytes to the file system
using (Stream streamLocal = new FileStream(sFilePathToWriteFileTo, FileMode.Create, FileAccess.Write, FileShare.None))
{
// loop the stream and get the file into the byte buffer
int iByteSize = 0;
byte[] byteBuffer = new byte[1024];
double dTotal = (double)iSize;
while ((iByteSize = streamRemote.Read(byteBuffer, 0, byteBuffer.Length)) > 0)
{
// write the bytes to the file system at the file path specified
streamLocal.Write(byteBuffer, 0, iByteSize);
iRunningByteTotal += iByteSize;
// calculate the progress out of a base "100"
double dIndex = (double)(iRunningByteTotal);
double dProgressPercentage = (dIndex / dTotal);
int iProgressPercentage = (int)(dProgressPercentage * 100);
// update the progress bar
worker.ReportProgress(iProgressPercentage);
}
// clean up the file stream
streamLocal.Close();
}
// close the connection to the remote server
streamRemote.Close();
}
}
}
然后是解压器:
private void decompresser_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
#region Unzip files
if (!Directory.Exists(decompressPath))
Directory.CreateDirectory(decompressPath);
using (ZipArchive archive = ZipFile.OpenRead(archiveName))
{
int iTotal = archive.Entries.Count();
int curr = 0;
foreach (ZipArchiveEntry entry in archive.Entries)
{
if (entry.FullName != entry.Name)
{
if (entry.Name == string.Empty)
{
//create folder here
Directory.CreateDirectory(Path.Combine(decompressPath, entry.FullName));
}
else
{
//create folder and extract file into it
string dirToCreate = entry.FullName.Replace(entry.Name, "");
Directory.CreateDirectory(Path.Combine(decompressPath, dirToCreate));
entry.ExtractToFile(Path.Combine(decompressPath, entry.FullName));
}
}
else
{
//just extract file
Console.WriteLine(Path.Combine(decompressPath, entry.FullName));
entry.ExtractToFile(Path.Combine(decompressPath, entry.FullName));
}
curr++;
var progress = ((double)curr / (double)iTotal) * 60.0;
worker.ReportProgress((int)progress);
}
}
//delete zip file
File.Delete(Path.Combine(BASE_DIR, "Patch", "patch.zip"));
#endregion
#region Copy files
string sourceDirName = Path.Combine(BASE_DIR, "Patch");
string destDirName = BASE_DIR;
DirectoryInfo dir = new DirectoryInfo(sourceDirName);
long maxbytes = 0;
List<FileInfo> files = new List<FileInfo>();
FileInfo[] folder = dir.GetFiles("*.*", SearchOption.AllDirectories);
foreach (FileInfo file in folder)
{
if ((file.Attributes & FileAttributes.Directory) != 0) continue;
files.Add(file);
maxbytes += file.Length;
}
// Copy files
long bytes = 0;
foreach (FileInfo file in files)
{
try
{
//where to copy
string copyPath = file.FullName.Replace("Patch\\", "").Replace(file.Name, "");
if (!Directory.Exists(copyPath))
Directory.CreateDirectory(copyPath);
File.Copy(file.FullName, Path.Combine(copyPath, file.Name), true);
var progress = 60 + ((double)bytes / (double)maxbytes) * 30.0;
worker.ReportProgress((int)progress);
}
catch (Exception ex)
{
}
bytes += file.Length;
}
#endregion
#region Clean Up
foreach (FileInfo file in files)
{
try
{
var progress = 90 + ((double)(maxbytes - file.Length) / (double)maxbytes) * 9;
file.Delete();
worker.ReportProgress((int)progress);
}
catch (Exception ex) { }
}
try
{
string delPath = Path.Combine(BASE_DIR, "Patch");
Directory.Delete(delPath, true);
}
catch (Exception ex) { }
worker.ReportProgress(100);
#endregion
}
我通过调用App.Current.Shutdown(); 方法终止应用程序。
【问题讨论】: