Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/337.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何从远程主机-c#4.0-wpf应用程序更新exe_C#_Wpf_Exe_Remote Host - Fatal编程技术网

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

如何从远程主机-c#4.0-wpf应用程序更新exe,c#,wpf,exe,remote-host,C#,Wpf,Exe,Remote Host,我想从远程服务器更新我的exe。因此,当按钮点击我的wpf应用程序时,它将下载远程文件和远程txt文件,并替换运行exe的同一文件夹中的当前文件。因此,当我的exe正在运行时,它将覆盖当前的txt和exe文件。我怎样才能做到这一点 远程主机的url类似于www.mydomain.com/MyAPP.exe wpf应用程序,c#4.0解决此问题的方法是创建一个shell exe,作为最初安装并部署到客户端机器的shell exe “真正的”可执行程序存储在此初始应用程序的子目录中。启动shell应

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

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


wpf应用程序,c#4.0解决此问题的方法是创建一个shell exe,作为最初安装并部署到客户端机器的shell exe

“真正的”可执行程序存储在此初始应用程序的子目录中。启动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
方法传递到“real”应用程序。

解决方案取决于您的具体情况。但是没有直接的解决方案,因为当程序集加载到内存中并被使用时,您无法更新程序集。我可以提出两种解决方案:使用和使用某种助手可执行文件。我两个都用过

卷影复制。

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

助手可执行文件

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


p.s.我个人更喜欢前一种解决方案,因为它涉及使用应用程序域、反射、组件(如t.c.)的某种巫毒魔法,如果需要,它可以演变为使用插件(如通过)。但后者更容易理解,特别是如果您从未使用过应用程序域和手动程序集加载,它非常简单。

您可能可以使用(根据您上面的评论,您将准备让另一个程序集获得exe…正如另一张海报所述,您无法替换正在运行的程序集)。您可以将其配置为在不同时间(例如启动时)检查新版本,并自动下载。这是一个非常健壮的解决方案,您可以对部署程序集做很多工作。

您无法更新正在运行的程序。更新程序必须是一个单独的可执行文件,在要更新的应用程序未运行时运行。那么,最好的方法是什么呢。我想当点击按钮时,它会调用更新程序exe,然后退出。我该怎么做?