When using a third-party class library, you will often see its own Demo program, including such a Demo license file
Copy codeThe Code is as follows:
Infragistics. Win. Misc. UltraButton, Infragistics2.Win. Misc. v11.1, Version = 11.1.20111.2009, Culture = neutral, PublicKeyToken = f8b58b62b52fdf31
Infragistics. Win. Misc. UltraLabel, Infragistics2.Win. Misc. v11.1, Version = 11.1.20111.2009, Culture = neutral, PublicKeyToken = f8b58b62b52fdf31
Infragistics. Win. Printing. UltraPrintPreviewDialog, Infragistics2.Win. UltraWinPrintPreviewDialog. v11.1, Version = 11.1.20111.2009, Culture = neutral, PublicKeyToken = bytes
Infragistics. Win. UltraWinDataSource. UltraDataSource, Infragistics2.Win. UltraWinDataSource. v11.1, Version = 11.1.20111.2009, Culture = neutral, PublicKeyToken = f8b58b62b52fdf31
The format of this file is a text file, but it must be written according to its format requirements:
Control name, Full Set Name
First, write a list of controls to be authorized as needed, as shown above. For example, if the hostapp.exe application references the authorization control MyCompany. Samples. LicControl1 in Samples. DLL, you can create HostAppLic.txt that contains the following content. MyCompany. Samples. LicControl1, Samples. DLL.
Call the following command to create the. licenses file HostApp.exe. licenses. Lc/target: HostApp.exe/complist: hostapplic.txt/I: Samples. DLL/outdir: c: \ bindir
Generate the. licenses file as a resource embedded in the resource of hostapp.exe. If the C # application is generated, use the following command to generate the application.
Csc/res: HostApp.exe. licenses/out: HostApp.exe *. cs
The LC. EXE file in the. NET Framework SDK directory is compiled by the. NET language. Its function is to generate a resource file based on the content of the license file. At the final moment of compilation, the CSC compiler embeds the generated resource file into the execution file.
Load LC. EXE with. NET Reflector to start the source code analysis journey.
At the entry of the program, the command line parameters are analyzed and the specified functions are executed according to different parameters. First, let's look at a complete parameter list. The Code is as follows:
Copy codeThe Code is as follows:
If (! ProcessArgs (args ))
{
Return num;
}
MSDN has a complete explanation. Copy it to the following for your reference to reduce the interruption of Thinking Caused by MSDN search.
/Complist: filename specifies the name of the file containing the authorization component list. These authorization components must be included in the. licenses file. Each component is referenced by its full name, and each line has only one component. The command line user can specify a separate file for each form in the project. Lc.exe accepts multiple input files and generates a. licenses file.
/H [elp] shows the command syntax and options of the tool.
/I: module specifies modules that contain components listed in the file/complist. To specify multiple modules, use multiple/I labels.
/Nologo undisplay Microsoft startup title.
/Outdir: path specifies the directory for storing the output. licenses file.
/Target: Specifies the executable file for which the. licenses file is generated.
/V specifies the verbose mode and displays the compilation progress.
/? Displays the command syntax and options of the tool.
The key role of the ProcessArgs method is to analyze the component list and assembly list, as shown in the following code:
Copy codeThe Code is as follows:
If ((! Flag3 & (str2.Length> 7) & str2.Substring (0, 7). ToUpper (CultureInfo. InvariantCulture). Equals ("TARGET :"))
{
TargetPE = str2.Substring (7 );
Flag3 = true;
}
If ((! Flag3 & (str2.Length> 8) & str2.Substring (0, 9). ToUpper (CultureInfo. InvariantCulture). Equals ("COMPLIST :"))
{
String str3 = str2.Substring (9 );
If (str3! = Null) & (str3.Length> 1 ))
{
If (compLists = null)
{
CompLists = new ArrayList ();
}
CompLists. Add (str3 );
Flag3 = true;
}
}
If ((! Flag3 & (str2.Length> 2) & str2.Substring (0, 2). ToUpper (CultureInfo. InvariantCulture). Equals ("I :"))
{
String str4 = str2.Substring (2 );
If (str4.Length> 0)
{
If (assemblies = null)
{
Assemblies = new ArrayList ();
}
Assemblies. Add (str4 );
}
Flag3 = true;
}
After the component and assembly are analyzed, the meaning of the ResolveEventHandler delegate is returned. If the running Library Class Loader cannot parse the reference to the Assembly, type, or resource, the corresponding event is triggered, so that the callback has the opportunity to notify the Runtime Library of the Assembly, type, or resource in which the Assembly is referenced. ResolveEventHandler is responsible for returning the assembly of the resolution type, assembly, or resource.
Copy codeThe Code is as follows:
ResolveEventHandler handler = new ResolveEventHandler (LicenseCompiler. OnAssemblyResolve );
AppDomain. CurrentDomain. AssemblyResolve + = handler;
The list of components analyzed by the first parameter is cyclically generated to generate authorization licenses for them.
Copy codeThe Code is as follows:
DesigntimeLicenseContext creationContext = new DesigntimeLicenseContext ();
Foreach (string str in compLists)
{
Key = reader. ReadLine (); hashtable [key] = Type. GetType (key); LicenseManager. CreateWithContext (Type) hashtable [key], creationContext );
}
Finally, generate the license file and save it to the disk. Wait for the CSC compiler to compile it into the resource source file and embed it into the program set.
Copy codeThe Code is as follows:
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 ();
}
}
This method is the protection component recommended by. NET Framework. It is different from the input serial number and RSA signature we usually discuss.
Let's take a look at how commercial components apply such technical protection components.
Copy codeThe Code is as follows:
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.
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
}
First, create a type that inherits from the License type, and then create a type that inherits from the LicenseProvider to issue a License, including the design License and runtime License, as shown in the preceding example, there is no limit during the design and it can be run. However, you must have a serial number to generate a license object, instead of returning null.. NET Framework type. The entire verification process is completed by. NET.
You only need to apply the license protection mechanism as follows:
Copy codeThe Code is as follows:
[LicenseProvider (typeof (RedistributableLicenseProvider)]
Public class MyControl: Control {
// Insert code here.
Protected override void Dispose (bool disposing ){
/* All components must dispose of the licenses they grant.
* Insert code here to dispose of the license .*/
}
}
The verification code (RedistributableLicenseProvider) of the Control license is completely separated from the control logic. The division of labor and collaboration protects the intellectual property rights of components.