一种不使用ClickOnce的.NET WinForms应用程序更新方式是什么?

23

由于技术原因,我无法使用ClickOnce自动更新我的.NET应用程序及其子程序集。在.NET中处理自动更新的最佳方法是什么?


什么“技术原因”阻止您使用ClickOnce,这些原因将会成为您寻找答案时的限制条件? - lotsoffreetime
1
在我看来,最好的技术原因是不允许将安装程序安装到全局程序集缓存(GAC)。这是我对ClickOnce的主要抱怨之一。 - MagicKat
什么?ClickOnce 的哪个部分会安装到 GAC? - Matt Hamilton
哦,我明白了。你不喜欢它不能安装到全局程序集缓存(GAC)。我以为你在抱怨它试图将东西放入 GAC,而你不想要它。说得对。 - Matt Hamilton
2
ClickOnce 在紧凑框架上无法工作。 - MusiGenesis
显示剩余2条评论
9个回答

16
我们有一个商业/开源产品:wyBuild & wyUpdate。它具有修补能力,并且非常易于使用。
编辑:我的帖子并不是仅仅为了推销。我们的更新程序wyUpdate是开源的,用C#编写,并在BSD许可下获得许可。
我认为这可能会对任何试图使用.NET框架从头开始构建更新程序的人有所帮助。
但是,如果必须的话,请投票反对我。

这对紧凑框架部署有何帮助? - ctacke
1
我们的开源更新程序可能在开发您自己的更新程序时非常有用。它是用C#编写的,并在BSD许可下获得许可。但如果您必须这样做,请投我反对票。 - Wyatt O'Day

9

我认为更新应用程序块是 ClickOnce 的前身。值得研究。查看其源代码可能足以激发一些想法。


谢谢!这正是我几年前所记得阅读的内容。 - MusiGenesis
4
现在我想起来为什么我从未使用它了。天哪。 - MusiGenesis
哈哈!是啊,应用程序块有点令人望而生畏。我也从未使用过它们。 - Matt Hamilton
此安装需要 .NET Framework 版本 1.1.4322... 天啊,这个东西太老了。 - Cameron MacFarland
Updater Application Block是一个已经停用的项目,详情请见http://msdn.microsoft.com/en-us/library/ms978574.aspx。 - Junior Mayhé
@MattHamilton 这篇文章已经无法获取了。 - Tassisto

2

如果您想自己编写软件更新功能,建议先查看Alex Feinman在MSDN上的文章,该文章名为“使用.NET Compact Framework创建自更新应用程序”。


2

大约3-4年前,我发布了一个示例,它位于应用程序之外。如果检测到更新,则应用程序调用更新程序并关闭,然后进行更新,最后重启应用程序。

我在旧的GotDotNet网站上发布了这个示例...我得试着找到它。

它完美地工作,并且编写时间大约为1-2小时。


1
我在应用程序中有一个方法,如果发现更新程序的更新,它将应用该更新。基本上,每个更新都会更新另一个,听起来复杂且难以管理,但实际上非常简单。我想至少我还在家里某个地方有这段代码。 - Mitchel Sellers
我仍在努力寻找示例代码。它曾经发布在一个旧的微软网站上...但他们关闭了该网站和示例... - Mitchel Sellers

2
Indigo Rose有一个名为TrueUpdate的产品,也可以为您完成此操作。我以前从托管和非托管应用程序中都使用过它们。它基本上是一个文件,您将其放在服务器上(http、ftp或任何您喜欢的方式)。然后您调用客户端EXE来检查更新。更新文件被拉取,并具有检测客户端版本的逻辑(您选择,DLL检测、注册表键读取等)。然后它会找到相应的更新程序并下载执行文件。它还可以通过代理很好地工作。
唯一的问题是它实际上不会为您构建补丁。您必须手动完成这项工作,或使用他们拥有的另一个产品。这是一种商业解决方案,如果需要,它非常有效。

看起来很酷,谢谢,但不支持Windows Mobile。这个应用程序有点不同,因为它可以在Windows Mobile和普通PC Windows中运行。 - MusiGenesis

1

自己写。

我听说第一次写可能有些困难,但之后就会变得简单。

由于我还没有写过(虽然在我的清单上),我可以告诉你我想到的一些事情。保持准确的dll版本,因为这对于自更新很重要。并确保更新程序可以更新自身。


做那件事真的很有趣!我是通过让应用程序更新更新器来完成的。 - Vincent McNabb
在我们公司,自己开发更新程序花了好几个月的时间,但现在我们拥有了一个非常熟悉且可以随意调试的更新程序。这真的是值得的。 - Dinah

1
很久以前,在一個使用 .NET Compact Framework 1.0 的專案上,我寫了一個自動更新的應用程序。我們使用 SqlCE 的 CAB 部署功能將文件傳輸到設備上(現在你可以使用 Sync Framework),我們有一個獨立的 exe 程序來解壓 CAB,並更新文件。
更新過程如下:用戶會被提示更新,點擊按鈕退出 UI 應用程序。更新程序 exe 將接管,從服務器獲取 cab 文件,備份當前的 dll 文件和使用 wceload 解壓 cab 文件。然後重新啟動 UI,如果失敗,則回滾更新。這仍然是一個有趣的情況,但現在有比只使用 sqlce 更好的工具。
如果 clickonce 不可行,我肯定會考慮使用更新程序塊和同步框架來實現此功能。但我猜你仍然需要一個獨立的可執行文件,因為你想覆蓋的 dll 文件可能正在被一個 exe 使用時鎖定,就像之前的答案中說的那樣。

你如何在UI关闭后让升级exe接管?它是否一直运行并轮询以查看是否需要更新?我尝试过在另一个进程中自动启动更新程序,但仍然无法覆盖原始运行的EXE。 - MusiGenesis
我不太记得了,但你可以使用ManualResetEvent或类似的机制来实现这个。作为最后一个操作,退出UI会触发一个系统级事件。当更新程序下载CAB文件、解压缩并尝试覆盖UI exe时,UI已经退出很久了。 - stombeur

1

我编写了自己的自动更新程序,该自动更新程序使用一个通用配置文件来应用程序,其中包含从中下载最新版本的URL / 检查是否需要更新。

这样,您运行更新程序,它会更新应用程序或不更新,然后运行应用程序,作为正常操作的一部分,检查是否有更新的更新程序并修补它。


1
在你的 Program.cs 文件中,可以像这样做:
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Update();
        Application.Run(new Form1());
    }

    private static void Update()
    {
        string mainFolder;
        string updateFolder;
        string backupFolder;

        foreach (string file in
            System.IO.Directory.GetFiles(updateFolder))
        {
            string newFile = file.Replace(
                updateFolder, mainFolder);

            if (System.IO.File.Exists(newFile))
            {
                System.IO.File.Replace(file, newFile, backupFolder);
            }
            else
            {
                System.IO.File.Move(file, newFile);
            }
        }
    }

此外,如果需要,它可以递归地获取目录结构。这将允许您更新项目中的任何.dll文件;实际上是除了主.exe之外的所有内容。然后在应用程序的其他位置,您可以处理从服务器(或其他地方)获取需要更新的文件,将其放入updateFolder并重新启动应用程序。

谢谢。我的问题主要是针对自更新(即从主EXE内部更新主EXE)。 - MusiGenesis
你不能从exe本身更新exe,因此仍然需要外部进程。 - Mitchel Sellers
当然可以。您可以将exe文件重命名,对旧版本排队执行“在重启后删除”命令,并复制新版本。旧应用程序随后可以运行新应用程序并立即退出,可能会传递某种/upgrade参数,以便新应用程序知道可能需要更新的旧存储数据结构。 - Sander

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接