Description
This action allows you to insert pieces of code written in the popular programming language C# into the project and thereby repeatedly expand the functionality of ZennoPoster and the scope of its use.
C# is an object-oriented language, but this action does not take full advantage of this approach (classes, inheritance) and the code is executed sequentially, except for the use of classes and public variables from the using directive and general code
How to add an action to a project?
Via context menu Add Action -> Custom code -> C# code
Or use smart search .
Where can it be applied?
Almost any action of the cubes can be replaced with similar ones executed in C#, thus accelerating the development and efficiency of code execution.
Use of any development in C# in your project.
Integration of third-party libraries and their application in code.
How to work with an action?
The " Custom C# Code " cube is a regular text editor with basic code highlighting.
You can use any project variables ( Работа с переменными ), and the result can also be saved in variables, text files, tables and databases. To use the methods and properties of the project, the project
entity is used, and to work with the browser, the instance
entity is used.
If you want to use a project variable in your code, you must call it like this - project.Variables ["counter"]
. Value, where counter is the name of the variable.
Context menu
Right-clicking on the cube window opens a context menu that has the following options:
Undo-Redo
Undoes the last change in the code. If the cancellation was done incorrectly, you can redo the canceled entry. It is important to note that these actions only work in the C # window code and do not cause changes in other cubes. For a similar function in the workspace for working with cubes, there are similar actions on the ProjectMaker toolbar.
Cut-Copy-Paste-Delete
Standard actions for working with code as text.
Comment-Undo comment
Code commenting is extremely useful functionality. Especially in large projects or when debugging code. Comments can contain information about changes, links, functionality of lines or parts of code. Comments can quickly enable/disable individual lines or pieces of code for error checking and testing. To comment out a part of the code, you need to select it and click this item.
Line numbering
Enables/disables line numbering, which is important for quick navigation through the code, for finding errors after receiving information about an error in the logs. But on small projects, numbering can be turned off to expand the workspace.
In the program settings, you can set behavior by default.
Wrap lines
Setting enabled
Setting disabled
In the program settings, you can set behavior by default.
Go to line
In large projects, it is important to quickly find the erroneous section of the code. Errors are displayed in the program logs. Clicking on this menu item opens a dialog box where you can enter the line number and column number. When you confirm the entry, the cursor moves exactly to the specified place in the cube code.
Search
Opens a search box for the code of this action. You can search based on parameters: case-sensitive or not, whole word, reverse search direction, and use regular expressions or wildcards when searching. By pressing the “ Find Next ” button, the cursor moves to the first found value, repeated pressing moves the cursor to the next found value, etc.
Replacement
Almost the same as “Search”, but immediately after finding the desired value, it is replaced with the entered value. It can work in a step-by-step mode, or immediately replace all found occurrences by clicking the "Replace All" button
Insert C# snippet
The entire contents of the selected file will be inserted into the place where the cursor is currently located.
Initially, this menu item is not displayed, so that it appears, you need to add at least one file to the C# Snippets Directory or save a code fragment using the Save in C# snippet function (described below).
Files in a directory can be moved to folders and thus it is convenient to group them.
Save snippet in C#
Allows you to save the selected code fragment to a TXT-file as a snippet for further use and quick insertion in other projects.
The directory where snippets will be saved can be changed in the program settings.
Set the value from the variable
When you hover the cursor over this context menu item, a list of all “Own” and “Auto-generated” project variables opens. Selecting the required variable in the editor appears a construction of the form project.Variables ["myVar"]. Value
, which is the value of the variable myVar
.
This value always has a string type and conversion is necessary to use it as other types.
Do not return a value
Disabling this checkbox allows you to pass the result of code execution using the return statement
.
Save the result to the variable
From this list, you can substitute any variable into which the value will be saved according to the result of the return
execution, of course, if the checkbox from the previous paragraph is disabled.
Each C # line must end with a semicolon ;
... This helps the compiler determine where the line ends. Without this symbol, the project will simply throw an error at startup.
Settings
To set the default settings for the C# cube, use this part of the project settings (Project settings
Converting actions to code
It is important to note that ZennoPoster has functionality that allows beginners to quickly get used to C# and start using this language at the very beginning of their work with the program. Almost any action/cube can be converted to C# code and then work with the resulting code similar in functionality to the cube. To do this, after creating a cube and setting its properties, click on “ Convert to C# ” in the context menu and then paste the copied code into the “ C# code ” cube.
Debugging C #
In complex and large pieces of C#, it is often difficult to quickly find an error. Therefore, it is necessary to debug C# code with step-by-step monitoring of changes in variables and data in lists, tables and databases. As with the main ZennoPoster project, each C# action can be debugged in Project Maker by setting one or more breakpoints.
To add a breakpoint, click in the field to the left of the code editor opposite the required line. After that, by clicking "Next", we start the execution of the cube and then using the navigation in the panel above the code editor in step-by-step mode or in the mode until the next breakpoint we check the work of the code, look at the changes in the variables in https://zennolab.atlassian.netnull/pages/createpage.action?spaceKey=EN&title=%D0%9E%D0%BA%D0%BD%D0%BE%20%D0%BF%D0%B5%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%BD%D1%8B%D1%85&linkCreation=true&fromPageId=924582221 and it helps to efficiently correct errors.
Examples of using
Learning to program in C# is beyond the scope of this document, however, it is possible to give you some tips and practical examples, which are often used in the practice of ZennoPoster users when working with C#.
Integer arithmetic
int value1 = Convert.ToInt32(project.Variables["value1"].Value); int value2 = Convert.ToInt32(project.Variables["value2"].Value); int value3 = value1 + value2; //или value1 - value2 or value1 * value2 etc. return value3.ToString(); //the sum of two numbers
Rounding the result of division
float value1 = Convert.ToSingle(project.Variables["value1"].Value); float value2 = Convert.ToSingle(project.Variables["value2"].Value); return Math.Ceiling(value1/value2); // round up //or return Math.Ground(value1/value2); // round down
Create a list with random numbers from 1 to 10
Note that in this example, the C# action does not return anything, unlike the two examples above, where the final value is returned to the variable specified by the cube using the return
operator . Here the result of the work is saved in the list.
In this example, the var keyword refers to the type in an implicit way. This is an alias of any type. The real type will be determined by the C# compiler
var list = project.Lists ["numbers"]; // we refer to the list of project lists to get the essence of one of them. list.Clear (); // clear the list before filling int value; // explaining an integer variable List <string> tempList = new List <string> (); // create a new list of strings, but this list exists only within this action and will be destroyed after the action for (int i = 0; i <10; = "" i ++) = "" {// loop = "" from = "" 10 = "" iterations = "" value = "i; // assign" value = "" counter = "" cycle = "" so that = "" not = "" change = "" it = "" value ++ ; // increase = "" by = "" 1 = "" value = "" variable = "" templist.add (value.tostring ()); // add = "" to = "" temporary = "" list = "" string = "" value = "" numbers = ""} // repeat = "" so = "" 10 = "" times = "" templist.shuffle (); // shuffle = "" list = "" list .addrange (templist); // add = "" to = "" result = "" list = "" mixed = "" list = "" numbers = "" from = "" 1 = "" to = "" 10] ] = ""> </ ac: plain-text-body> </ ac: structured-macro> <h3> Getting a random string from a file with access to accounts and splitting it into a username and password </h3> < ac: structured-macro ac: name = "info" ac: schema-version = "1" ac: macro-id = "a6c84dbf-782d-4da5-854b-93031e07d735"> <ac: rich-text-body> <p > The <code> return statement </code> can be used to return <strong> null </strong>. The <strong> null </strong> keyword is a literal representing a null reference that does not refer to an object. When <strong> null is </strong> returned, the <strong> C # </strong> action will exit on the red line, which is often useful for creating relationships with other cubes. In the example below, with an empty list of accounts, you can display a warning (although the same can be done inside <strong> C # </strong> using the <code> project.SendInfoToLog (& quot; Empty list & quot ;, true ); </code> method) and fill the empty list from TXT with new accesses. </p> </ ac: rich-text-body> </ ac: structured-macro> <ac: structured-macro ac: name = "code" ac: schema-version = "1" ac: macro-id = "dc6aca72-07c3-4c9b-8279-b60452f17731"> <ac: plain-text-body> <! [CDATA [IZennoList list = project. Lists ["accounts"]; // get a list with an attached TXT file in which accesses are stored line by line in the login: password format if (list.Count == 0) return null; // If the list is empty, then exit the cube along the red line Random rnd = new Random (); // create a random number generator string str = list [rnd.Next (0, list.Count)]; // calculate a random purely from 0 to the number of elements in the list (not inclusive) and assign the value of the found index to a string variable string [] arr = str.Split (':'); // form an array of strings by splitting the variable using a delimiter: project.Variables ["login"]. Value = arr [0]; // take the first element of the array, which is the login (indices of arrays, lists always start from 0) and assign this value to the login variable project.Variables ["password"]. Value = arr [1]; // the second element of the array will be the password
Getting a random string from a file with access to accounts and splitting it into a username and password
The return
operator can be used to return null. The null keyword is a literal representing a null reference that does not refer to an object. When null is returned, the C # action will exit on the red line, and this is often useful for creating relationships with other cubes. In the example below, with an empty list of accounts, you can display a warning (although the same can be done inside C# using the project.SendInfoToLog
("Empty list", true);
method) and fill the empty list from TXT with new accesses.
IZennoList list = project.Lists ["accounts"]; // get a list with an attached TXT file in which accesses are stored line by line in the login: password format if (list.Count == 0) return null; // If the list is empty, then exit the cube along the red line Random rnd = new Random (); // create a random number generator string str = list [rnd.Next (0, list.Count)]; // calculate a random purely from 0 to the number of elements in the list (not inclusive) and assign the value of the found index to a string variable string [] arr = str.Split (':'); // form an array of strings by splitting the variable using a delimiter: project.Variables ["login"]. Value = arr [0]; // take the first element of the array, which is the login (indices of arrays, lists always start from 0) and assign this value to the login variable project.Variables ["password"]. Value = arr [1]; // the second element of the array will be the password
Working with HTML elements
Through C#, you can work with instace
object methods in the same way as with standard cubes, but at a higher level. In the example below, we get a collection of HTML elements and add links from their children to the list.
To quickly get the values of the attributes of HTML elements, it is convenient to first use the " Action Designer " Action Designer and XPath Search add a cube for working with this element, and then using the " Convert to C# " functionality, get the code that needs minimal edits.
var list = project.Lists ["urls"]; // list into which we will add links HtmlElementCollection hec = instance.ActiveTab.GetDocumentByAddress ("0"). FindElementsByAttribute ("li", "class", "pageNav-page", "regexp"); // get a collection of HTML elements with the "li" tag in the class name text "pageNav-page" for (int i = 0; i <hec.Count; i ++) { HtmlElement he = hec.GetByNumber (i); // iterate over all elements of the collection in a loop if (he.IsVoid) break; // if the element is not available, then we break the loop using the break command string attribute = he.FirstChild.GetAttribute ("href"); // get the value of the "href" attribute - the URL to the page list.Add (attribute); // add URL to the list }
Working with files: getting the resolution (width x height) of an image
The @
in front of a line means that the compiler will literally use the line after it, not as an escape sequence. If you remove this symbol, then for the path in the example below to be correct, you would have to put a double slash instead of a single slash for the code to work correctly.
Image img = Image.FromFile (project.Directory + @ "/ temp.jpg"); // get an image from a file int width = img.Width; // get the width of the image int height = img.Height; // and height return width.ToString () + "x" + height.ToString (); // form a string with data
Working with OwnCode and Images: Overlaying a semi-transparent "watermark" in the center
In practice, it is often required to take out some C# functions in a separate place and access them from different actions. This is served by OwnCode (own code) https://zennolab.atlassian.netnull/pages/createpage.action?spaceKey=EN&title=Using-%D0%B4%D0%B8%D1%80%D0%B5%D0%BA%D1%82%D0%B8%D0%B2%D1%8B%20%D0%B8%20%D0%BE%D0%B1%D1%89%D0%B8%D0%B9%20%D0%BA%D0%BE%D0%B4&linkCreation=true&fromPageId=924582221 ...
In this class, you can insert a function that will be available from the cubes. This function can take parameters (arguments) and it will return the results of these calculations.
The example below creates a SetImageOpacity
function that takes an image and a value to change its transparency to, and sends the changed image as output. This function requires using System.Drawing.Imaging;
Image original = Image.FromFile (project.Directory + @ "/ image.jpg"); // original image to be watermarked int w = original.Width; // Dimensions of the original image int h = original.Height; int w_wm = (int) w / 10; // the width of the watermark, in this case this width is 10 of the original image Image wm = OwnCode.CommonCode.SetImageOpacity (Image.FromFile (project.Directory + @ "/ wm.png"), .5F); // in one line we get the image from the file and process it (apply the translucency effect) using the function SetImageOpacity, which is in the common code class float scale = (float) wm.Height / wm.Width; // proportions of the watermark int h_wm = (int) (w_wm * scale); // calculate the new height of the watermark depending on the new width and aspect ratio int x = (int) (w / 2 - w_wm / 2); // x position of the watermark (middle of the main image minus the middle of the new width of the watermark int y = (int) (h / 2 - h_wm / 2); // y position of the watermark Graphics gr = Graphics.FromImage (original); // create a graphic object from the original image gr.DrawImage (wm, x, y, w_wm, h_wm); // draw a watermark over the original image with previously calculated coordinates and new dimensions original.Save (project.Directory + @ "/ image_result.jpg", System.Drawing.Imaging.ImageFormat.Jpeg); // save the picture in JPEG format at the specified path original.Dispose (); // we destroy objects that are no longer needed so that they do not take up memory wm.Dispose (); gr.Dispose ();
And the actual SetImageOpacity
class, which needs to be inserted in the OwnCode.CommonCode
class
using System.Drawing.Imaging; public static Image SetImageOpacity (Image image, float opacity) { try { Bitmap bmp = new Bitmap (image.Width, image.Height); // create graphics from a picture using (Graphics gfx = Graphics.FromImage (bmp)) { // create a color matrix object ColorMatrix matrix = new ColorMatrix (); // set transparency matrix.Matrix33 = opacity; // create new attributes ImageAttributes attributes = new ImageAttributes (); // set the transparency color of the picture attributes.SetColorMatrix (matrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap); // draw the picture gfx.DrawImage (image, new Rectangle (0, 0, bmp.Width, bmp.Height), 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, attributes); } return bmp; } catch (Exception ex) { return null; } }
Working with Regex
With the help of regular expressions, which C# fully supports, it is convenient to parse data, find the desired values, process and assign data to variables, and clean up garbage from texts.
In the example below, the task is to clear all HTML tags from the content of some element.
string html = project.Variables ["value1"]. Value; // assign the value to the variable containing the source code of the element return Regex.Replace (html, @ "<. *?> & quot ;, String.Empty); // replace HTML tags with emptiness and return the result
Working with macros
The Macros
object gives you access to a variety of file system or word processing functions. For example, it is possible in C# to organize Spintax
processing similar to the corresponding cube.
return Macros.TextProcessing.Spintax ("{0 | 1 | 2}"); // will randomly output one of the three values