您现在的位置是:首页 >

开发一个编译器 深入解析.NET 许可证编译器 (Lc.exe) 的原理与源代码剖析

火烧 2021-09-25 15:43:53 1070
深入解析.NET 许可证编译器 Lc.exe 的原理与源代码剖析 许可证编译器 Lc exe 的作用是读取包含授权信息的文本文件 并产生一个可作为资源嵌入到公用语言运行库可执行文件中的 lice e

深入解析.NET 许可证编译器 (Lc.exe) 的原理与源代码剖析  

许可证编译器 (Lc exe) 的作用是读取包含授权信息的文本文件 并产生一个可作为资源嵌入到公用语言运行库可执行文件中的 licenses 文件  

  在使用第三方类库时 经常会看到它自带的演示程序中 包含有这样的Demo许可文件

复制代码 代码如下: Infragistics Win Misc UltraButton Infragistics Win Misc v Version= Culture=neutral PublicKeyToken=f b b b fdf Infragistics Win Misc UltraLabel Infragistics Win Misc v Version= Culture=neutral PublicKeyToken=f b b b fdf Infragistics Win Printing UltraPrintPreviewDialog Infragistics Win UltraWinPrintPreviewDialog v Version= Culture=neutral PublicKeyToken=f b b b fdf Infragistics Win UltraWinDataSource UltraDataSource Infragistics Win UltraWinDataSource v Version= Culture=neutral PublicKeyToken=f b b b fdf

   这个文件的格式是文本文件 但要按照它的格式要求来写

  控件名称 程序集全名称

  首先根据需要 写一个需要被授权的控件列表 格式如上所示 例如 HostApp exe 的应用程序要引用Samples DLL 中的授权控件 MyCompany Samples LicControl 则可以创建包含以下内容的 HostAppLic txt MyCompany Samples LicControl Samples DLL

  再调用下面的命令创建名为 HostApp exe licenses 的 licenses 文件 lc /target:HostApp exe /plist:hostapplic txt /i:Samples DLL /outdir:c:bindir

  生成将 licenses 文件作为资源嵌入在HostApp exe的资源中 如果生成的是 C# 应用程序 则应使用下面的命令生成应用程序

  csc /res:HostApp exe licenses /out:HostApp exe * cs

   NET Framework SDK目录中的LC EXE文件是由 NET语言编写的 它的功能就是为了根据许可文件的内容 生成资源文件 在编译的最后时刻 由CSC编译器把生成的资源文件嵌入到执行文件中

  用 NET Reflector载入LC EXE 开始源代码分析之旅

   程序的入口处先是分析命令行参数 根据参数的不同来执行指定的功能 先看一个完整的参数列表 代码是下面三行

复制代码 代码如下: if (!ProcessArgs(args))  {      return num;  }

  MSDN有完整的解释 拷贝到下面方便您参考 以减少因查找MSDN引起思路中断 /plist:filename   指定包含授权组件列表的文件名 这些授权组件要包括到 licenses 文件中 每个组件用它的全名引用 并且每行只有一个组件 命令行用户可为项目中的每个窗体指定一个单独的文件 Lc exe 接受多个输入文件并产生一个 licenses 文件 /h[elp]     显示该工具的命令语法和选项 /i:module   指定模块 这些模块包含文件 /plist 中列出的组件 若要指定多个模块 请使用多个 /i 标志 /nologo  取消显示 Microsoft 启动标题 /outdir:path  指定用来放置输出 licenses 文件的目录 /target:targetPE   指定为其生成 licenses 文件的可执行文件 /v   指定详细模式 显示编译进度信息 /?  显示该工具的命令语法和选项 ProcessArgs方法的关键作用是分析出组件列表 程序集列表 如下面的代码所示

复制代码 代码如下:   if ((!flag && (str Length > )) && str Substring( ) ToUpper(CultureInfo InvariantCulture) Equals("TARGET:"))  {        targetPE = str Substring( );        flag = true;  } if ((!flag && (str Length > )) && str Substring( ) ToUpper(CultureInfo InvariantCulture) Equals("PLIST:"))  {       string str = str Substring( );       if ((str != null) && (str Length > ))         {                     if (pLists == null)                     {                         pLists = new ArrayList();                     }                     pLists Add(str );                     flag = true;        } } if ((!flag && (str Length > )) && str Substring( ) ToUpper(CultureInfo InvariantCulture) Equals("I:"))  {        string str = str Substring( );        if (str Length > )         {                     if (assemblies == null)                     {                         assemblies = new ArrayList();                     }                     assemblies Add(str );         }         flag = true; }

   分 析出组件和程序集之后 再来ResolveEventHandler 委托的含义 如果运行库类加载程序无法解析对程序集 类型或资源的引用 则将引发相应的事件 从而使回调有机会通知运行库引用的程序集 类型或资源位于哪 个程序集中 ResolveEventHandler 负责返回解析类型 程序集或资源的程序集

复制代码 代码如下: ResolveEventHandler handler = new ResolveEventHandler(LicenseCompiler OnAssemblyResolve); AppDomain CurrentDomain AssemblyResolve += handler;

   对第一部参数分析出来的组件列表 依次循环 为它们产生授权许可

复制代码 代码如下: DesigntimeLicenseContext creationContext = new DesigntimeLicenseContext(); foreach (string str in pLists) {    key = reader ReadLine();    hashtable[key] = Type GetType(key);        LicenseManager CreateWithContext((Type) hashtable[key] creationContext); }

   最后 生成许可文件并保存到磁盘中 等待CSC编译器将它编译成资源文件 嵌入到程序集中

复制代码 代码如下: string path = null; if (outputDir != null)  {     path = outputDir + @"" + targetPE ToLower(CultureInfo InvariantCulture) + " licenses";  } else  {       path = targetPE ToLower(CultureInfo InvariantCulture) + " licenses";  }  Stream o = null;  try      {             o = File Create(path);            DesigntimeLicenseContextSerializer Serialize(o targetPE ToUpper(CultureInfo InvariantCulture) creationContext);      }      finally      {             if (o != null)             {                 o Flush();                 o Close();             }      }

   这种方式是 NET Framework推荐的保护组件的方式 与我们平时所讨论的输入序列号 RSA签名不同 来看一下 商业的组件是如何应用这种技术保护组件的

开发一个编译器 深入解析.NET 许可证编译器 (Lc.exe) 的原理与源代码剖析
复制代码 代码如下: using System; using System Web; using System Web UI; using System Web UI WebControls; using System ComponentModel; namespace ComponentArt Licensing Providers {   #region RedistributableLicenseProvider     public class RedistributableLicenseProvider : System ComponentModel LicenseProvider     {     const string strAppKey = "This edition of ComponentArt Web UI is licensed for XYZ application only ";        public override System ComponentModel License GetLicense(LicenseContext context Type type object instance bool allowExceptions)     {       if (context UsageMode == LicenseUsageMode Designtime)       {         // We are not going to worry about design time Issue a license         return new ComponentArt Licensing Providers RedistributableLicense(this "The App");       }       else       {         string strFoundAppKey;         // During runtime we only want this control to run in the application         // that it was packaged with         HttpContext ctx = HttpContext Current;         strFoundAppKey = (string)ctx Application["ComponentArtWebUI_AppKey"];         if(strAppKey == strFoundAppKey)           return new ComponentArt Licensing Providers RedistributableLicense(this "The App");         else           return null;       }     }   }   #endregion   #region RedistributableLicense Class   public class RedistributableLicense : System ComponentModel License   {     private ComponentArt Licensing Providers RedistributableLicenseProvider owner;     private string key;     public RedistributableLicense(ComponentArt Licensing Providers RedistributableLicenseProvider owner string key)     {       this owner = owner;       this key = key;     }     public override string LicenseKey     {       get       {         return key;       }     }     public override void Dispose()     {     }   }   #endregion }

   首 先要创建一个类型 继承于License类型 再创建一个继承于LicenseProvider的类型 用于颁发许可证 包含在设计时许可和运行时许可 从上面的例子中可以看到 设计时没有限制 可以运行 但是到运行时 你必须有序列号 它才会生成许可对象 而不是返回null给 NET Framework类型 整个验证过程由 NET完成 你只需要像下面这样 应用这个许可保护机制

复制代码 代码如下: [LicenseProvider(typeof(RedistributableLicenseProvider))] public class MyControl : Control {     // Insert code here     protected override void Dispose(bool disposing) {        /* All ponents must dispose of the licenses they grant         * Insert code here to dispose of the license */     } } lishixinzhi/Article/program/net/201311/14366  
永远跟党走
  • 如果你觉得本站很棒,可以通过扫码支付打赏哦!

    • 微信收款码
    • 支付宝收款码