📜 ⬆️ ⬇️

Automating the assembly of .NET applications - part 2



Three years ago I wrote an article about automating the assembly of .NET applications. It was planned that it will be in two parts. The first part is the basics of using NAnt and examples of performing basic tasks (compiling a project, building an ASP.NET site). In the second part I wanted to talk about more advanced tasks like configuring configs, running unit tests, etc.

When the second part was almost ready, I re-read it and realized that it was a retelling of the NAnt documentation. Outside the context of real-world tasks, it is useless, and if the need arises, all the necessary information is easily found in Google. As a result, the article still lies in the drafts.
')
Now I would like to bring to your attention the second part, but on a slightly different topic than originally planned. I will talk about writing my own tasks for NAnt, as well as a brief review of the task library I wrote for myself for the last 4 years.


Writing your own tasks


Task (task) is an element of the build script that performs a specific action (for example, copies a file to another folder or runs unit tests). Task can contain parameters. For example, the regasm task registers COM objects from the specified library, and its parameter is the path to the desired .dll file.

<regasm assembly="myAssembly.dll" /> 

NAnt already contains a large number of tasks for solving various tasks, but, unfortunately, sometimes they are not enough. In this case, you can write your own tasks that perform the necessary actions and use them in your build scripts. Make it very easy!

Each task is a .NET class inherited from the base class NAnt.Core.Task (from the NAnt.Core.dll library). To write your own task, open Visual Studio, create a new Class Library project, add a link to NAnt.Core.dll and create something like this:

 [TaskName("my-task")] public class MyTask : NAnt.Core.Task { protected override void ExecuteTask() { // TODO:     System.IO.File.WriteAllText("file.txt", "Hello, world!"); } } 

NAnt.Core.Task is an abstract class, all the descendants of which must contain their own implementation of the abstract method void ExecuteTask() - it is in it that the actions are performed for which the task is intended. In order to set the name of the XML tag, which will then be used in build scripts, you need to mark the created class with the attribute TaskName .

To pass parameters, add properties to the class and mark them with the TaskAttribute attribute. At run time, these properties will contain the values ​​specified in the task parameters in the build script.
Please note that it is more convenient to use the properties of the type System.IO.FileInfo , rather than string , to pass in the file path parameters.

 [TaskAttribute("path", Required = true)] public string Path { get; set; } 

To write messages to the log, use the Log method from the base class.

 Log(Level.Warning, "  "); 


Use and debug your own tasks


To use your own tasks in the build script, you need to connect your compiled library using the loadtasks , and then call the necessary task using the name specified in the TaskName attribute.

 <loadtasks assembly="MyLibrary.dll" /> <my-task path="D:\temp" /> 

To debug your task, add to the desired location the call to the static method System.Diagnostics.Debugger.Launch() and build the library in Debug mode. When you run the task via NAnt in the specified location, the script execution will stop and you will be asked to start Visual Studio for debugging.

Other


Over the past few years I have occasionally had to write my own tasks for solving various specific tasks. I added all of them into one common project (the source code lies on code.google.com) and now quite a lot of interesting things have accumulated there. Below are examples of its use. I hope this is useful to someone.

Creating a new MSSQL database
 <createDatabase database="dbname" instance="." integratedSecurity="true" /> 

MSSQL database backup
 <!-- integrated security --> <backupDatabase database="dbname" instance="." integratedSecurity="true" backupFileName="d:\test.bak" /> <!-- user & password --> <backupDatabase database="dbname" instance="." user="sa" password="123" backupFileName="d:\test.bak" /> 

Adding MSSQL users database rights (users add the db_owner role; if users do not exist, they are created)
 <addDatabaseUsers database="dbname" instance="." integratedSecurity="true"> <user login="IIS APPPOOL\test" isWindowsUser="true" /> <user login="test1" password="123" /> <user login="test2" password="qwert" /> </addDatabaseUsers> 

Minification of JS and CSS (uses YUI Compressor for .NET ):
 <minify-js obfuscate-js="true" with-line-breaks="true" disable-optimizations="true"> <files> <include name="test2.js" /> <include name="test.js" /> </files> </minify-js> <minify-css compression-type="hybrid" with-line-breaks="true"> <files> <include name="*.css" /> </files> </minify-css> 

Compiling .LESS files (using DotLess ):
 <compile-less file="D:\projects\ecm7milk\milk.less" result="D:\milk.min.css" /> 

Creating a site in IIS
 <createIISWebSite websiteName="xxx3.ru" fileSystemPath="d:\xxx3.ru" appPool="xxx3.ru"> <bindings> <add host="localhost" port="4898" protocol="http" /> <add host="xxx3.ru" /> </bindings> </createIISWebSite> 

Creating an application and virtual directories in IIS
 <createIISApplication websiteName="xxx3.ru" virtualPath="/admin" fileSystemPath="d:/admin" /> <createIISDirectory websiteName="xxx3.ru" applicationVirtualPath="/admin" virtualPath="/images" fileSystemPath="d:/images" /> 

XDT transformation of XML files
 <xdt target="test.xml"> <transformation> <moo1 xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform"> <moo2 xdt:Transform="Insert">123</moo2> <rewrite xdt:Transform="Insert"> <a1>456!</a1> </rewrite> </moo1> </transformation> </xdt> 

XDT transformation of XML files (transformation parameters are taken out separately)
 <!--    - --> <xdt target="test.xml"> <transformation refid="mimimi" /> </xdt> ... <raw-xml id="mimimi"> <moo1 xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform"> <moo2 xdt:Transform="Insert">123!</moo2> <rewrite xdt:Transform="Insert" xxx2="${test.property}" aaa="bbbb"> <a1 xxx1="${test.property}">456!</a1> </rewrite> </moo1> </raw-xml> <!--    --> <xdt target="test.xml"> <transformation file="transform.xml" /> </xdt> 
Note that inside the files with the transformation description you can use NAnt expressions.

Basically, that's all I wanted to tell you. I hope this will be useful to someone and will be happy to answer questions.
Thanks for attention!

Source: https://habr.com/ru/post/189190/


All Articles