返回首页

{A}介绍
有些应用程序可能需要定期更新自己。通常情况下,其目的通常是高度可扩展的应用程序可能更新几个模块,从而可以得到新的能力和功能一样的插件,动态。
。NET应用程序可以采取单独的AppDomain中加载更新模块的优势和卸载更新可用时重新更新组件。您可能会遇到的一个问题是,加载的程序集文件被锁定,这样可以防止替换它们。如果您使用的是单独的AppDomain中加载程序集,那么解决的办法是更容易。这实际上使得在装货前大会的一个副本,因此原来的组件保持解锁和应用程序运行时,您可以替换他们的AppDomain中,您可以启用卷影副本功能。
如果你不使用一个单独的AppDomain中,你要更新的组件,包括你的应用程序EXE,然后你需要做的一些棘手的事情,在本文的其余部分解释。背景
我想从根本上运行的应用程序,并让应用程序更新自身的EXE和其他一些位置偏远的集会。这就需要在这样一种方式,它不锁定它的组件,通常发生应用程序启动时启动应用程序。如果应用程序可以自行更新,应用程序分发,可以从一个集中的位置。我不包括任何下载本文中的程序集的逻辑。使用代码
我发现如下问题的解决方案。解决方案之一
在这里,我已与主应用程序一起使用额外的应用程序(即Starter.exe)。在Starter.exe应该是目前在应用程序的备份目录开始。如果您正在下载的代码,然后确保你复制后建设Startup.exe。
解决方法一的代码如下:

internal static class Program

    {

        private static readonly string DomainName = "MarvinDomain";

        private static readonly string CatchFolder = "AssemblyCatch";



    

        [STAThread]

        private static void Main()

        {

if (AppDomain.CurrentDomain.FriendlyName != DomainName)

{

    string exeFilePath = Assembly.GetExecutingAssembly().Location;

    string applicationFolder = Path.GetDirectoryName(exeFilePath);



    string starterExePath = applicationFolder + "\\Starter.exe";

    //Debugger.Launch(); // You can uncomment to automatically launch VS for debugging

    //Solution one - Using Separate EXE to start application.

    if (File.Exists(starterExePath)) // Check if starter EXE is available

    {

        XmlSerializer serialier = new XmlSerializer(typeof(AppDomainSetup));

        string xmlFilePath = applicationFolder + "\\XmlData.xml";

        using (var stream = File.Create(xmlFilePath))

        {

	serialier.Serialize(stream, AppDomain.CurrentDomain.SetupInformation);

        }



        exeFilePath = exeFilePath.Replace(" ", "*");

        xmlFilePath = xmlFilePath.Replace(" ", "*");

        string args = exeFilePath + " " + xmlFilePath;



        Process starter = Process.Start(starterExePath, args);

    }

应用程序的Main方法,检查当前的AppDomain的FriendlyName,如果它匹配到一个特定的域名(即MarvinDomain)。这可以是任何你想要的。
如果名称不匹配,那么应用程序检查如果Starter.exe是在其启动路径。如果得到这个EXE,启动新的进程,并将推出Starter.exe。同时发动新工艺,它传递两个字符串参数:其自身的EXE路径XML文件的路径。
应用程序序列化到XML文件为当前AppDomain的AppDomainSetup,它作为第二个字符串参数传递。
注意,我已经取代了星在文件路径中的空格,因为如果空间是存在的,它会产生额外的参数。
Starter.exe运行时,它接收我们的主应用程序和XML文件,其中包含从在其主要方法的字符串参数序列的AppDomainSetup路径EXE路径。然后,它创建新的AppDomain和卷影副本功能,使这个新创建的域。这样做,它使得使用反序列化的AppDomainSetup和更改相关的属性。如果反序列化的AppDomainSetup不可用,它创建一个新的。然后,它运行的应用程序,例如,我们在这个新领域的主要应用。起动器的应用代码{C}
当应用程序运行在新的域名具有预期的名称,这个时候,我们的主要应用将尽其正常工作,如运行MainForm的,而不是寻找Starter.exe。
检查演示,下载二进制文件和单击"UpgradableApplication.exe这是一个WinForm application.You会注意将启动文件夹内创建一个组件的附加渔获文件夹和所有组件将被复制到这个文件夹"。以确保我们的UpgradableApplication.exe没有被锁定,您可以删除的文件,而在应用程序运行。解决方案二
虽然解决方案的一个工程,它需要额外的Startup.exe和,如果你看一下进入Windows任务管理器,你会看到名称,而不是我们的主EXE Starter.exe。
演示应用程序使用的解决方案,如果没有找到Starter.exe。因此,检查该解决方案的演示,你可以重命名Starter.exe别的,将使用第二种方法。第二种方法是完全不同的。代码如下:
if (!applicationFolder.EndsWith(CatchFolder))

        {

string copyDirectoryPath = applicationFolder + "\\" + CatchFolder;

if (!Directory.Exists(copyDirectoryPath))

{

    Directory.CreateDirectory(copyDirectoryPath);

}

DateTime now = DateTime.Now;

string dateTimeStr = now.Date.Day.ToString() + now.Month.ToString() 

         + now.Second.ToString() + now.Millisecond.ToString();

string copyExePath = copyDirectoryPath + "\\CopyOf" +

          Path.GetFileNameWithoutExtension(exeFilePath)

         + dateTimeStr + ".exe";

           

File.Copy(exeFilePath, copyExePath,false );



Process.Start(copyExePath);

return;

        }



        Thread mainThread = new Thread(() =>

         {

 // Debugger.Launch();    // You can uncomment to automatically launch VS for debugging

 AppDomainSetup appDomainShodowCopySetup = AppDomain.CurrentDomain.SetupInformation;



 appDomainShodowCopySetup.ShadowCopyFiles = true.ToString();

 appDomainShodowCopySetup.ApplicationBase = applicationFolder.Replace(CatchFolder, "");

 appDomainShodowCopySetup.CachePath = 

	Path.GetDirectoryName(exeFilePath) + "\\" + CatchFolder;

 //Configure shadow copy directories 

 //appDomainShodowCopySetup.ShadowCopyDirectories = "C:\\DllsToBeShadowCopyied";

 AppDomain marvinDomain = AppDomain.CreateDomain

			(DomainName, null, appDomainShodowCopySetup);



 marvinDomain.ExecuteAssembly(exeFilePath);



 AppDomain.Unload(marvinDomain);

         });



        mainThread.Start();

    }

    return;

}

这种方法也使得当前AppDomain的FriendlyName一起启动的应用程序路径的使用。应用检查启动路径,如果它不是从一个catch路径,然后复制EXE AssemblyCatch夹,并启动新的进程,使用新路径EXE。我已经使用的系统日期和时间,给一个唯一的名称复制EXE文件。当这个时候推出新工艺,它是从捕获的路径,现在这个时候,应用程序将创建一个新域影副本功能和将推出的这一新领域中的应用。当应用程序运行在新的领域,它具有有效的友好名称域,以及运行形式捕获的路径,所以这个时候,它会做其运行MainForm的正常工作。
我使用了一个新的线程,因为我遇到一个问题,卸载默认的主线程的AppDomain创建一个新的AppDomain。
它是由应用程序开发人员如何得到更新时。应用程序可能会保持定期检查,更新背景,如果它发现,它会下载。应用程序可以通知用户重新启动应用程序,或者如果可能的话,它可以重新启动,并得到,新changes.You可以指定文件夹,从该组件将使用的AppDomainSetup属性ShadowCopyDirectories复制。为了防止重新启动整个应用程序,你也可以设计更新只有少数的模块,它可以是单独的域,可以卸载并重新加载一次更新是可用的应用程序。景点
在这里,我已经设法使启用卷影副本默认应用程序域。因此,原有的应用程序集仍然上锁,并可以由应用程序本身取代。与几个模块的阴影复制,您可以确保您的应用程序可以继续运行,永远没有重新启动,并仍在更新。

回答

评论会员:ShdNx 时间:2012/02/04
我的应用程序,我只是复制更新程序的所有文件到%temp%,并从那里运行。这样,有没有锁定问题,并在所有的语言(甚至那些没有一个AppDomain的概念)。
它需要很少的编码和它引起的任何问题,我还没有见过。唯一你要注意的是自己清理后,即当他们不再需要删除的文件复制到%temp%。

尽管如此,您的AppDomain中神奇的解决方案是耐人寻味的,但我只是觉得它不必要地复杂
评论会员:游客 时间:2012/02/04
Prafulla混得:简单的始终是更好,如果它符合要求。如果你不需要更新DLL的应用程序正在运行您的解决方案better.In我们的实际应用中,有不同的模块,目前在各自的folders.Since他们有很多的二进制文件,我想一些如何更新,而应用程序是running.So时间可节省下载时,下一次应用starts.The真正的问题是加载的程序集不能replaced.This解决方案不锁定原来的DLL,并可以随时更新。如果不同的模块使用单独的AppDomain,那么我们可以卸载重装,甚至没有重新启动应用程序创建所需的对象。我错过了在演示应用清洁,这是非常需要我的情况,以及我认为没有必要给唯一的名称为temp文件夹well.Use也是适当的应用程序EXE。建议{S0的}感谢。prafulla
Prafulla混得:你的小编码更新任何示例代码? THX
AE
评论会员:ShdNx 时间:2012/02/04
,我一定会喜欢的份额,但它非常具体的项目和不能使用通用的解决方案
prafulla