.NET script

zhaozj2021-02-16  57

.NET script (a) Author: jconwell

Introduction

Do you know what is your nostalgia? script! I like to create a small script file to do some small tasks for me, or to test a small piece of code without creating an engineering or a solution. I like to handle and clear just a small file instead of a solution folder, an engineering folder, and an attached BIN and OBJ folder. I miss those times, this is why I created .NET script.

What is .NET script? Basically, it is a simple console application that reads the XML document from the .dnml file (Dot Net Markup Language, .NET tag language, this is my definition, haha). This XML document contains the language of the sub-elements, the storage assembly reference, the written code belonging, and the code that is actually compiled and executed. That console application, I call the script engine, read XML text and analyze the required data. Then it uses Csharp, VisualBasic, and CodeDom namespaces to compile code and load the assembly as the result to memory. This engine uses the reflex mechanism to perform the entry function of the generated program set. When the user closes the console window, the script engine is turned off, and the assembly in the memory will not be existed, it will be cleaned up by the garbage collector. There is no library or executable generated.

Dot Net Markup

Let's take a look at the .NET markup language. It is actually very simple. Here is an example of it. I will explain each element in the XML document.

Using system.windows.forms;

Public Class Test

{

Public static void main ()

{

Console.writeline ("this is a test");

MessageBox.show ("this is another test");

TEST2 TWO = New Test2 ();

TWo.stuff ();

}

}

Public Class Test2

{

Public void stuff ()

{

Console.writeline ("Instance Call");

}

}

]]>

This document XML element is called (Can you guess what it represents?). There are three different sub-elements inside this element, you can use them how to compile the script.

The first is the element, which only has an attribute called "askMBLY". The "assembly" property contains the program set name (including the file extension) you want to reference. A .dnml document can contain many elements, which correspond to the reference list you added to the project in VS.NET. For each of your code, you must add a element.

Based on the consideration of assembly detection, any GAC assembly you reference will be automatically found by the CLR. But if you quote a set that is not a GAC, the situation is different. Suppose you quote a non-GAC assembly called Common.dll. In order to make your .NET script correctly, Common.dll must be placed in two places. First it must be placed in the folder to which you belong to your .dnml file. Second, it must be placed in the folder where the script engine is located. I am trying to solve this problem, but I have a non-GAC assembly that must be stored in two different folders. The next element is , it has an attribute called 'Name'. One .dnml file can only have a language element. Two possible values ​​for 'Name' attributes are 'c #' and 'VB', I hope they are described.

The last element is , which contains a CDATA XML element. This element contains the code that will be executed when you execute the.dnml file. But in order to use it you must follow some interface rules. First, it is actually just ordinary embedded C # and VB.NET, all methods and fields must be placed inside the class. Second, you can define any more classes, but you must have a class with a public static function called "main", no input parameters, nor return results. It is only the entry method search for the scripting engine; if it is found, it will call it. Of course, which class "main" method is irrelevant because the scripting engine will traverse each type defined until it finds the main method.

How is the script engine work?

Most of the code for the script engine is very intuitive, so I will describe every aspect of it. There is a very interesting part is a class called AssemblyGenerator, which only has one method called CreateAssembly (). This method will complete all work, compile and generate a new assembly, just as seen below.

// Create an Instance of the C # compiler

Codedomprovider CodeProvider = NULL;

IF (Code.Iscsharp)

CodeProvider = New CsharpcodeProvider ();

Else

CodeProvider = new vbcodeprovider ();

ICodeCompiler Compiler = CodeProvider.createCompiler ();

First of all, I need to declare an instance of a Code CodeDomProvider. It is the base class of CsharpcodeProvider and class VBCodeProvider. You can use these languages ​​to create a CodeGenerator object, which will be used to generate code based on the CodeDom object map you created according to it. You can create a CodeParser object that generates a CodeDom object map according to your incoming source code string (in the current 1.1 .NET Framework version, it returns a null value). The xxxprovider object can also be used to create a codecompiler, which is exactly what I use here. The CodeCompiler class is the code I used to compile the .dnml file, and generate a new assembly class.

Therefore, based on the language type defined in the .dnml file, I created a suitable XXXCodeProvider object. From this object, I request a CodeCompiler instance that will be different from the language.

// Add compiler parameters

CompilerParameters CompilerParams = New CompilerParameters (); CompilerParams.comPilerOptions = "/ Target: library / optimize";

CompilerParams.GenerateExecutable = false;

CompilerParams.GenerateInmemory = true;

Compilerparams.includedebuginformation = false;

CompilerParams.ReferenceDassemblies.Add ("mscorlib.dll");

CompilerParams.ReferenceDassemblies.Add ("System.dll");

// Add Any Aditional Reference Needed

Foreach (String Refassembly In Code.Reference)

CompilerParams.ReferenceDassemblyMblies.Add (RefaSsembly);

Next, I created a CompilerParameters object. This class basically packages all command line parameters used by CSC.exe (C # compiler) and VBC.exe (VB.NET compiler). A particularly important parameter is attribute generateInmemory, here I use it. It ensures that when the code is compiled, the generated assembly only resides in memory without creating any files as a result.

The last part of this code is added to all the references required for the script code to the CompilerParameters. By default, I added a reference for Mscorlib.dll and System.dll. Then I added a reference to the assembly indicated by each element in the .dnml file.

// Actually Compile The CODE

CompilerResults Results = compiler.compileassemblyfromsource

CompilerParams, Code.SourceCode)));

// do we have any compiler errors

IF (results.errors.count> 0)

{

FOREACH (CompileRerror Error In Results.erro)

DotNetScripTENGINE.LOGALLERRMSGS ("Compine Error:" Error.ErrorText);

Return NULL;

}

Then, I called CodeCompiler.comPileAsessemblyFromSource, it passed the CompilerParameters object and the string variable containing the actual code to be compiled. The returned object belongs to class CompilerResults. When compiling an error, this object contains a collection of CompileError objects, I will use it to display the user when compiling.

// Get a Hold of the Actual Assembly That Was generated

AskEMBLY GeneratedASsembly = Results.comPiledassembly;

// Return THE Assembly

Return generatedassembly;

}

If the script code is successfully compiled, the CompilerRESLTS object will contain a reference to the newly compiled and created assembly. I preserved the object and returned to the modified method.

Once the assembly is successfully created and returned, the script engine will use the reflection to traverse each generated type, look for a static method called 'main'. If you find it, you will use the reflection to perform it. If not found, it will return to the user an error to explain the problem of occurrence. last step

The .NET script engine can also add and delete the association of the.dnml file. This means that once the file is associated, you can do it in order to execute. DNML file just double-click it. When you are doing, the script engine will perform, command line parameters of a correlation path and the .dnml file name will be passed to it. Then, this engine will read the file and process the corresponding XML.

In order to create a .dnml file, the association between the .NET script engine, you only need to double-click DotNetScripTengine.exe. When it does not perform any command line parameters, it will create a file on your server. If you run DotNetScripTengine.exe in the console, and get to the 'Remove' parameter, the engine will delete file associations on your server.

转载请注明原文地址:https://www.9cbs.com/read-27980.html

New Post(0)