【问题标题】:How to update .Net 4.x application without updating any dlls/exe?如何在不更新任何 dll/exe 的情况下更新 .Net 4.x 应用程序?
【发布时间】:2012-10-19 14:36:51
【问题描述】:

我需要为使用 .Net 4.0 或 4.5 构建的桌面应用程序开发自动更新机制。它不应下载或更新任何 dll 或 exe 文件。这是公司的政策,我不能改变。

但是,允许下载任何类型的脚本、c# 代码、xml、json、xaml 等,这些脚本可以存储在此应用程序正在使用的 SQL 数据库中。

任何想法如何构建这种更新程序?有什么标准的方法或框架吗?

【问题讨论】:

  • 下载.doc并将其重命名为.exe
  • 一旦您遇到需要更新的代码相关错误,您会怎么做?这对我来说似乎“不是一个真正的问题”......
  • 给你:工作站上根本没有DLL。从您的数据库中检索任何 DLL 的 base-64 文本编码版本,并在客户端上动态解码和加载它。因此,应用程序始终会更新。但这需要事先计划,因为无法在工作站上更新 dll 或 exe 有点,嗯,毫无意义。
  • 感谢 cmets。在我的情况下,我也无法下载 exe 或 dll,这可能被视为策略中断。但是我可以下载任何脚本、xml 并在客户端构建应用程序。
  • @user695797:你们有源代码控制吗?如果是这样,请安装一个“构建服务器”(例如 Jenkins 或类似服务器)来为您构建它。或者在客户端使用 msbuild(和 msbuildextensions)从源代码管理中提取源代码并构建项目。

标签: .net dll desktop-application auto-update


【解决方案1】:

由于不是“下载二进制文件”的要求,您将需要使用 CSharpCodeProvider 将您的 .cs 文件转换为程序集,然后可以按照我在原始答案中的描述进行加载。 Here is a good tutorial 在代码项目上,了解如何使用该类在运行时编译您的 .cs 代码。


原答案:

扩展Jesse's comment。您的主程序需要是一个简单的加载程序,可以查询包含真实文件的“程序数据库”。

加载过程分为两个阶段:引导 AppDomin、加载程序集


要引导您的应用程序域,您需要创建一个新的 AppDomain,将其限制为仅加载签名文件,然后加载加载其余 DLL 的加载程序

在您的代码中,您需要create a new AppDomain 才能将文件加载到其中。在该应用程序域中,您需要创建一个 evidence,它只允许加载 signed by your private key 的程序集。

//Assumes you have your X509Certificate (the version that only has the public key)
// stored in Settings.Resources.
var onlySignedByMe = new Publisher(Settings.Resources.MyCompanyCertificate);

var evidence = new Evidence();
evedence.(onlySignedByMe);

var adi = new AppDomainInitializer(AppDomainInit);

var appDomainSetup = new AppDomainSetup();
appDomainSetup.AppDomainInitializer = adi;
appDomainSetup.ApplicationBase = System.Environment.CurrentDirectory;

var programAppDomain = AppDomain.CreateDomain("programAppDomain", evidence, appDomainSetup, PermissionSet(PermissionState.Unrestricted)); 

当 AppDomian 初始化时,它将从新域调用 AppDomainInit。从那里查询数据库以获取它需要加载的任何程序集。将这些文件加载​​到byte[],然后使用Load method on the AppDomain 加载byte[]

private static void AppDomainInit(string[] args)
{
    List<Byte[]> assemblies;

    //Snip, populating the list;

    Asesembly entryAssembly;
    foreach(var assembly in assemblies)
    {
         var loadedAssembly = Assembly.Load(assembly);
         if(TestForKnownEntryPointAssembly(loadedAssembly)
             entryAssembly = loadedAssembly;
    }
    if(entryAssembly != null)
    {
        Type type = entryAssembly.GetType("MyNamespace.EntryClass");
        MethodInfo method = type.GetMethod("Main");
        method.Invoke(null, null);
    }

}

这都是凭记忆写的,所以可能会有一些错误。

【讨论】:

  • 所以我有下载 dll 吗?不幸的是,由于公司政策,我不能这样做。但我可以下载任何类型的脚本、c# 代码、xml、json、xaml 等。有什么想法吗?
  • 如果您不能下载二进制文件,您希望如何替换二进制文件。为什么下载源代码然后在客户端计算机上编译代码(可以在编译之前修改代码)被认为比保证不会被修改的数字签名文件更安全?
  • Scott,这些是大公司的规则,有些已经过时,有些很愚蠢,但我需要解决任务而不是尝试修改它们。我 100% 确定可以下载 c# 源代码、编译它并在需要时附加 XAML,无需更新任何 dll,这对我有用。然而,可能有更简单或更好的方法。您的回答不正确,因为我明确指出我的应用程序不能下载任何 dll 或 exe(所有更新必须通过 SMS 进行,这不是我的选择)。将 .dll 重命名为 .doc 也是没有意义的,这违反了政策。
  • 我已经用一些链接更新了我的答案,这些链接将帮助您将 .cs 文件转换为程序集,然后使用我显示的步骤加载程序集。我链接的教程还显示了程序集加载步骤。
  • “所有更新都必须通过短信”太多的东西都有短信的缩写,你指的是哪一个?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-12-12
  • 2012-07-29
  • 1970-01-01
  • 2016-04-27
  • 1970-01-01
  • 2020-08-11
  • 1970-01-01
相关资源
最近更新 更多