Strong name

xiaoxiao2021-03-06  78

The secrets of strong naminghttp: //www.ondotnet.com/pub/a/dotnet/2003/04/28/strongnaming.htmlhttp: //dev.9cbs.net/develop/article/18/18445.shtm in .net Environment prohibited others from calling code http://network.ccidnet.com/pub/Article/c1136_a59697_p1.html Analysis .NET Sharing assembly programming http://tech.ccidnet.com/pub/disp/Article?columnid=294&articleID= Analysis of 34439 & Pageno = 1. AppDomain programming under NET http://develop/article?cidnet.com/pub/disp/Article?columnid=294&articleid=30763&pageno=1 Creating a key for creating and using a Strong name assembly language C # MS-Help: //Ms.vscc.2003/ms.msdnqtr.2003feb.2052/cpguide/html/cpConcreatingKeypairforuseIncreatingstrongly-namedassembly.htm

Visual Basic

All shows that you want to use a strong name to a program segment signature, you must have a public key / private key pair. This pair of encryption public keys and encrypted private keys are used to create a strong name assembly during the compilation process. You can use a Strong Name Tool (sn.exe) to create a key pair. The key pair file usually has a .snk extension. Creating a key pair At the command prompt, type the following command: Sn -k In this command, "File Name" is the name of the output file containing the key pair. The following example creates a key pair named SGKEY.SNK. Sn -k sgkey.snk If you need to delay the sequence signature and control the entire key pair (the key pair is unlikely outside the test scheme), you can generate a key pair using the following command, then extract the public key to A separate file. First, create a key pair: Sn -k keypair.snk Next, extract the public key from the key pair, and copy it into a separate file: Sn -p keypair.snk public.snk creates a key pair The file must be found in the Strong Name Signature tool. When signing the assembly using a strong name, the assembly link (Al.exe) finds key files associated with the current directory and output directory. When using the command line compiler, simply copy the key to the current directory containing the code module. If you want to use IDE (for example, Visual Studio .NET) to sign a strong name for the assembly, you must know the location of the IDE lookup key file. For example, Visual Basic .NET looks for key files in a directory containing the Visual Studio solution, while the C # compiler looks for key files in a directory containing binary files. Place the key file in the appropriate project directory and set the file properties, as shown below: [Visual Basic] [c #] [assembly: askEMBLYKEYFILEATTRIBUTE (@ ". /. /. ./key.snk ")] Add: 'Query.snk is the key file for your homing class library. Generate a key file with sn.exe: Sn -k c: /query.snk finds a solution:

1 - Use Sn -k Generate a Key File PrivateKey

2 - Use Sn -P , get a publickey file from privateKey

3 - You can get the publickeytoken (I think it should be) using Sn -T PrivateKey and using Sn -T Publickey, but these two values ​​are different, which makes me a bit confused.

Sn -t asseembly uppercase T can remove the publickeyToken name directly from the compiled Assembly file including a public key and a private key, SNK works only when compiling, he encrypts Assembly Header with private key, out of Header Reserved area, this area is stored as a public key. User import this Assembly Mscoree.dll first decrypts with a public key, and then saved the HASH value saved in Manifest. SNK file organization is compiled inside, not to customers. Sn -k mykey.snk

[Assembly: AssemblyVersion ("1.0.1.1")]]]]

[Assembly: asmblyMblyKeyFile ("..////rkey.snk")] Gacutil / I myassembly.dll

You can use VS directly, you don't need to use the command line mode. As long as you generate the SN file, then in the program project properties, one can set the key file, after setting it, the compilation is a collected assembly. For example, you use Appdomain.currentDomain.Load ("MyLib, PublickeyToken = 324223423423"); this method loads MYLIB, if you can load it, representing publickeyToken is definitely 324223423423. Otherwise, you can't find the specified Assembly. This is DOTNET. And it is not reliable (essentially impossible to spoof. Unless the private spoon of the algorithm is broken) ASM.Fullname, you will need to analyze the string. Just use asm.assemblyname.getpublicKeyToken ().

PublickeyToken is the result obtained with an asymmetric algorithm. Only use the specified private pocket to get the publickeyToken. If publickeyToken can verify who Assembly is released. .

I created a WinForm control, using a strong name (with the "sn -tp assembly" command to see the public key and public key mark). Http://community.9cbs.net/expert/topic/3395/339588.xml?temp=.1084711

Compiled DLL location in: D: /myControl/bin/mycontrol.dll

I have successfully released it to the GAC: Gacutil / I D: /myControl/bin/mycontrol.dll

The problem now is: New test application, click "Add / Transfer" on the toolbox, add D: /MYCONTROL/BIN/myControl.dll to the toolbox, drag to Form Show "Not found .NET assembly myControl", you must first add MyControl's reference to drag the control to the Form. If you do not publish myControl.dll to the GAC area, you can drag directly to the FORM without reference (automatically add reference).

This problem has been bothering me for a long time. In the previous post, someone replied that I need to re-sign, I used the "sn -r " command to re-sign the back, still not.

Finally solved, add the corresponding key to the note table:

HKEY_LOCAL_MACHINE / SOFTWARE / Microsoft / .NetframeworkHttp: //dev.9cbs.net/Article/21/21435.shtm

CSHARP TIPS: Strong Name when referenced by ActiveX / COM component Select the blog keyword C #; strong name; COM / ACTIVEX source

problem

Under the DOTNET platform, a complete class library is provided, but the first version is always impossible, and because of historical legacy issues, often and com

Interoperability between / ACTIVEX components.

The problem that the author touched is to call the Excel object in an Assembly, but the assembly needs to be encapsulated into an ActiveX's Control for IE for client script call. In short, I used a COM component in C #, but also packaged myself into a COM component, it sounds a bit of a little more than a better way.

In such packaged mode, I encountered a problem. If an assembly wishes to encapsulate the ActiveX / COM component, it must have a strong name, that is to specify the SNK (Strong Name Key) when compiling. But when an assembly is compiled by a strong name, it requires that the other Assembly referenced by itself must have a strong name, otherwise it is not possible to successfully compile. And when we directly refer to a COM component (for example: Excel 10 Object Library), VS.NET can help us import type library, but at this time, the reference type library is not a strong name, the environment expected in the author Can't compile success. solve

I feel very tricky, it seems to be caught in and dead, but I've been able to find the document very easily, and the corresponding tool is provided in the DOTNET Framework, which is able to convert COM's type library. He is tlbimp.exe (everyone can Found in the directory similar to "C: / Program Files / Microsoft Visual Studio .NET 2003 / SDK / V1.1"). TLBIMP can package a COM component into the form of class libraries that DOTNETs can be used, and VS.NET's automatic conversion should be the tool. This tool has many parameter switches, which requires a strong name to open an additional switch. Introduce the author thinks the most likely parameters:

/ OUT: FileName: The name of the output file after the type library conversion.

/ Namespace: Namespace: The namespace used by the type library conversion.

/ keyfile: filename: Specifies the SNK file used in the conversion, indicating that the parameter, the type library after the configuration has a strong name.

Complete examples are as follows:

Tlbimp Excel.exe /out:Iinterop.Excel.dll / namespace: Excel /keyfile :Excel.snk

The SNK file can be generated by another tool Sn in the DOTNET, and details are not described herein.

Complete the above work, directly quote the type library we constructed in the project, you can successfully compile with a strong named DLL.

If it is a control, instead of ordinary component, then you can't use TLBIMP, but you need to use the AXIMP.EXE tool, how to use TLBIMP, he generates two files: one is the proxy file of the type library, the other is Proxy file for Windows Form.

Further resolution

However, there is a simpler solution that sets "Wrapper Assembly Key File" in the engineering attribute, this property. After setting this property, the COM / ActiveX component added by add report will be identified, with a strong name.

This requires a setting, it should be more convenient.

Reference documentation

TLBIMP related: http://msdn.microsoft.com/library/en-us/cptools/html/cpgrftypelibraryImportertlbimpexe.asp

SN related: http://msdn.microsoft.com/library/en-us/cptools/html/cpgrfstrongnameutilitySnexe.asp

AXIMP Related: http://msdn.microsoft.com/library/en-us/cptools/html/cpgrfwindowsFormSactiveXControlImportraximpexe.aspc# Project Attribute Description: http://msdn.microsoft.com/library/en-us/cscon/ HTML / vcurfcprojectGeneralPropertyPage.asp

Author Blog:

http://blog.9cbs.neet/mittermeyer/

related articles

Code Series --Base24 Coding CSHARP TIPS: Call API Registration and Logout Windows Service Csharp Tips: Application Access Integration Windows Certified Site Exchange Full Text Retrieval Overview Csharp Tips: Let DOTNET implemented COM object support IOBJECTSAFETY interface

http://www.blogcn.com/user8/flier_lu/blog/3765092.html

Use the Fusion API to control the GAC and the traditional Windows directory storage positioning, and the registry positioning in the COM is different. The CLR uses several-level component positioning strategies to try to completely solve the problem of DLL Hell. Where GAC is the most important central repository shared by CLR in CLR, all Strong Named Accessories (Assembly) should be managed through GAC to manage sharing and version management. But unfortunately, the BCL does not directly provide control and management functions to the GAC, but managed by a command line tool named Gacutil.exe. Trouble is that this interface is not friendly tool. NET Framework releases version distribution, must be included in the installer.

Fortunately, the CLR provided a formal document, but passed

KB317540 semi-disclosed Fusion API is used to control code storage mechanisms such as GAC.

These interfaces and functions definition files can be found in the .NET FX 1.1 in the SDK's include / fusion.h (.IDL) file, only include / fusion.h in FX 2.0 Beta, probably because of Fusion and complete The reason why merged into mscorwks.dll.

This API is mainly divided into three sections: assembly list and information acquisition; assembly, deletion, and information queries; assembly and settings for Assembly installation reference information.

The acquiring of the Assembly list and information is the most important interface we get detailed.

First, enumerate the location where the cache is defined in the ASM_Cache_Flags:

The following is the program code: typedef enum {asm_cache_zap = 0x1, ASM_CACHE_GAC = 0x2, ASM_CACHE_DOWNLOAD = 0x4} ASM_CACHE_FLAGS;

Zap is NGEN to generate a cache of local code; GAC is a buffer of global strong name components; Download is a cache for Internet download components. You can use the getCachePath function to get these three cache physical directories.

The following program code is: public class Fusion {[Flags] public enum ASM_CACHE_FLAGS {ASM_CACHE_ZAP = 0x1, ASM_CACHE_GAC = 0x2, ASM_CACHE_DOWNLOAD = 0x4} [DllImportAttribute ( "fusion.dll" [img] /images/wink.gif [/ img] ] public static extern int GetCachePath (ASM_CACHE_FLAGS dwCacheFlags, [MarshalAs (UnmanagedType.LPWStr)] StringBuilder pwzCachePath, ref uint pcchPath);} public class FusionUtil: Fusion, IEnumerable {public static string GetCachePath (ASM_CACHE_FLAGS cache) {uint len ​​= 0; int hr = Fusion.GetCachePath (cache, null, ref len); if (hr == ComUtil.ERROR_INSUFFICIENT_BUFFER && len> 0) {StringBuilder sb = new StringBuilder ((int) len); ComUtil.ComCheck (Fusion.GetCachePath (cache, SB, REF LEN); RETURN SB.TOSTRING ();} else {return ";}}} You can get an Assembly Enumerator IASSEMBLYENUM interface instance through the createassemblycache function, and then via IassemblyEnum :: getNextasseMbly The function traverses Assembly in all containers.

The following program code is: public class Fusion {[ComImport, Guid ( "21b8916c-f28e-11d2-a473-00c04f8ef448" [img] /images/wink.gif [/ img], InterfaceTypeAttribute (ComInterfaceType.InterfaceIsIUnknown)] public interface IAssemblyEnum {[PreserveSig] int GetNextAssembly (out IApplicationContext ppAppCtx, // Must be null. out IAssemblyName ppName, // pointer to a memory location that is to receive the interface pointer to the assembly name of the next assembly that is enumerated. uint dwFlags) ; // must be zero [preservesig] int rev (); [preservesig] int clone (out assemblyenum ppenum);} [DLLIMPORTATTRIBUTE ("fusion.dll" [ivg] /images/wink.gif [/ img] public static extern int CreateAssemblyEnum (out IAssemblyEnum ppEnum, // pointer to a memory location that contains the IAssemblyEnum pointer IApplicationContext pAppCtx, // Must be null. ??? IAssemblyName pName, // An assembly name t hat is used to filter the enumeration Can be null to enumerate all assemblies in the GAC ASM_CACHE_FLAGS dwFlags, // Exactly one bit from the ASM_CACHE_FLAGS enumeration int pvReserved); // Must be NULL} public class FusionUtil:... Fusion, IEnumerable { private ArrayList _asms = new ArrayList (256); private ASM_CACHE_FLAGS _cache = ASM_CACHE_FLAGS.ASM_CACHE_GAC; public void Refresh (ASM_CACHE_FLAGS cache) {IAssemblyEnum asmEnum; this._cache = cache; ComUtil.ComCheck (CreateAssemblyEnum (out asmEnum, null, null, cache, 0)); IAPPlicationContext AppCTXT; IASSEMBLYNAME Asmname; _ASMS.CLEAR ();

while (! ComUtil.SUCCEEDED (asmEnum.GetNextAssembly (out appCtxt, out asmName, 0)) && asmName = null) {AssemblyName name = new AssemblyName (asmName, appCtxt); _asms.Add (name);}} public void Refresh ( {Refresh (asm_cache_flags.asm_cache_gac);}} You can get an IASSEMBLYNAME that expresses its name information via the IASSEMBLYNum :: GetNextassembly function, you can further get the details of Assembly, such as name, version number, culture, by this interface, such as name, version number, culture, Public Key, etc. You can encapsulate it through an AssemblyName class.

The following program code is: public class AssemblyName {private IAssemblyName _name; private IApplicationContext _ctxt; public AssemblyName (IAssemblyName name, IApplicationContext ctxt) {this._name = name; this._ctxt = ctxt; Properties = new PropertyCollection (this);} public Readonly PropertyCollection Properties;}

The IASSEMBLYNAME interface itself provides some direct acquisition methods of common information, such as Assembly name and version number information:

The following is the program code: public class assemblyname {public version assembly {get {uint hi, low; comutil.comCheck (_name.getversion (out ut hi, out low); return new system.version ((int) (hi >> 16), (int) (h & 0xfff), (int) (now >> 16), (int) (low & 0xfff);}}}

However, more commonly used by getDisplayName methods similar "System.configuration.IgnorectionHandler, System, Version = 1.0.5000.0, Culture = neutral, publickeyToken = B77A5C561934E089", "" "" "" "

The following program code is: public class AssemblyName {protected string getDisplayName (ASM_DISPLAY_FLAGS flags) {uint len ​​= 0; int hr = _name.GetDisplayName (null, ref len, flags); if (hr == ComUtil.ERROR_INSUFFICIENT_BUFFER && len> 0 ) {StringBuilder displayName = new StringBuilder ((int) len); ComUtil.ComCheck (_name.GetDisplayName (displayName, ref len, flags)); return displayName.ToString ();} else {return "";}}} flag ASM_DISPLAY_FLAGS Define explicit names that wish to get from which parts are

The following program code is: [Flags] public enum ASM_DISPLAY_FLAGS {ASM_DISPLAYF_VERSION = 0x1, // Includes the version number as part of the display name ASM_DISPLAYF_CULTURE = 0x2, // Includes the culture ASM_DISPLAYF_PUBLIC_KEY_TOKEN = 0x4, // Includes the public key.. token. ASM_DISPLAYF_PUBLIC_KEY = 0x8, // Includes the public key. ASM_DISPLAYF_CUSTOM = 0x10, // Includes the custom part of the assembly name. ASM_DISPLAYF_PROCESSORARCHITECTURE = 0x20, // Includes the processor architecture. ASM_DISPLAYF_LANGUAGEID = 0x40, // Includes the language ID. ASM_DISPLAYF_DEFAULT = ASM_DISPLAYF_VERSION | ASM_DISPLAYF_CULTURE | ASM_DISPLAYF_PUBLIC_KEY_TOKEN}

Generally speaking, explicit names consisting of name, version number, Culture, and Public Key Token.

If you want to get or set more detailed information, you can use the getProperty / setProperty method.

The following is a program code: public class Fusion {ASM_NAME_PUBLIC_KEY, ASM_NAME_PUBLIC_KEY_TOKEN, ASM_NAME_HASH_VALUE, ASM_NAME_NAME, ASM_NAME_MAJOR_VERSION, ASM_NAME_MINOR_VERSION, ASM_NAME_BUILD_NUMBER, ASM_NAME_REVISION_NUMBER, ASM_NAME_CULTURE, ASM_NAME_PROCESSOR_ID_ARRAY, ASM_NAME_OSINFO_ARRAY, ASM_NAME_HASH_ALGID, ASM_NAME_ALIAS, ASM_NAME_CODEBASE_URL, ASM_NAME_CODEBASE_LASTMOD, ASM_NAME_NULL_PUBLIC_KEY, ASM_NAME_NULL_PUBLIC_KEY_TOKEN, ASM_NAME_CUSTOM, ASM_NAME_NULL_CUSTOM, ASM_NAME_MVID, ASM_NAME_MAX_PARAMS} public class AssemblyName {protected string getProperty (ASM_NAME id) {uint len ​​= 0; int hr = _name.GetProperty (id, IntPtr.Zero, ref len); if (hr == ComUtil.ERROR_INSUFFICIENT_BUFFER && len> 0) { IntPtr buf = Marshal.AllocCoTaskMem ((int) len); ComUtil.ComCheck (_name.GetProperty (id, buf, ref len)); string str = Marshal.PtrToStringUni (buf); Marshal.FreeCoTaskMem (buf); return str; } Else {return "";}} protected byte [] getPropertyData (ASM_NAME id) {uint len ​​= 0; int hr = _name.GetProperty (id, IntPtr.Zero, ref len); if (hr == ComUtil.ERROR_INSUFFICIENT_BUFFER && len> 0) {IntPtr buf = Marshal.AllocCoTaskMem (( Int); Comutil.comCheck (_Name.GetProperty (ID, buf, ref let); byte [] data = new byte [len]; marshal.copy (buf, data, 0, (int); marshal .FreeCoTaskMem (buf); return data;} else return new byte [0];} public string Name {get {return getProperty (ASM_NAME.ASM_NAME_NAME);}} public string Culture {get {return getProperty (ASM_NAME.ASM_NAME_CULTURE);

}}} Public data publickey {get {return new data;}}}}}} The enumeration value ASM_NAME is used to specify which data to get, can be directly packaged by a DATA class and the PropertyCollection class. access.

The following is a program code: public class AssemblyName {public class Data {private byte [] _data; public Data (byte [] data) {_data = data;} public override string ToString () {return IntToHex (_data);} public static String INTTOHEX (Byte [] DATA) {StringBuilder SB = New StringBuilder (Data.Length * 2); for (int i = 0; i = (int) Fusion.ASM_NAME.ASM_NAME_MAX_PARAMS) throw new IndexOutOfRangeException (); return new Data (_name.getPropertyData ((ASM_NAME) id));}} public int Count {get {RETURN (INT) ASM_NAME.ASM_NAME_MAX_PARAMS;}}} PUBLIC READOSLY PropertyCollectio N Properties;

This only needs access to the index of the Properties property when used.

The following is program code: asmname.properties [assemblyproperty.publicKeyToken] .tostring () asmname.properties [assemblyproperty.custom] .tostring ()

In addition to different cached assembly lists, the installation, unloading, and information query functions for Assembly are often used. An IAASSEMBLYCACHE interface instance can be obtained by the CreateAssemblyCache function, which is operated to the cache.

The following program code is: public class Fusion {[ComImport, Guid ( "e707dcde-d1cd-11d2-bab9-00c04f8eceae" [img] /images/wink.gif [/ img], InterfaceTypeAttribute (ComInterfaceType.InterfaceIsIUnknown)] public interface IAssemblyCache {// ...} ["fusion.dll" [IMG] /IMAGES/Wink.gif [/ img]] public static extern int createassemblyingcache (out iasMblycache pPasmcache, uint dwreserved);} When installing Assembly Specify the path to the assembly's Manifest file via the PSzmanifestFilePath parameter. For most Assembly, only one independent DLL includes all information and data; but in some cases, an assembly may be compiled into a main module containing manifest information. Auxiliary Module that is coupled to multiple delayed network distribution. For example, resource files of different languages ​​Module may exist independently until they are needed.

In addition, the installed policy can be specified by the DWFlags parameter, such as IASSEMBLYCACHE_INSTALL_FLAG_REFRESH indicates that if the installation file is replaced in the original file; the assemblycache_install_flag_force_refresh flag does not consider the version number forced to replace, corresponding to the GACUTIL / F parameter.

Finally, you can also use the fusion_install_reference structure to specify external information dependent on this Assembly in the GAC, but this way reduces the reuse of the GAC, which is not recommended, which is temporarily ignored here.

The following program code is: public class Fusion {[StructLayout (LayoutKind.Sequential, CharSet = CharSet.Unicode)] public struct FUSION_INSTALL_REFERENCE {public uint cbSize; public uint dwFlags; public Guid guidScheme; // contains one of the pre-defined guids . public string szIdentifier; // unique identifier for app installing this assembly public string szNonCannonicalData;. // data is description; relevent to the guid above} public enum ASM_INSTALL_FLAG {IASSEMBLYCACHE_INSTALL_FLAG_REFRESH = 1, IASSEMBLYCACHE_INSTALL_FLAG_FORCE_REFRESH = 2} public interface IAssemblyCache {[PreserveSig] int InstallAssembly (ASM_INSTALL_FLAG dwFlags, [MarshalAs (UnmanagedType.LPWStr)] string pszManifestFilePath, IntPtr pvReserved);}} public class FusionUtil: Fusion, IEnumerable {public void Install (string fileName) {IAssemblyCache cache; ComUtil.ComCheck (Fusion.CreateAssemblyCache ( Out cache, 0)); Comutil.comCheck (cache.installassembly (fusion.as M_install_flag.iassemblycache_install_flag_refresh, filename, intptr.zero);}} You only need to give the full name of Assembly, pay attention to the name of information such as version number. If external dependency information is specified, the same information must be given. The IASSEMBLYCACHE :: Uninstallassembly method returns a status information asm_uninstall_disposition, indicating that the uninstallation is successful or not.

The following is a program code: public class Fusion {public enum ASM_UNINSTALL_DISPOSITION {IASSEMBLYCACHE_UNINSTALL_DISPOSITION_UNINSTALLED = 1, IASSEMBLYCACHE_UNINSTALL_DISPOSITION_STILL_IN_USE = 2, IASSEMBLYCACHE_UNINSTALL_DISPOSITION_ALREADY_UNINSTALLED = 3, IASSEMBLYCACHE_UNINSTALL_DISPOSITION_DELETE_PENDING = 4, IASSEMBLYCACHE_UNINSTALL_DISPOSITION_HAS_INSTALL_REFERENCES = 5, IASSEMBLYCACHE_UNINSTALL_DISPOSITION_REFERENCE_NOT_FOUND = 6} public interface IAssemblyCache {[PreserveSig] int UninstallAssembly (uint dwFlags , [MarshalAs (UnmanagedType.LPWStr)] string pszAssemblyName, IntPtr pvReserved, out ASM_UNINSTALL_DISPOSITION pulDisposition);}} public class FusionUtil: Fusion, IEnumerable {public ASM_UNINSTALL_DISPOSITION Uninstall (string assemblyName) {IAssemblyCache cache; ComUtil.ComCheck (Fusion.CreateAssemblyCache (out Cache, 0)); asm_uninstall_disposition disposition; comutil.comcheck (cache.uninst Allassembly (0, AssemblyName, INTPTR.ZERO, OUT Disption); Return Disposition;}} Also you can query a Assembly installed, cached file name, and the size of the file in the cache by IAssemblyCache :: queryness And other information.

The following program code is: public class Fusion {public enum QUERYASMINFO_FLAG {QUERYASMINFO_FLAG_VALIDATE = 1, QUERYASMINFO_FLAG_GETSIZE = 2} [StructLayout (LayoutKind.Sequential)] public struct ASSEMBLY_INFO {public uint cbAssemblyInfo; // size of this structure for future expansion public ASSEMBLYINFO_FLAG dwAssemblyFlags ; public ulong uliAssemblySizeInKB; public IntPtr pszCurrentAssemblyPathBuf; public uint cchBuf;. // size of path buf} public interface IAssemblyCache {[PreserveSig] int QueryAssemblyInfo (QUERYASMINFO_FLAG dwFlags, [MarshalAs (UnmanagedType.LPWStr)] string pszAssemblyName, out ASSEMBLY_INFO pAsmInfo); }} public class FusionUtil: Fusion, IEnumerable {public bool Check (string assemblyName, out string msg) {IAssemblyCache cache; ComUtil.ComCheck (Fusion.CreateAssemblyCache (out cache, 0)); ASSEMBLY_INFO info = new ASSEMBLY_INFO (); info. CBASSEMBLYINFO = (uint) Marshal.SizeOf (info); info.cchbuf = 0; info.pszcur rentAssemblyPathBuf = IntPtr.Zero; int hr = cache.QueryAssemblyInfo (QUERYASMINFO_FLAG.QUERYASMINFO_FLAG_VALIDATE, assemblyName, out info); if (hr == ComUtil.ERROR_INSUFFICIENT_BUFFER && info.cchBuf> 0) {info.pszCurrentAssemblyPathBuf = Marshal.AllocCoTaskMem ((int) info.cchBuf); ComUtil.ComCheck (cache.QueryAssemblyInfo (QUERYASMINFO_FLAG.QUERYASMINFO_FLAG_VALIDATE | QUERYASMINFO_FLAG.QUERYASMINFO_FLAG_GETSIZE, assemblyName, out info)); string path = Marshal.PtrToStringUni (info.pszCurrentAssemblyPathBuf); Marshal.FreeCoTaskMem (info.pszCurrentAssemblyPathBuf); msg = String.Format ("Assembly {0} ({1} KB) Installed @ {2}"

, AssemblyName, info.uliAssemblySizeInKB, path); return true;} else {try {Marshal.ThrowExceptionForHR (hr); msg = "";} catch (Exception e) {msg = e.Message;} return false;}}} If the queryasminfo_flag_validate parameter is specified, Fusion verifies the cache in the cache; if queryasminfo_flag_getsize is specified, the size of Assembly is returned via UliasSizeinkb.

Finally, you can also browse the external dependency information given when installing Assembly, or through the IASSEMBLYCACHE :: CreateAssEMBLYCACHE :: CreateassemblyCacheItem method and the IASSEMBLYCACHEITEM interface to control the cache item content. However, these advanced features are generally not used, this is no longer coming.

In .NET Framework 2.0 beta, the Fusion API has made a lot of adjustment: adds the ASM_Cache_root tag to the cache type, indicating the impact of the impact on a cache type; also adds the PEKIND enumeration type to provide multiple platforms Support; Assembly property ASM_NAME has also been extended accordingly, adding support for file version numbers, platform architecture, etc.

The following program code is: public enum PEKIND {peNone = 0, peMSIL = 1, peI386 = 2, peIA64 = 3, peAMD64 = 4, peInvalid = -1} public enum ASM_NAME {... ASM_NAME_FILE_MAJOR_VERSION = ASM_NAME_MVID 1, ASM_NAME_FILE_MINOR_VERSION = ASM_NAME_FILE_MAJOR_VERSION 1, ASM_NAME_FILE_BUILD_NUMBER = ASM_NAME_FILE_MINOR_VERSION 1, ASM_NAME_FILE_REVISION_NUMBER = ASM_NAME_FILE_BUILD_NUMBER 1, ASM_NAME_RETARGET = ASM_NAME_FILE_REVISION_NUMBER 1, ASM_NAME_SIGNATURE_BLOB = ASM_NAME_RETARGET 1, ASM_NAME_CONFIG_MASK = ASM_NAME_SIGNATURE_BLOB 1, ASM_NAME_ARCHITECTURE = ASM_NAME_CONFIG_MASK 1, ASM_NAME_MAX_PARAMS = ASM_NAME_ARCHITECTURE 1}

A new interest feature is to support two Assembly comparisons to check the similarities of two Assembly.

The following is a program code: typedefenum _tagAssemblyComparisonResult {ACR_Unknown = 0, ACR_EquivalentFullMatch = ACR_Unknown 1, ACR_EquivalentWeakNamed = ACR_EquivalentFullMatch 1, ACR_EquivalentFXUnified = ACR_EquivalentWeakNamed 1, ACR_EquivalentUnified = ACR_EquivalentFXUnified 1, ACR_NonEquivalentVersion = ACR_EquivalentUnified 1, ACR_NonEquivalent = ACR_NonEquivalentVersion 1, ACR_EquivalentPartialMatch = ACR_NonEquivalent 1, ACR_EquivalentPartialWeakNamed = ACR_EquivalentPartialMatch 1, ACR_EquivalentPartialUnified = ACR_EquivalentPartialWeakNamed 1, ACR_EquivalentPartialFXUnified = ACR_EquivalentPartialUnified 1, ACR_NonEquivalentPartialVersion = ACR_EquivalentPartialFXUnified 1} AssemblyComparisonResult; STDAPI CompareAssemblyIdentity (LPCWSTR pwzAssemblyIdentity1, BOOL fUnified1, LPCWSTR pwzAssemblyIdentity2, BOOL fUnified2, BOOL * pfEquivalent, AssemblyComparisonResult * PRESULT); a complete implementation example can be downloaded from here in the short term:

http://flier.5i4k.net/gacutilw.rar

BTW: Thanks

Junfeng Zhang's strong support in fusion

Flier_lu published

> 2004-9-11 22: 44: 41 ←