如何从远程主机更新您的exe - c#4.0 - wpf应用程序

时间:2011-12-07 01:13:17

标签: c# wpf exe remote-host

我想从远程服务器更新我的exe。因此,当按钮单击我的wpf应用程序时,它将下载远程和远程txt文件,并替换exe运行的同一文件夹中的当前文件。所以它会在我的exe运行时覆盖当前的txt和exe文件。我怎么能做到这一点?

远程主机的网址类似于www.mydomain.com/MyAPP.exe

wpf应用程序,c#4.0

3 个答案:

答案 0 :(得分:2)

我们解决此问题的方法是创建一个shell exe,作为最初安装并部署到客户端计算机的shell。

“真正的”可执行程序存储在此初始应用程序的子目录中。启动shell应用程序后,在下载并安装了真实应用程序的任何更新后,它会在单独的AppDomain中启动真实应用程序的可执行文件。

以下是从shell应用程序中启动的“真实”应用程序的核心:

        System.AppDomainSetup oSetup = new System.AppDomainSetup();
        string sApplicationFile = null;

        // Use this to ensure that if the application is running when the user performs the update, that we don't run into file locking issues.
        oSetup.ShadowCopyFiles = "true";
        oSetup.ApplicationName = sAppName;

        // Generate the name of the DLL we are going to launch
        sApplicationFile = System.IO.Path.Combine(sApplicationDirectory, sAppName + ".exe");

        oSetup.ApplicationBase = sApplicationDirectory;
        oSetup.ConfigurationFile = sApplicationFile + ".config";
        oSetup.LoaderOptimization = LoaderOptimization.MultiDomain;

        // Launch the application
        System.AppDomain oAppDomain = AppDomain.CreateDomain(sAppName, AppDomain.CurrentDomain.Evidence, oSetup);
        oAppDomain.SetData("App", sAppName);
        oAppDomain.SetData("User", sUserName);
        oAppDomain.SetData("Pwd", sUserPassword);

        oAppDomain.ExecuteAssembly(sApplicationFile);

        // When the launched application closes, close this application as well
        Application.Exit();

请注意,在我们的版本中,shell应用程序会从用户收集用户名和密码,以便正确访问更新网站。然后,此数据将通过AppDomain上的SetData方法传递给“真实”应用。

答案 1 :(得分:2)

解决方案取决于您的具体情况。但是没有直接的解决方案,因为在将程序集加载到内存并使用时无法更新程序集。我可以提出两个解决方案:使用shadow copying并使用某种辅助可执行文件。我已经使用了它们。

影子复制。

显而易见的方法是将主要可执行文件复制为阴影,在应用程序运行时替换它,然后重新启动应用程序。但是无法使您的默认应用域被复制阴影,只有辅助应用域才可以。但您仍然可以将所有代码移动到另一个程序集(例如,MainAppLib.dll)并重写主应用程序可执行文件(MainApp.exe),使其仅包含“加载程序代码”。此加载程序代码必须创建另一个应用程序域,将其设置为阴影复制,然后在辅助应用程序域中运行程序逻辑。请注意,不要将主应用程序域直接引用到MainAppLib.dll中,因为这个程序集将被加载到主应用程序域中,而不会复制卷影并且程序集文件将被锁定。在大多数情况下,您可以使用AppDomain.ExecuteAssembly()方法。

帮助程式可执行文件

我们的想法是使用某种更新修整程序。您的主应用程序保持不变,您只需在其中添加少量代码,以便您的应用程序将下载更新,将其放入临时文件夹,然后您的主应用程序启动更新修整程序(在单独的过程中 )并退出。更新修整程序等待您的应用程序关闭,然后将新文件从临时文件夹复制到您的应用程序文件夹中,替换所有文件。更新修整程序不能替换它自己的可执行文件,但可以在启动更新修整程序之前由主应用程序完成。复制文件后,更新修整程序将运行您的应用程序。

p.s。就我个人而言,我更喜欢以前的解决方案,因为它涉及使用应用程序域,反射,程序集e.t.c的某种伏都教法术。如果需要,它可以演变为使用插件(例如通过MEF framework)。但后者更容易理解,特别是如果您从未使用过应用程序域和手动程序集加载,那就非常简单了。

答案 2 :(得分:1)

你可能会使用ClickOnce(基于你上面的评论,你会准备让另一个程序集获得exe ...因为另一个海报提到你无法替换正在运行的程序集)。您可以将其配置为在新版本的不同时间(例如在启动时)进行检查,并自动下载它们。它是一个非常强大的解决方案,您可以使用部署程序集做很多事情。