好的,所以我正在开发游戏发射器。它会检查更新,如果存在,则会下载并解压缩。解压缩完成后,将新文件复制到需要的位置,然后删除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();
方法终止应用程序。
答案 0 :(得分:0)
如果我没有遗漏任何东西,那么有一个非常简单的解决方案。
您可以使用退出时的应用程序event通过调用workerObject.RequestStop();
来停止所有后台工作人员(请注意,它仅表示工作人员中已经请求停止的代码,您需要在工作人员的工作中处理此问题)循环停止工作)。然后你可以清理补丁文件夹。
答案 1 :(得分:0)
作为对此问题的回避,您是否还可以在启动应用程序时删除补丁文件夹,但在开始下载之前?
答案 2 :(得分:0)
@GWLlosa - 我确实考虑过在发布时删除文件,如果需要的话,但如果我找不到更好的东西,我会把它作为最后的手段保存
我试过这样的事情
protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
{
updater.CancelAsync();
while (updater.IsBusy)
{
Thread.Sleep(100);
}
//run code to delete the files after the worked has stopped
}
但这只会让我陷入无限循环:)
答案 3 :(得分:0)
如果我这样做,我会在启动后立即查找并终止下载过程。
Process[] p = Process.GetProcessesByName("processname");
foreach (var proc in p)
{
proc.Kill();
}
答案 4 :(得分:0)
我有2个解决方案可以解决您的问题。
1)不要试图在退出时删除补丁文件夹,只需要激活&amp;忘记BackgroundWorker,如果用户取消补丁并退出,那么只需退出应用程序。但是在用户启动你的应用程序时总是删除补丁文件夹,特别是在你调用解压缩之前。
2)如果您仍想在退出时删除补丁文件夹,则使用CancelAsync()函数取消BackgroundWorker。例如
private void btnStart_Click(object sender, EventArgs e)
{
if (btnStart.Text == "Start")
{
...
}
else
{
m_bgWorker.CancelAsync();
}
}
private void SearchFiles(string strPath, string strPattern)
{
string strMessage = "Parsing directory " + strPath;
m_bgWorker.ReportProgress(0, strMessage);
foreach (string strFileName in Directory.GetFiles(strPath, strPattern))
{
if (m_bgWorker.CancellationPending)
{
return;
}
else
{
m_lstFiles.Add(strFileName);
}
}
foreach (string strDirName in Directory.GetDirectories(strPath))
{
if (m_bgWorker.CancellationPending)
{
return;
}
else
{
SearchFiles(strDirName, strPattern);
}
}
}
我收到了此post的代码表单。您可以从该示例中阅读更多内容,以了解作者如何取消他的BackgroundWorker。