1

我有一些 UI 应用程序,它位于用 C# 编写的用户任务栏中。该工具的 EXE 已在许多使用它的项目上签入我们的源代码控制系统,因此我们能够通过签入更新的 EXE 来更新它们运行的​​版本。

问题是当用户获得最新版本的 exe 时,程序经常在运行,并且在他们的机器上同步失败。我想修复它,这样程序在运行时就不会锁定 exe 和任何依赖的 DLL,这样它们就可以同步而不必关闭程序。

目前,我有一个程序将可执行文件作为参数,并通过提前将程序集内容读入内存来从内存中启动它。不幸的是,当涉及到程序所需的 DLL 时,这完全失败了。

我现在拥有的代码如下所示:

public class ExecuteFromMemory
{
    public static void Main(string[] args)
    {
        //Figure out the name of the EXE to launch and the arguments to forward to it
        string fileName = args[0];
        string[] realArgs = new string[args.Length - 1];
        Array.Copy(args, 1, realArgs, 0, args.Length - 1);

        //Read the assembly from the disk
        byte[] binary = File.ReadAllBytes(fileName);

        //Execute the loaded assembly using reflection
        Assembly memoryAssembly = null;
        try
        {
            memoryAssembly = Assembly.Load(binary);
        }
        catch (Exception ex)
        {
            //Print error message and exit
        }

        MethodInfo method = memoryAssembly.EntryPoint;
        if (method != null && method.IsStatic)
        {
            try
            {
                method.Invoke(null, new object[] { realArgs });
            }
            catch(Exception ex)
            {
                //Print error message and exit
            }
        }
        else
        {
            //Print error message and exit
        }
    }
}

我的问题是,我在做一些完全愚蠢的事情吗?有没有更好的方法来处理这个?如果不是,我应该怎么做才能支持处理外部依赖项?

例如,如果您尝试运行使用“Bar.dll”中的函数的“Foo.exe”,上述代码无法加载任何依赖文件,“Foo.exe”将是可覆盖的,但“Bar.dll”仍然是被锁定并且不能被覆盖。

我尝试从加载的程序集上的“GetReferencedAssemblies()”方法获取引用程序集的列表,但这似乎没有给出任何指示应该从哪里加载程序集......我需要自己搜索它们吗?如果是这样,最好的方法是什么?

似乎其他人以前可能遇到过这种情况,我不想重新发明轮子。

- 更新:EXE 已签入,因为这就是我们将内部工具分发给使用它们的团队的方式。它不是这个用例的最佳选择,但我没有机会更改该策略。

4

3 回答 3

4

免责声明:我不使用 Windows,尽管我熟悉它奇怪的锁定方式。

为了在应用程序运行时更新它,您可能需要有两个进程:可执行文件本身,以及将完成更新过程的更新“帮助”应用程序。假设您的应用程序是 ProcessA.exe,而您的更新助手是 Updater.exe。您的主程序将下载可执行文件的新副本,并以随机名称保存。然后你运行你的更新程序,它会监视你当前进程的终止。当您的进程终止时,它会显示一个显示更新状态的快速窗口,将新的可执行文件移动到旧可执行文件的位置,然后重新启动该程序。

能够模拟 POSIX 文件系统语义并能够删除当前运行的进程磁盘映像并将其替换为新文件会更加优雅,但我不知道这在 Windows 上是否可行。在 POSIX 系统上,您可以删除一个正在使用的文件,并且在关闭任何剩余的文件句柄之前它实际上不会被删除,尽管您可以重用文件名。

您可能想查看在CodeProject上写的一篇关于此的文章。它还有一篇后续文章

祝你好运!

于 2009-02-27T16:47:21.857 回答
1

程序是否需要在更新时保持运行?

通常,要更新正在运行的程序,您会将要替换的任何文件复制到临时文件夹中。然后关闭旧实例,删除它并将新文件移动到正确的位置,然后重新启动它。

这允许应用程序的最小停机时间,因为最长的部分通常是副本,如果临时文件夹位于同一逻辑驱动器上,则文件移动非常快。

于 2009-02-27T16:46:47.083 回答
0

Although Michael's answer is one way of doing this, there are tools out there that are explicitly for managing what's installed on the desktop.

What you are doing with the exe being checked into source control is not normal. If you have a windows domain controller, you can use Group Policy to push programs down to the client. Alternatively, you could use something like Altiris to handle it.

If you must continue the way you are going then you have two options. One, using a helper / loader app which does a version check on launch. This is similar to how firefox works.

The second way is to build a helper service that sits in memory and polls every so often for updates. This is how Google Chrome, Adobe, etc work.

于 2009-02-27T17:53:00.777 回答