程序集

【Unity】程序集 程序集是什么呢?主要介绍了程序集及其使用方法。 阅读详情

 

程序集是任何 .NET Framework 应用程序的基本构造块。例如,在生成简单的 C# 应用程序时,Visual Studio 创建一个单个可移植可执行 (PE) 文件形式的程序集,明确地说就是一个 EXE 或 DLL。

程序集包含描述它们自己的内部版本号和它们包含的所有数据和对象类型的详细信息的元数据。

程序集仅在需要时才加载。如果不使用程序集,则不会加载。这意味着程序集可能是在大型项目中管理资源的有效途径。

程序集可以包含一个或多个模块。例如,计划较大的项目时,可以让几个各个开发人员负责单独的模块,并通过组合所有这些模块来创建单个程序集。

 

一、程序集概述

程序集具有以下特点:

·程序集作为 .exe 或 .dll 文件实现。

·通过将程序集放在全局程序集缓存中,可在多个应用程序之间共享程序集。

·要将程序集包含在全局程序集缓存中,必须对程序集进行强命名。

·程序集仅在需要时才加载到内存中。

·可以使用反射以编程方式获取关于程序集的信息。

·如果加载程序集的目的只是对其进行检查,应使用诸如 ReflectionOnlyLoadFrom 的方法。

·可以在单个应用程序中使用相同程序集的两个版本。

 

二、友元程序集

      可以从一个程序集访问另一个程序集中的内部类型或内部成员。

备注:

友元程序集功能用于访问内部成员;私有类型和私有成员仍然不可访问。

若要使程序集(程序集 B)能够访问另一个程序集(程序集 A)的内部类型和成员,应使用程序集 A 中的 InternalsVisibleToAttribute 属性。

说明:

在对将要访问另一个程序集(程序集 A)的内部类型或内部成员的程序集(程序集 B)进行编译时,必须用 /out 编译器选项显式指定输出文件的名称(.exe 或 .dll)。这是必需的,因为当编译器将生成的程序集绑定到外部引用时,尚未为该程序集生成名称。

StrongNameIdentityPermission 类还提供共享类型的功能,其与友元程序集的区别如下:

·StrongNameIdentityPermission 应用于单个类型,而友元程序集应用于整个程序集。

·如果希望程序集 B 能够共享程序集 A 中的数百个类型,则必须使用 StrongNameIdentityPermission 修饰所有这些类型;而使用友元程序集时只需声明一次友元关系。

·使用 StrongNameIdentityPermission 时,想要共享的类型必须声明为公共类型。使用友元程序集时,会将共享类型声明为内部类型。

·有关如何生成可访问程序集中的非公共类型的 .netmodule 的信息,请参见 /moduleassemblyname。

示例

在此示例中,程序集使内部类型和内部成员对名为 called cs_friend_assemblies_2 的程序集可见。

 

// cs_friend_assemblies.cs

// compile with: /target:library

using System.Runtime.CompilerServices;

using System;

 

[assembly:InternalsVisibleTo("cs_friend_assemblies_2")]

 

// internal by default

class Class1

{

    public void Test()

    {

        Console.WriteLine("Class1.Test");

    }

}

 

// public type with internal member

public class Class2

{

    internal void Test()

    {

        Console.WriteLine("Class2.Test");

    }

}

在此示例中,程序集使用程序集 cs_friend_assemblies.dll 中的内部类型和内部成员。

注意,必须显式指定输出文件的名称 (/out:cs_friend_assemblies_2.exe)。

如果此程序集允许另一个程序集(程序集 C)访问它的内部类型和成员,则程序集 C 不会自动变成程序集 cs_friend_assemblies.dll 的友元。

 

// cs_friend_assemblies_2.cs

// compile with: /reference:cs_friend_assemblies.dll /out:cs_friend_assemblies_2.exe

public class M

{

    static void Main()

    {

        // access an internal type

        Class1 a = new Class1();

        a.Test();

 

        Class2 b = new Class2();

        // access an internal member of a public type

        b.Test();

    }

}

 

Class1.Test

Class2.Test

此示例演示了如何使内部类型和成员对具有强名称的程序集可用。

若要生成 keyfile 并显示公钥,请使用下面的 sn.exe 命令序列:

·sn -k friend_assemblies.snk // 生成强名称密钥

·sn -p friend_assemblies.snk key.publickey // 将公钥从 key.snk 提取到 key.publickey 中

·sn -tp key.publickey // 显示存储在文件 key.publickey 中的公钥

用 /keyfile 将 keyfile 传递到编译器。

 

// cs_friend_assemblies_3.cs

// compile with: /target:library /keyfile:friend_assemblies.snk

using System.Runtime.CompilerServices;

 

[assembly:InternalsVisibleTo("cs_friend_assemblies_4, PublicKey=0024000004800000940000000602000000240000525341310004000001000100031d7b6f3abc16c7de526fd67ec2926fe68ed2f9901afbc5f1b6b428bf6cd9086021a0b38b76bc340dc6ab27b65e4a593fa0e60689ac98dd71a12248ca025751d135df7b98c5f9d09172f7b62dabdd302b2a1ae688731ff3fc7a6ab9e8cf39fb73c60667e1b071ef7da5838dc009ae0119a9cbff2c581fc0f2d966b77114b2c4")]

class Class1

{

    public void Test()

    {

        System.Console.WriteLine("Class1.Test");

    }

}

此示例演示如何使用对具有强名称的程序集可用的内部类型和成员。

// cs_friend_assemblies_4.cs

// compile with: /keyfile:friend_assemblies.snk /reference:cs_friend_assemblies_3.dll /out:cs_friend_assemblies_4.exe

public class M

{

    static void Main()

    {

        Class1 a = new Class1();

        a.Test();

    }

}

 

三、如何:与其他应用程序共享程序集

      程序集可以是私有的也可以是共享的:默认情况下,大多数简单的 C# 程序都包含一个私有程序集,原因是不打算将该程序集供其他应用程序使用。

为了与其他应用程序共享程序集,必须将该程序集置于 全局程序集缓存 (GAC) 中。

共享程序集:

·创建程序集。

·为程序集指定一个强名称。

·为程序集指定版本信息。

·将您的程序集添加到全局程序集缓存中。

·从其他应用程序中访问该程序集包含的类型。

 

四、如何:加载和卸载程序集

      程序引用的程序集将在生成时自动加载,不过也可以在运行时将特定的程序集加载到当前应用程序域中。

没有办法卸载单独的程序集而不卸载包含它的所有应用程序域。即使程序集已在范围之外,实际的程序集文件仍然保持被加载,直至包含它的所有应用程序域都被卸载。

如果想要卸载某些程序集而不卸载其他程序集,可考虑创建新的应用程序域,在该域中执行代码,然后卸载该应用程序域。

将程序集加载到应用程序域中:

·使用 AppDomain 和 System.Reflection 类中包含的几个加载方法之一。有关更多信息,请参见将程序集加载到应用程序域中。

卸载应用程序域:

·没有办法卸载单独的程序集而不卸载包含它的所有应用程序域。使用 AppDomain 中的 Unload 方法可卸载应用程序域。

 

五、如何:确定文件是否为程序集

      当且仅当一个文件是托管文件并且在其元数据中包含程序集入口时,该文件才是一个程序集。

如何手动确定一个文件是否为程序集:

·启动 MSIL 反汇编程序 (Ildasm.exe)。

·加载希望测试的文件。

·如果 ILDASM 报告该文件不是可移植的可执行 (PE) 文件,则它不是程序集。有关更多信息,请参见主题 如何:查看程序集内容。

如何以编程方式确定一个文件是否为程序集:

·调用 GetAssemblyName 方法,并向其传递正在测试的文件的完整文件路径和名称。

·如果引发 BadImageFormatException 异常,则该文件不是程序集。

示例:

此示例测试一个 DLL 以确定它是否为程序集。

class TestAssembly

{

    static void Main()

    {

 

        try

        {

            System.Reflection.AssemblyName testAssembly =

                System.Reflection.AssemblyName.GetAssemblyName(@"C:/Windows/Microsoft.NET/Framework/v3.5/System.Net.dll");

 

            System.Console.WriteLine("Yes, the file is an Assembly.");

        }

 

        catch (System.IO.FileNotFoundException)

        {

            System.Console.WriteLine("The file cannot be found.");

        }

 

        catch (System.BadImageFormatException)

        {

            System.Console.WriteLine("The file is not an Assembly.");

        }

 

        catch (System.IO.FileLoadException)

        {

            System.Console.WriteLine("The Assembly has already been loaded.");

        }

    }

}

/* Output (with .NET Framework 3.5 installed):

    Yes, the file is an Assembly.

*/

GetAssemblyName 方法加载测试文件,然后在读取信息之后释放它。

 

六、extern

      extern 修饰符用于声明在外部实现的方法。extern 修饰符的常见用法是在使用 Interop 服务调入非托管代码时与 DllImport 属性一起使用。在这种情况下,还必须将方法声明为 static,如下示例所示:

[DllImport("avifil32.dll")]
private static extern void AVIFileInit();

extern 关键字还可以定义外部程序集别名,使得可以从单个程序集中引用同一组件的不同版本。

将 abstract 和 extern 修饰符一起使用来修改同一成员是错误的。使用 extern 修饰符意味着方法在 C# 代码的外部实现,而使用 abstract 修饰符意味着在类中未提供方法实现。

      extern 关键字在使用上比在 C++ 中有更多限制。

示例

在该示例中,程序接收来自用户的字符串并将该字符串显示在消息框中。程序使用从 User32.dll 库导入的 MessageBox 方法。

//using System.Runtime.InteropServices;

class ExternTest

{

    [DllImport("User32.dll", CharSet=CharSet.Unicode)]

    public static extern int MessageBox(int h, string m, string c, int type);

 

    static int Main()

    {

        string myString;

        Console.Write("Enter your message: ");

        myString = Console.ReadLine();

        return MessageBox(0, myString, "My Message Box", 0);

    }

 

}

此示例使用 C 程序创建一个 DLL,在下一示例中将从 C# 程序调用该 DLL。

// cmdll.c

// Compile with: /LD

int __declspec(dllexport) SampleMethod(int i)

{

   return i*10;

}

该示例使用两个文件 CM.cs 和 Cmdll.c 来说明 extern。C 文件是示例 2 中创建的外部 DLL,它从 C# 程序内调用。

// cm.cs

using System;

using System.Runtime.InteropServices;

public class MainClass

{

   [DllImport("Cmdll.dll")]

   public static extern int SampleMethod(int x);

 

   static void Main()

   {

      Console.WriteLine("SampleMethod() returns {0}.", SampleMethod(5));

   }

}

SampleMethod() returns 50.

 

七、公共语言运行库中的程序集

1、程序集概述

      程序集是 .NET Framework 编程的基本组成部分。程序集执行以下功能:

·包含公共语言运行库执行的代码。如果可移植可执行 (PE) 文件没有相关联的程序集清单,则将不执行该文件中的 Microsoft 中间语言 (MSIL) 代码。请注意,每个程序集只能有一个入口点(即 DllMain、WinMain 或 Main)。

·程序集形成安全边界。程序集就是在其中请求和授予权限的单元。

·程序集形成类型边界。每一类型的标识均包括该类型所驻留的程序集的名称。在一个程序集范围内加载的 MyType 类型不同于在其他程序集范围内加载的 MyType 类型。

·程序集形成引用范围边界。程序集的清单包含用于解析类型和满足资源请求的程序集元数据。它指定在该程序集之外公开的类型和资源。该清单还枚举它所依赖的其他程序集。

·程序集形成版本边界。程序集是公共语言运行库中最小的可版本化单元,同一程序集中的所有类型和资源均会被版本化为一个单元。程序集的清单描述您为任何依赖项程序集所指定的版本依赖性。

·程序集形成部署单元。当一个应用程序启动时,只有该应用程序最初调用的程序集必须存在。其他程序集(例如本地化资源和包含实用工具类的程序集)可以按需检索。这就使应用程序在第一次下载时保持精简。

·程序集是支持并行执行的单元。

程序集可以是静态的或动态的。静态程序集可以包括 .NET Framework 类型(接口和类),以及该程序集的资源(位图、JPEG 文件、资源文件等)。静态程序集存储在磁盘上的可移植可执行 (PE) 文件中。您还可以使用 .NET Framework 来创建动态程序集,动态程序集直接从内存运行并且在执行前不存储到磁盘上。您可以在执行动态程序集后将它们保存在磁盘上。

有几种创建程序集的方法。您可以使用过去用来创建 .dll 或 .exe 文件的开发工具,例如 Visual Studio 2005。您可以使用 Windows 软件开发工具包 (SDK) 中提供的工具来创建带有在其他开发环境中创建的模块的程序集。您还可以使用公共语言运行库 API(例如 Reflection.Emit)来创建动态程序集。

 

2、程序集优点

      程序集旨在简化应用程序部署并解决在基于组件的应用程序中可能出现的版本控制问题。

最终用户和开发人员比较熟悉当今基于组件的系统所产生的版本控制和部署问题。一些最终用户曾经历过在计算机上安装新应用程序失败的事情,发现已有应用程序突然停止工作。许多开发人员花费了大量的时间来使所有必需的注册表项保持一致,以便激活 COM 类。

通过在 .NET Framework 中使用程序集,许多开发问题得以解决。因为程序集是不依赖于注册表项的自述组件,所以程序集使无相互影响的应用程序安装成为可能。程序集还使应用程序的卸载和复制得以简化。

版本控制问题:

·目前,Win32 应用程序存在两类版本控制问题:

·版本控制规则不能在应用程序的各段之间表达,并且不能由操作系统强制实施。目前的办法依赖于向后兼容,而这通常很难保证。接口定义一经发布就必须是静态的,并且单段代码必须保持与以前版本向后兼容。此外,通常要对代码进行设计,以便在任意给定时间在计算机上只能出现和执行代码的一个版本。

·没有办法在创建到一起的多套组件集与运行时提供的那套组件之间保持一致。

这两类版本控制问题结合在一起产生了 DLL 冲突,在这些冲突中,安装一个应用程序可能会无意间破坏现有的应用程序,因为所安装的某个软件组件或 DLL 与以前的版本不完全向后兼容。出现此情况后,系统不支持诊断和解决此问题。

 

最终解决 DLL 冲突:

Microsoft® Windows® 2000 开始致力于解决这些问题。它所提供的两个功能可以部分地解决 DLL 冲突:

·Windows 2000 使您能够创建这样的客户端应用程序,其中的 .dll 依赖文件与该应用程序的 .exe 文件位于相同的目录中。Windows 2000 经过配置,能够在检查完全限定的路径或搜索常规路径前,检查 .exe 文件所在目录中的组件。这使组件可以独立于其他应用程序所安装和使用的组件。

·Windows 2000 锁定 System32 目录中随操作系统提供的文件,使这些文件不会在安装应用程序时被无意替换。

公共语言运行库使用程序集来继续致力于 DLL 冲突的彻底解决。

 

程序集解决方案:

为了解决版本控制问题以及导致 DLL 冲突的其余问题,运行库使用程序集来执行以下功能:

·使开发人员能够指定不同软件组件之间的版本规则。

·提供强制实施版本控制规则的结构。

·提供允许同时运行多个版本的软件组件(称作并行执行)的基本结构。

 

3、程序集内容

通常,静态程序集可能由以下四个元素组成:

  • 程序集清单,包含程序集元数据。
  • 类型元数据。
  • 实现这些类型的 Microsoft 中间语言 (MSIL) 代码。
  • 资源集。

只有程序集清单是必需的,但也需要类型或资源来向程序集提供任何有意义的功能。

程序集中的这些元素有分组几种方法。您可以将所有元素分组到单个物理文件中,如下图所示。

单文件程序集


或者,可以将一个程序集的元素包含在几个文件中。这些文件可能是编译代码的模块 (.netmodule)、资源(例如 .bmp 或 .jpg 文件)或应用程序所需的其他文件。在您希望组合以不同语言编写的模块并优化应用程序的下载过程时,可创建一个多文件程序集,优化下载过程的方法是将很少使用的类型放入只在需要时才下载的模块中。

在下图中,一个假想应用程序的开发人员已选择将一些实用工具代码单独放入另一个模块中,同时在其原文件中保留一个较大的资源文件(在此例中为一个 .bmp 图像)。.NET Framework 只在文件被引用时下载该文件;通过将很少引用的代码保留在独立于应用程序的文件中来优化代码下载。

多文件程序集

说明:

构成多文件程序集的那些文件实际上并非由文件系统来链接。它们而是通过程序集清单进行链接,公共语言运行库将这些文件作为一个单元来管理。

在此插图中,所有三个文件均属于一个程序集,如 MyAssembly.dll 所包含的程序集清单文件中所述。对于该文件系统,这三个文件是三个独立的文件。请注意,文件 Util.netmodule 被编译为一个模块,因为它不包含任何程序集信息。在创建了程序集后,该程序集清单就被添加到 MyAssembly.dll,指示程序集与 Util.net 模块和 Graphic.bmp 的关系。

现在设计源代码时,您会作出有关如何将应用程序的功能划分到一个或多个文件的明确的决定。在设计 .NET Framework 代码时,您也将作出类似的决定,即如何将应用程序的功能划分到一个或多个程序集中。

 

4、程序集清单

每一程序集,无论是静态的还是动态的,均包含描述该程序集中各元素彼此如何关联的数据集合。程序集清单就包含这些程序集元数据。程序集清单包含指定该程序集的版本要求和安全标识所需的所有元数据,以及定义该程序集的范围和解析对资源和类的引用所需的全部元数据。程序集清单可以存储在具有 Microsoft 中间语言 (MSIL) 代码的 PE 文件(.exe 或 .dll)中,也可存储在只包含程序集清单信息的独立 PE 文件中。

以下插图显示了清单的不同存储方法。

程序集的类型

对于有一个关联文件的程序集,该清单将被合并到 PE 文件中以构成单文件程序集。您可以创建有独立的清单文件,或清单被合并到同一多文件程序集中某一 PE 文件的多文件程序集。

每一程序集的清单均执行以下功能:

·枚举构成该程序集的文件。

·控制对该程序集的类型和资源的引用如何映射到包含其声明和实现的文件。

·枚举该程序集所依赖的其他程序集。

·在程序集的使用者和程序集的实现详细信息的使用者之间提供一定程度的间接性。

·呈现程序集自述。

 程序集清单内容:

下表显示了在程序集清单中包含的信息。前四项(程序集名称、版本号、区域性和强名称信息)构成了程序集的标识。

信息

说明

程序集名称

指定程序集名称的文本字符串。

版本号

主版本号和次版本号,以及修订号和内部版本号。公共语言运行库使用这些编号来强制实施版本策略。

区域性

有关该程序集支持的区域性或语言的信息。此信息只应用于将一个程序集指定为包含特定区域性或特定语言信息的附属程序集。(具有区域性信息的程序集被自动假定为附属程序集。)

强名称信息

如果已经为程序集提供了一个强名称,则为来自发行者的公钥。

程序集中所有文件的列表

在程序集中包含的每一文件的散列及文件名。请注意,构成程序集的所有文件所在的目录必须是包含该程序集清单的文件所在的目录。

类型引用信息

运行库用来将类型引用映射到包含其声明和实现的文件的信息。该信息用于从程序集导出的类型。

有关被引用程序集的信息

该程序集静态引用的其他程序集的列表。如果依赖的程序集具有强名称,则每一引用均包括该依赖程序集的名称、程序集元数据(版本、区域性、操作系统等)和公钥。

通过在代码中使用程序集属性,您可以添加或更改程序集清单中的一些信息。您可以更改版本信息和信息性属性,包括商标、版权、产品、公司和信息性版本。

 

5、全局程序集缓存

安装有公共语言运行库的每台计算机都具有称为全局程序集缓存的计算机范围内的代码缓存。全局程序集缓存中存储了专门指定给由计算机中若干应用程序共享的程序集。

应当仅在需要时才将程序集安装到全局程序集缓存中以进行共享。一般原则是:程序集依赖项保持专用,并在应用程序目录中定位程序集,除非明确要求共享程序集。另外,不必为了使 COM 互操作或非托管代码可以访问程序集而将程序集安装到全局程序集缓存。

说明:

在有些情况下,您显然不希望将程序集安装到全局程序集缓存中。如果您将组成应用程序的某个程序集置于全局程序集缓存中,则将不再能够通过使用 xcopy 命令复制应用程序目录来复制或安装该应用程序。您还必须在全局程序集缓存中移动该程序集。

有若干方法可以将程序集部署到全局程序集缓存中:

  • 使用专用于全局程序集缓存的安装程序。该方法是将程序集安装到全局程序集缓存的首选方法。
  • 使用 Windows 软件开发工具包 (SDK) 提供的名为全局程序集缓存工具 (Gacutil.exe) 的开发工具。
  • 使用 Windows 资源管理器将程序集拖到缓存中。

说明:

在部署方案中,应该使用 Windows Installer 2.0 将程序集安装到全局程序集缓存中。我们一般只在开发方案中使用 Windows 资源管理器或全局程序集缓存工具,这是因为它们不提供使用 Windows Installer 时可以提供的程序集引用计数功能和其他功能。

管理员通常使用访问控制列表 (ACL) 来保护 systemroot 目录,以控制写入和执行访问。因为全局程序集缓存安装在 systemroot 目录的子目录中,它继承了该目录的 ACL。建议只允许具有“管理员”权限的用户从全局程序集缓存中删除文件。

在全局程序集缓存中部署的程序集必须具有强名称。将一个程序集添加到全局程序集缓存时,必须对构成该程序集的所有文件执行完整性检查。缓存执行这些完整性检查以确保程序集未被篡改(例如,当文件已更改但清单未反映此更改时)。

 

6、具有强名称的程序集

      强名称是由程序集的标识加上公钥和数字签名组成的。其中,程序集的标识包括简单文本名称、版本号和区域性信息(如果提供的话)。强名称是使用相应的私钥,通过程序集文件(包含程序集清单的文件,并因而也包含构成该程序集的所有文件的名称和散列)生成的。Microsoft® Visual Studio® .NET 和 Windows 软件开发工具包 (SDK) 中提供的其他开发工具能够向一个程序集分配多个强名称。强名称相同的程序集应该是相同的。

通过签发具有强名称的程序集,您可以确保名称的全局唯一性。强名称还特别满足以下要求:

·强名称依赖于唯一的密钥对来确保名称的唯一性。任何人都不会生成与您生成的相同的程序集名称,因为用一个私钥生成的程序集的名称与用其他私钥生成的程序集的名称不相同。

·强名称保护程序集的版本沿袭。强名称可以确保没有人能够生成您的程序集的后续版本。用户可以确信,他们所加载的程序集的版本出自创建该版本(应用程序是用该版本生成的)的同一个发行者。

·强名称提供可靠的完整性检查。通过 .NET Framework 安全检查后,即可确信程序集的内容在生成后未被更改过。但请注意,强名称中或强名称本身并不暗含信任级别,例如由数字签名和支持证书提供的信任。

在引用具有强名称的程序集时,您应该能够从中受益,例如版本控制和命名保护。如果此具有强名称的程序集以后引用了具有简单名称的程序集(后者没有这些好处),则您将失去使用具有强名称的程序集所带来的好处,并依旧会产生 DLL 冲突。因此,具有强名称的程序集只能引用其他具有强名称的程序集。

 

7、程序集安全注意事项

      在您生成程序集时,您可以指定该程序集运行所需的一组权限。是否将特定的权限授予程序集是基于证据的。

 

使用证据有两种截然不同的方式:

·将输入证据与加载程序所收集的证据合并,以创建用于策略决策的最终证据集。使用这种语义的方法包括 Assembly.Load、Assembly.LoadFrom 和 Activator.CreateInstance。

·原封不动地使用输入证据作为用于策略决策的最终证据集。使用这种语义的方法包括 Assembly.Load(byte[]) 和 AppDomain.DefineDynamicAssembly()。

 

通过在将运行程序集的计算机上设置安全策略,您可以授予一些可选的权限。如果您希望代码可以处理所有潜在的安全异常,可以执行以下操作之一:

·为您的代码必须具有的所有权限插入权限请求,并预先处理在未授予权限时发生的加载时错误。

·不要使用权限请求来获取您的代码可能需要的权限,但一定要准备处理在未授予权限时发生的安全异常。

 

说明:

安全性是一个较为复杂的领域,您将要作出很多选择。

 

在加载时,程序集的证据用作安全策略的输入。安全策略是由企业和计算机的管理员以及用户策略设置建立的,它在执行时确定向所有托管代码授予的权限组。可以为该程序集(如果该程序集具有签名工具生成的签名)的发行者建立安全策略,或者为该程序集的下载网站和区域(就 Internet Explorer 而言)建立安全策略,也可以为该程序集的强名称建立该策略。例如,一台计算机的管理员可以建立这样一种安全策略:它允许从某一网站下载由指定软件公司签发用以访问计算机上的数据库的所有代码,但不授予对该计算机磁盘的写访问权。

 

强名称程序集和签名工具

可以用两种不同但相互补充的方式对程序集进行签名:使用强名称或使用 .NET Framework 1.0 和 1.1 版中的 文件签名工具 (Signcode.exe) 或 .NET Framework 更高版本中的 签名工具 (SignTool.exe)。使用强名称对程序集进行签名将向包含程序集清单的文件添加公钥加密。强名称签名帮助验证名称的唯一性,避免名称欺骗,并在解析引用时向调用方提供某标识。

但是,任何信任级别都不会与一个强名称关联,这样 文件签名工具 (Signcode.exe) 和 签名工具 (SignTool.exe) 就变得十分重要。这两个签名工具要求发行者向第三方证书颁发机构证实其标识并获取证书。然后此证书将嵌入到您的文件中,并且管理员能够使用该证书来决定是否相信这些代码的真实性。

您可以将强名称和使用 文件签名工具 (Signcode.exe) 或 签名工具 (SignTool.exe) 创建的数字签名一起提供给程序集,或者您可以单独使用其中之一。这两个签名工具一次只能对一个文件进行签名,对于多文件程序集,您可以对包含程序集清单的文件进行签名。强名称存储在包含程序集清单的文件中,但使用 文件签名工具 (Signcode.exe) 或 签名工具 (SignTool.exe) 创建的签名存储在该程序集清单所在的可移植可执行 (PE) 文件中保留的槽中。当您已经具有依赖于 文件签名工具 (Signcode.exe) 或 签名工具 (SignTool.exe) 生成的签名的信任层次结构或者当您的策略只使用密钥部分并且不检查信任链时,就可以使用通过 文件签名工具 (Signcode.exe) 或 签名工具 (SignTool.exe) 对程序集进行的签名(带或不带强名称)。

 

说明:

在一个程序集上同时使用强名称和签名工具签名时,必须首先分配强名称。

 

公共语言运行库还将执行哈希验证;程序集清单包含构成该程序集的所有文件的列表,包括当生成清单时存在的每一文件的散列。在加载每一文件时,其内容被散列化并与清单中存储的哈希值进行比较。 如果两个哈希值不匹配,则无法加载该程序集。

因为强名称和使用 文件签名工具 (Signcode.exe) 或 签名工具 (SignTool.exe) 进行签名确保了完整性,因此您可以将代码访问安全策略建立在这两种形式的程序集证据的基础上。强名称和使用 文件签名工具 (Signcode.exe) 或 签名工具 (SignTool.exe) 进行签名通过数字签名和证书来确保完整性。上面提到的所有技术(哈希验证、强名称和使用 文件签名工具 (Signcode.exe) 或 签名工具 (SignTool.exe) 进行签名)共同作用,可以确保程序集没有做过任何方式的改动。

 

8、程序集版本控制

使用公共语言运行库的程序集的所有版本控制都在程序集级别上进行。一个程序集的特定版本和依赖程序集的版本在该程序集的清单中记录下来。除非被配置文件(应用程序配置文件、发行者策略文件和计算机的管理员配置文件)中的显式版本策略重写,否则运行库的默认版本策略是,应用程序只与它们生成和测试时所用的程序集版本一起运行。

说明:

      仅对具有强名称的程序集进行版本控制。

运行库执行以下几步来解析程序集绑定请求:

1.     检查原程序集引用,以确定该程序集的版本是否被绑定。

2.     检查所有适用的配置文件以应用版本策略。

3.     通过原程序集引用和配置文件中指定的任何重定向来确定正确的程序集,并且确定应绑定到调用程序集的版本。

4.     检查全局程序集缓存和在配置文件中指定的基本代码,然后使用在运行库如何定位程序集中解释的探测规则检查该应用程序的目录和子目录。

下图说明了这些步骤。

解析程序集绑定请求


 版本信息

每一程序集都用两种截然不同的方法来表示版本信息:

  • 程序集的版本号,该版本号与程序集名称及区域性信息都是程序集标识的组成部分。该号码将由运行库用来强制实施版本策略,它在运行时的类型解析进程中起着重要的作用。
  • 信息性版本,这是一个字符串,表示仅为提醒的目的而包括的附加版本信息。

程序集版本号

每一程序集都有一个版本号作为其标识的一部分。因此,如果两个程序集具有不同的版本号,运行库就会将它们视作完全不同的程序集。此版本号实际表示为具有以下格式的四部分号码:

<major version>.<minor version>.<build number>.<revision>

例如,版本 1.5.1254.0 中的 1 表示主版本,5 表示次版本,1254 表示内部版本号,而 0 则表示修订号。

版本号与其他标识信息(包括程序集名称和公钥,以及与该应用程序所连接的其他程序集的关系和标识有关的信息)一起存储在程序集清单中。

在生成程序集时,开发工具将把每一个被引用程序集的依赖项信息记录在程序集清单中。运行库将这些版本号与管理员、应用程序或发行者设置的配置信息结合使用,以加载被引用程序集的正确版本。

为进行版本控制,运行库会区分常规程序集和具有强名称的程序集。只对具有强名称的程序集执行版本检查。

程序集信息性版本

信息性版本是一个字符串,它仅出于提醒的目的将附加的版本信息附加到一个程序集;此信息不在运行时使用。基于文本的信息性版本相当于产品的营销广告、包装或产品名称,不被运行库使用。例如,信息性版本可以是“公共语言运行库版本 1.0”或“NET Control SP 2”。在 Microsoft Windows 中的文件属性对话框的“版本”选项卡上,此信息显示在“产品版本”项中。

说明:

虽然可以指定任意文本,但是如果字符串的格式不是程序集版本号使用的格式,或者虽然是这种格式但包含通配符,则在编译时会显示一条警告消息。此警告无碍

信息性版本用自定义属性 System.Reflection..::.AssemblyInformationalVersionAttribute 表示。有关信息性版本属性的更多信息,请参见设置程序集属性。

 

9、程序集位置

      对于大多数 .NET Framework 应用程序而言,您可以在以下位置找到构成该应用程序的程序集,这些位置包括:该应用程序的目录中,该应用程序目录的子目录中,或全局程序集缓存中(如果该程序集是共享的话)。可以通过在配置文件中使用 <codeBase> 元素 重写公共语言运行库查找某一程序集的位置。如果该程序集没有强名称,则使用 <codeBase> 元素 指定的位置将被限制在应用程序目录或子目录中。如果程序集具有强名称,则 <codeBase> 元素 能够指定计算机或网络上的任意位置。

当在使用非托管代码或 COM 互操作 应用程序的过程中查找程序集的位置时,类似的规则同样适用:如果该程序集将由多个应用程序共享,则此程序集应被安装到全局程序集缓存中。和非托管代码一起使用的程序集必须作为类型库导出并注册。由 COM 互操作 使用的程序集必须在目录中进行注册,尽管有些情况下会自动进行此注册。

 

10、程序集和并行执行

      并行执行是在同一台计算机上存储和执行应用程序或组件的多个版本的能力。这意味着在同一台计算机上可以同时有运行库的多个版本,并且可以有使用其中某个运行库版本的应用程序和组件的多个版本。并行执行使您能够更多地控制应用程序绑定到的组件版本和应用程序使用的运行库版本。

支持并行存储和执行同一程序集的不同版本是强命名中不可缺少的部分,这种支持内置于运行库基础结构中。因为强名称程序集的版本号是其标识的一部分,所以运行库能够在全局程序集缓存中存储同一程序集的多个版本,并且在运行时加载这些程序集。

尽管运行库使您能够创建并行应用程序,但并行执行并不是自动进行的。

 

C# 友元程序集 使用友元程序集可以将internal成员提供给其他的友元程序集访问。程序集FriendTest1.dll程序集FriendTest2.dll调用。 阅读详情

相关推荐

Stable-Baselines3性能优化:多环境训练对比指南(DummyVecEnv vs SubprocVecEnv)

本文深入对比了Stable-Baselines3中DummyVecEnv与SubprocVecEnv两种向量化环境的性能差异与应用场景。DummyVecEnv适用于轻量级、步进快的环境,调试友好且开销低;而SubprocVecEnv则通过真正的多进程并行,能显著加速计算密集型环境的训练。文章通过基准测试与决策树,指导开发者根据环境计算成本、CPU核心数等关键因素做出最优选择,以实现训练效率最大化。

weixin_29063979的博客 147

c#语言程序集

程序集是C#中非常重要的概念,它不仅是代码的封装单元,还提供了版本控制、安全性和资源管理等功能。通过合理地创建和使用程序集,可以提高代码的重用性和维护性。当然,接下来我们可以深入探讨一些与C#程序集相关的高级主题,包括程序集的加载、依赖管理、版本控制、以及如何使用反射和特性等。可以定义自定义特性,并在代码中使用它们。get;

本博客聚焦游戏开发技巧、创业实战心得及大学热门课程干货。这里既有技术深度,也有思维广度,无论你是开发者、创业者还是高校学子,都能在这里找到适合自己的成长之路! 820

XGBoost实战:从原理到调参,手把手教你提升模型性能(附Python代码)

本文深入解析XGBoost核心原理,并提供一套从数据准备、系统性调参到生产部署的完整实战指南。通过剖析目标函数、正则化项与分裂算法,帮助读者理解参数背后的数学逻辑,并利用交叉验证、早停法及自动化工具(如Optuna)高效提升模型性能。文中附有详尽的Python代码示例,涵盖类别特征处理、缺失值应对、不平衡数据调整及模型可视化等高级技巧。

weixin_29178069的博客 457

什么是程序集

程序集是为协同工作而生成的类型和资源的集合,这些类型和资源构成了一个逻辑功能单元,构成了.NET应用程序的部署、版本控制、重用、激活范围和安全权限的基本单元。程序集采用可执行文件(.exe)或动态链接文件(.dll)的形式,是.NET应用程序的构建基块。

SanShui_yang的博客 1843

通讯模块_三菱IQ-R PLC串口通讯模块RJ71C24进行Modbus-RTU通讯

在日常的选型中,很多电气工程师咨询我,三菱iQ-R系列有没有Modbus通讯模块,我在这里可以肯定的回复您,这个肯定是有的;我们共有三种可以选择分别是RJ71C24、RJ71C24-R2、RJ71C24-R4。RJ71C24系列支持MC协议通信、通信协议通信、无顺序协议通信、双向协议通信全、MODBUS通信。当我帮助他们选型之后,他们在使用的时候,又是一头雾水。那么今天我抽一些时间讲解一RJ71...

weixin_39878549的博客 9269

华为模拟器eNSP练习题 - HCIA综合实验

华为模拟器eNSP练习题 - HCIA综合实验 题目要求 ISP路由器只能配置IP地址,之后不得进行其他任何配置; 整个内部网络基于192.168.1.0/24进行地址规划; R1/R2之间启动OSPF协议,单区域; PC1-PC4自动获取IP地址; PC1不能telnet R1,PC1外的其他内网pc可以; PC1-PC4可以访问PC5,R2的公网接口只拥有一个公有IP12.0.0.1; 外部的client可以通过域名www.ensp.com访问http server; ISP路由telnet 12.0

炸鸡店老板z的博客 9870

电影台词预测类型:NLP小样本多标签分类实战

电影类型预测本质上是短文本语义建模问题,核心在于从高度碎片化、低语义密度的台词(平均仅12.7词)中挖掘隐含的类型学编码规则。其技术难点在于:需应对省略主语、倒装、拟声词等非规范表达;处理Drama与Comedy等类型强共现的多标签耦合;并克服领域迁移障碍——维基文本预训练模型在台词上性能骤降0.11。解决方案聚焦RoBERTa微调、类型感知注意力机制与标签平滑策略,兼顾小样本鲁棒性与业务可解释性,广泛适用于影视元数据标注、智能推荐系统及NLP教学实践。

weixin_33309048的博客 288

Unity程序集

比如Unity的默认程序集,,还有其他的比如 Assembly-CSharp-Editor.dll,Assembly-CSharp-firstpass.dll没有指定或不在特殊文件夹内的脚本都属于这个程序集即Assembly Definition Reference官方解释为什么意思呢?试验一下此时脚本默认属于Assembly-CSharp-Editor.dll接下来创建一个Assembly Definition Reference,并且指定程序集引用为UniTask。

Morris-w的专栏 1415

Vue2 - 最新详细实现接入天地图详细配置流程及示例代码教程,提供获取用户当前定位的城市名称及省市区数据、精准经纬度信息、IP属地定位、地图搜索标点等示例,解决天地图跨域报错/页面白屏/定位不准问题

vue2,nuxt2,天地图,使用教程,vue接入国家天地图,定位api,ip属地定位,获取用户当前位置数据,省市区,地图不显示,白屏,报错,vue2如何使用天地图,地图选点,cors跨域,白名单设置了还是不行,vue项目调用天地图api实现定位,Vue2中使用天地图,详细教程,天地图申请密钥key教程,经纬度,经纬度不准确,一直定位北京,定位在北京不准怎么办,nuxt项目天地图,网站,网页,h5页面,地图显示不全,获取当前定位,如何使用天地图,拿到客户ip地址定位城市名称,距离计算,实时搜索地址逆解析,天

🏆 前端领域优质创作者 5326

【EB_Tresos专题】-06-配置一个UDS诊断DID

<--返回「Autosar_BSW高阶配置」总目录--> <--返回「Autosar_BSW高阶配置」专栏主页--> <--返回「个人博客」首页--> <--返回「Autosar_BSW高阶配置」总目录--> <--返回「Autosar_BSW高阶配置」专栏主页--> <--返回「个人博客」首页--> 结尾 ...

「汽车电子助手」的博客 4085

什么是程序集?

一、      程序集定义由.NET 编译生成的EXE文件或DLL文件就是程序集,例如:System.Data.dll。 二、      程序集结构 1.         程序集清单:和我们在淘宝买东西的配送清单一样就是说明里面包含了什么东东。2.         类型元数据:类型元数据是描述程序集中定义的类型的信息,由一些元数据表组成,包含 类、方法、属性、参数、返回

yanglaiwang的专栏 6423

XGBoost原生接口和Sklearn接口参数详解

XGBoost原生接口和Sklearn接口参数详解

算法工程师 2654

C#程序集

程序集的概念 程序集的定义:            1.程序集是一个或多个托管模块,以及一些资源文件的逻辑组合。            2.程序集是组件复用,以及实施安全策略和版本策略的最小单位。              3.程序集是包含一个或者多个类型定义文件和资源文件的集合。在程序集包含的所有文件中,有一个文件用于保存清单。(清单是元数据部分中一组数据表的集合,其中包含了程序集中

一步一脚印 3529

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

C#之程序集

程序集的定义:           1.程序集是一个或多个托管模块,以及一些资源文件的逻辑组合。           2.程序集是组件复用,以及实施安全策略和版本策略的最小单位。           3.程序集是包含一个或者多个类型定义文件和资源文件的集合。在程序集包含的所有文件中,有一个文件用于 保存清单。(清单是元数据部分中一组数据表的集合,其中包含了程序集中一部分文件的名称,描述了程序集的

ruixj的专栏 4623

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

c#程序集

程序集是C#和.NET应用程序的核心构建块,负责代码的组织、部署和版本控制。理解程序集的结构和功能对于开发和维护.NET应用程序至关重要。通过使用程序集,开发者可以实现代码的模块化、重用和安全性。

本博客聚焦游戏开发技巧、创业实战心得及大学热门课程干货。这里既有技术深度,也有思维广度,无论你是开发者、创业者还是高校学子,都能在这里找到适合自己的成长之路! 1012

认识程序集:1. 程序集的生成

<br />源文来看:http://www.cnblogs.com/netatomy/archive/2008/06/10/1216872.html<br /><br />程序集(Assembly)是.NET程序的最小组成单位。每个程序集都有自己的名称、版本等信息。程序集通常<br /> <br />表现为一个文件(.exe或.dll文件),这样的程序集被称为单文件程序集,这种程序集是最常见的。程序<br /> <br />集也可以由多个文件组成,每个文件都是一个模块文件或者是一个资源文件,这样的程序集被称

tolearner的专栏 1502

C#程序集系列08,设置程序集版本

区别一个程序集,不仅仅是程序集名称,还包括程序集版本、程序集公匙、程序集文化等,本篇体验通过界面和编码设置程序集版本。   □ 通过Visual Studio设置程序集版本 →右键项目,选择"属性",选择"应用程序"→点击"程序集信息",设置如下,点击确定→点击项目Properties文件夹下的AssemblyInfo.cs,可以看到程序集版本已经设置生效[assembly: AssemblyVe...

weixin_34199405的博客 618

共享程序集

3.1 两种程序集、两种部署方式      1、.NET 框架支持两种程序集:强命名程序集(strongly named assembly)和非强命名程序集。      强命名程序集有一个发布者的公钥/私钥对签名,其中的公钥/私钥对唯一地标识了程序集的发布者。利用公钥/私钥对我们可以对程序集进行唯一的标识、安全策略和版本策略。      2、一个程序集有两种部署方式:私有方式和全局方式。    

小薛的Blog 2997

程序集标识属性

程序集属性是提供程序集相关信息的值。属性分为以下几组信息: 程序集标识属性。 信息性属性。 程序集清单属性。 强名称属性。 程序集标识属性三种属性与强名称(如果适用)一起决定程序集的标识:名称、版本和区域性。这些属性构成程序集的完整名称,并且在代码中引用程序集时需要这些属性。您可以使用属性来设置程序集的版本和区域性。编译器或程序集链接器 (Al.exe) 根据包含程

xinzhe的专栏 1494

如何部署程序集

引用MSDN上的原文:>原地址:http://www.microsoft.com/china/MSDN/library/enterprisedevelopment/softwaredev/misbasicinstincts.mspx部署程序集 发布日期: 12/14/2004 | 更新日期: 12/14/2004Ted Pattison本月的 Basic I

Aji.yang的专栏 1191

强命名程序集

强命名程序集的缘由:      目前Windows中出现的DLL Hell问题(两个不同的公司可能开发处具有相同名称的程序集,如果将相同名称的程序集放置到同一个目录下,则会出现程序集覆盖现象,最后安装的程序集会覆盖前面的程序集,从而可能导致应用序不能正常运行)。由此看来,仅靠名称来区分程序集是不足够的。CLR采取了强命名程序集的方式来唯一的表示程序集。强命名程序集包含四个标识:名称,版本号,语言文

calm_agan的专栏 3582

C#程序集系列09,程序集签名

在"C#程序集系列08,设置程序集版本"中体验了为程序集设置版本,但对于程序集的安全性来说,还远远不够。本篇体验程序集的签名。   □ 程序集的签名 →F盘as文件夹下有多个文件→在程序集所在文件夹创建密匙→打印密匙密匙是一堆乱码,这是经过加密了。→在密匙的基础上创建公匙Public Key→打印公匙Public Key注意:这里的public token是public key经过哈希算法而获得的...

weixin_33726943的博客 377

【CSharp】程序集

.NET程序的库和可执行文件称为程序集。程序集时编译好的、面向.NET Framework的代码的逻辑单元。 程序集是完全自描述性的,它是一个逻辑单元而不是物理单元,这意味着它可以存储在多个文件中(动态程序集存储在内存种,而不是存储在文件中)。如果一个程序集存储在多个文件中,其中就会由一个包含入口点的主文件,该文件描述了程序集中的其他文件。 可执行代码和库代码使用相同的程序集结构。唯一的区别是...

zhy29563 551
上一篇: 中间语言(IL)
下一篇: C# - 序列化和反序列化
dodream
博客等级 码龄21年 93粉丝 247原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值