您好。
我们正在用WPF在C#的学校自助餐厅创建一个销售控制系统,该系统将在我们网络中的18所学校实施。(学校分散在城市各处,因此,系统更新将通过互联网自动进行)。
研究了ClickOnce(开发了类似的东西),我们知道这种类型的更新是不可行的。
我们使用DotNetZip API创建了一个系统更新,但在将文件保存到安装了系统文件的目录中时出现错误,原因是与其他问题不兼容。
我的问题如下:
有人在这方面有任何经验可以与我分享吗,或者有任何情况的例子(就像这样),这样我们就可以在我们的系统中应用了吗?
我将把更新系统以创建的代码片段放在这里,如果有人想要分析它,它将更容易理解问题。
此代码的逻辑搜索XML文件的可用系统版本,并将其与程序集的版本进行比较。如果版本更高,则向下到临时目录更新文件并传输到安装应用程序的目录。出现的问题是,某些类型的文件即使在与主应用程序一起完成后,看起来也像是在运行。
我很感激你的帮助。
调用更新程序的主窗体
private void Window_Loaded(object sender, RoutedEventArgs e)
{
var doc = new XmlDocument();
doc.Load("http://www.meusite.org.br/Cantina/arquivoXML.xml");
if (doc.DocumentElement != null)
{
var node = doc.DocumentElement.SelectSingleNode("/Application/Version");
var node1 = doc.DocumentElement.SelectSingleNode("/Application/ZipFile");
if (node != null)
{
var version = node.InnerText;
var versionAssembly = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString();
if (Convert.ToDouble(version) > Convert.ToDouble(versionAssembly))
{
Process.Start("Updater.exe");
}
}
}
}
更新程序系统:
using System.Diagnostics;
using Ionic.Zip;
using System.Xml;
using System.IO;
namespace Updater
{
public class Program
{
private static void Main()
{
Process[] process = Process.GetProcessesByName("IASD.ASCS.WPF");
foreach (Process proc in process)
{
if (!proc.HasExited)
proc.Kill();
}
XmlDocument doc = new XmlDocument();
doc.Load("http://www.meusite.org.br/Cantina/arquivoXML.xml");
if (doc.DocumentElement != null)
{
XmlNode node1 = doc.DocumentElement.SelectSingleNode("/Application/ZipFile");
if (node1 != null)
{
string zipfile = node1.InnerText;
const string end = ("http://www.meusite.org.br/Cantina/");
string file = (end + zipfile);
ZipFile zipFile = ZipFile.Read(file);
{
foreach (var zipEntry in zipFile)
{
zipEntry.Extract(@"c:IASDCantinaEscolarTemp",ExtractExistingFileAction.OverwriteSilently);
}
}
string dirTemp = @"c:IASDCantinaEscolarTemp";
string dirInstalacao = @"c:IASDCantinaEscolar";
string[] arquivos = Directory.GetFiles(dirTemp);
foreach (string item in arquivos)
{
string nomedoarquivo = Path.GetFileName(item);
if (nomedoarquivo != null)
{
string destino = Path.Combine(dirInstalacao, nomedoarquivo);
File.Copy(item, destino, true);
}
}
string[] arquivosApagar = Directory.GetFiles(dirTemp);
foreach (string item in arquivosApagar)
{
File.Delete(item);
}
Process.Start("IASD.ASCS.WPF.exe");
}
}
const string nomeExecutavel2 = "Updater.exe";
foreach (Process pr2 in Process.GetProcessesByName(nomeExecutavel2))
{
if (!pr2.HasExited) pr2.Kill();
}
}
}
}
在这个例子中,我正在确定系统将安装在哪个位置,但我是否需要向用户提供安装在您计算机上任何目录中的信息(这是我无法解决的另一个问题)。
当您正在进行更新并且应用程序仍在运行时,您无论如何都可以进行更新,但您必须重命名所有文件,然后粘贴新文件。应用程序将保持正常运行,直到下一次应用程序重新启动。
我们的流程如下:
- 检查更新
- 下载更新zip
- 将所有文件重命名为*.old
- 将zip文件提取到应用程序位置
- 关闭(终止)并重新启动应用程序
- 启动时删除*.旧文件
我们从未遇到过这种行为的任何问题,但也许您不想为应用程序实现互斥,这样您就可以确保同时只有一个实例在运行。
在Window_Loaded事件中开始下载后,原始进程将继续运行。当下载程序尝试替换exe文件时,它使用的任何文件都将失败。
启动更新程序Process.Start("Updater.exe");
后,您需要退出当前进程,并确保它根本没有运行。您可以添加以下行:
if (Convert.ToDouble(version) > Convert.ToDouble(versionAssembly))
{
Process.Start("Updater.exe");
Application.Exit(); // Assumes a WinForms app
}