Artem's blog

Mainly .NET (C#, ASP.NET) and my projects

Archives for News

General thoughts about time management

[Originally published at]

Being able to plan your studies and time in general is important to be productive. But why do people really do it? Why do we want to stay productive? One possible answer to this is the realization of the tasks that have to be done and the time that is at our disposal. Once the number of tasks increases, we soon realize that time is a scarce resource and has to be used wisely. In this post, we are going to look at a purely tactical approach, how it can be affected by time pressure, and finally how the university has contributed to a combination of both tactical and strategical thinking and how this is related to knowledge from computer science.

Throughout the high school and the first year at the university, I’ve been really into time management. Back then, I think I viewed the planning from a tactical perspective, i.e. during the day I had a set of tasks (such as homework) that were split up into 45 minute sessions, accompanied by 15 minutes break, later by 30 minutes break, and later I switched the subject, even if I had things left. This was suggested by my ToK teacher Ric Sims. I must admit that I did not follow it all the time, but at least I had the time structured into intervals with breaks. At that time, my approach to homework was pragmatic (as far as I can recall), i.e. I prioritized them and executed them as some sort of TODO list.

Later, once the finals were approaching, I started to do other tasks such as doing past papers, rewriting the syllabus (this was not a good idea I think, but allowed me to memorize key concepts), and so on. Suddenly, as they got closer, I had detailed plans of what has to be done during a certain month, a certain week, and so forth; strategical thinking was emerging. For the finals, I came up with a detailed schedule to utilize as much time as possible (the Excel file: Finals approaching). To sum up, as time gets scarce, you tend to plan more to ensure that you use it effectively.

Now, at the university, planning gets even more important. I tend to plan several months and even years ahead (by specifying goals, a strategy). For instance, last year, my plan was to focus onMulti Variable Caclulus, a subject that I was not supposed to study in year 1. Now, my plan (this year) is to focus on my project – Serial Key Manager – and apply to Student Inc. Once the direction (strategy) is specified, it is easy to move forward by breaking the goals into smaller ones, and ultimately have a concise list of tasks; solving these is a question of tactical nature. As an example, this week, I tried to write down all the tasks in an Excel sheet, prioritize them, and complete them one by one (see fig 1).

Excel as a way to prioritize tasks

This gave me a clearer picture and allowed me to organize my time more effectively. This weekly plan however, can be generalized to a monthly plan, a yearly plan and so forth as well as broken down in to smaller components that take time into consideration.


Some computer scientist will point out that this kind of reasoning is related to modulation and abstraction. That is, the yearly plan can be thought of like Python, the monthly plan as Java, the weekly plan as C++ and the daily one as Assembler. It’s interesting that we can combine our knowledge from different disciplines to achieve great results!

Surely, planning is crucial to a successful use of our time. But, it’s also important to understand that different planning approaches have to be applied depending on the type of planning (such as strategical or tactical thinking). All of this helps us to cope with tasks considering that time is a scarce resource. However, we should always remember that for a good execution of tasks, we need to be balanced (don’t overestimate) and reflective (try to find a strategy that works best for you)!

Plan for future article: Next time, my intention is to look at ways to manage the time when you are executing a task. What other alternatives are there(such as Pomodoro technique)? How do we reduce procrastination? But for now, please let me know your thoughts about the current post! 🙂

Release notes for SKGL Extension (2.0.5)

Development of our new Web API is going quite fast. Therefore, it is important to keep SKGL Extension up-to-date so that you can take an advantage of all new features! Today, I want to mention some of the changes that were added to SKGL Extension since 2.0.4.


  • Get Activated Machines is a new method in the Web API (see here) that allows you to get all the activated devices (machine code, IP and Time) for any given key. Note, you need to explicitly enable it as well as use your privateKey for each request. This method has the same authentication level as key generation. An example is shown below:
     public void GetActivatedMachinesTest()
         var productVal = SKGL.SKM.LoadProductVariablesFromString("{\"uid\":\"2\",\"pid\":\"3\",\"hsum\":\"751963\"}");
         Assert.IsNull(SKGL.SKM.GetActivatedMachines(productVal, "dawdwadwa", "MJAWL-ITPVZ-LKGAN-DLJDN"));
         var devices = SKGL.SKM.GetActivatedMachines(productVal, "8dOtQ44PdMLPLNzelOtPqVGdrQEVs36Z7aDQEKzJvt8pGYvtPx", "MJAWL-ITPVZ-LKGAN-DLJDN");

    As you can see, in contrast to the classical operations such as validation and activation, pid, uid and hsum are passed in as a JSON array. I hope that all methods will work that way as soon as possible, because it is very easy to simply copy and paste from here and click on “Get C# friendly version”.

  • Load and Save Key Information to File will from now on take care of all error handling. This means that you need not to surround these method calls with a try-catch-finally. It’s great because you don’t need to worry if the stream is open during an exception.

Release notes for SKGL Extension (2.0.4)

I am happy to tell all users of SKGL Extension that there is a new version available (since the update in late January). In this post, I would like to mention some changes made to the API, a short usage tip, and then let you know how it is going to change in future.


  • Ability to sign pid, uid, activation dateBased on user feedback, the Web API now allows pid, uid and hsum to be added into the signature. This is particularly important for users that protect more than one product. Before, it was possible to use the same KeyInformation file (serialized by SaveKeyInformationToFile) to unlock other products (that used the same Public Key, i.e. by the same software vendor). For some, it worked out by specifying this information in the Notes field. This change makes it more simple. The activation date is intended for offline key validation; it’s a way to keep track the date of the last activation in order to force the user to activate the software periodically.
  • Deactivation: There is a new method that allows you to deactivate a license key. (method info, web api)
  • Optional Field: Finally you can access the optional field using .NET.  It’s a new type of method that takes in a ProductVariables object instead of separate strings for pid, uid, hsum, etc. Read more below Future ideas  (more info).
  • Machine code fix: The getEightDigitsLongHash was modified to fix a bug that generated nine digits instead of eight. Read more here.
  • Proxy: Get Parameters method allows you to specify the proxy settings.
  • Load Product Variables: A new method, LoadProductVariablesFromString allows you to load a serialized version of the ProductVariables object. Read more below Future ideas.

Usage tip

Some users have encountered problems when validating/activating keys because of a wrong code snippet (NullReferenceException). Basically, you should not check the .IsValid field as way to deduce whether the key is valid or invalid. Instead, check if the KeyInformation object is null.

SKGL.KeyInformation keyInfo = new SKGL.KeyInformation();
string machineID = SKGL.SKM.getMachineCode(SKGL.SKM.getSHA1);
keyInfo = SKGL.SKM.KeyActivation("pid", "uid", "hsum", "serialkey", "machine code");
if (keyInfo != null)
    //valid key
    //invalid key

Future ideas

As new functionality is added to the Web API,  more parameters have to be added to each method. In the long run, this is bad because it can be quite repetitive/confusing to add all the parameters all over again. My plan on how this can be resolved is by adding specialized classes, such as ProductVariables to facilitate reuse of existing variables in other methods. The goal is to make it as easy as possible to use SKGL Extension.

What’s new in SKGL Extension for .NET (v. 2)

The extension API for SKGL used to communicate with the Web API of Serial Key Manager has now been upgraded to support Web API 2.0. Below, I’ve listed some changes:

  • The project was moved to GitHub: You can find it here.
  • Some methods were removed/renamed: From now on, there is only one method for a specific action (eg. Activate). There is, for instance, only one method to perform activation, and that method will return a KeyInformation object rather than just stating whether the key is valid or invalid.
  • Support for error handling: When something is missing, you will receive an error. All errors are well documented here. In debug mode, these errors will be displayed in the output.
  • New hash methods and improved algorithm for data collection: The API uses an improved version of information collection (see all contributors) that is later hashed by a hashing algorithm. There are two algorithms at the movement: one that will calculate an eight digit long hash and a second one that will use SHA1. It’s always possible to pick any other hashing algorithm.

I can imagine that some of the changes may or may not trigger different kinds of emotions, partly because some code has to be modified. However, this upgrade is necessary as it will allow much more functionality to be added in the future. It’s also easier to use and thus make it work on other platforms.

Therefore, I will be available to answer some questions on how to migrate to the new library. I can’t guarantee a fast response time, but I will do my best. To save my time, please look through this page first, before contacting me. BUT first, please consider submitting your question on If you rather prefer CodePlex, please use


A new logo

It is important to have a logo to connect different things together (websites, blogs, programs).  After some hours of work I managed to create one:


Although I had some other drafts, I think this is the one I am going to use!

The prize for the Best C# Article of April 2014 (2nd level)

This morning I received a letter from Code Project Solutions with the second place prize for my article. In the letter, I found two stickers, which made me very happy! The pictures are found below:


The letter


The stickers










Before I wrote the article on CodeProject, it was originally written in LaTeX, because I wanted to submit it to several conferences. However, after a minute of thought, I quickly realized that if you want to share your ideas more efficiently, you should take the advantage of modern technologies (HTML, etc.) and modern media. I am a fan of LaTeX, but in this case, HTML was my choice because of the simple navigation (and some other things) that it allowed.

It came as a surprise that it received positive feedback (with suggestions for improvement) and the page view was high. My first article on CodeProject about Different Aspects of Website Protection received some views and votes too, but in comparison to Licensing Systems in .NET it was nothing.

It is difficult to say why it received more attention than my previous article, but in any way – positive feedback is very encouraging, and specially when other people take an advantage of it! I will definitely continue my hobby of writing articles and hopefully in some months from now a larger work.

I am very thankful to all people for their support! 🙂

A possible change for machine code

In the recent issue, it was reported that machine codes are repeated approximately once per 50 different machines in SKGL The reasons under investigation are:

  • small hash value allows even more collisions.
  • the machine information that is being hashed does not collect all hardware that can be changed.

The first reason is currently in focus, and I have tried to develop a piece of code that now increases the length of the machine code. It would be great if those of you who are able to test this on several machines could do so, and comment(either directly below this thread or here) how frequent the collisions are on different machines! Thank you in advance! 🙂

EDIT 2: This can be done by anyone using Windows:

  1. Download the software below (no installation required): (or download the exe file directly here) NOTE: In Google Chrome, it might tell that the file is dangerous because it is not commonly downloaded. Please right click and press keep.

Machinecode experiment

EDIT: You can also write the machine code you get on your own computer and post it below this thread. (hardware info using dxdiag would be awesome, but the machine code is more important at this point)

public class AnalysisOfMachineCode
    public void test()

    public static int getMachineCode()
        ManagementObjectSearcher searcher = new ManagementObjectSearcher("select * from Win32_Processor");
        string collectedInfo = "";
        // here we will put the informa
        foreach (ManagementObject share in searcher.Get())
            // first of all, the processorid
            collectedInfo += share.GetPropertyValue("ProcessorId");

        searcher.Query = new ObjectQuery("select * from Win32_BIOS");
        foreach (ManagementObject share in searcher.Get())
            //then, the serial number of BIOS
            collectedInfo += share.GetPropertyValue("SerialNumber");

        searcher.Query = new ObjectQuery("select * from Win32_BaseBoard");
        foreach (ManagementObject share in searcher.Get())
            //finally, the serial number of motherboard
            collectedInfo += share.GetPropertyValue("SerialNumber");

        // patch luca bernardini
        if (string.IsNullOrEmpty(collectedInfo) | collectedInfo == "00" | collectedInfo.Length <= 3)
            collectedInfo += getHddSerialNumber();

        return getEightByteHash(collectedInfo, 1000000);

    public static string getHddSerialNumber()

        // --- Win32 Disk 
        ManagementObjectSearcher searcher = new ManagementObjectSearcher("\\root\\cimv2", "select * from Win32_DiskPartition WHERE BootPartition=True");

        uint diskIndex = 999;
        foreach (ManagementObject partition in searcher.Get())
            diskIndex = Convert.ToUInt32(partition.GetPropertyValue("Index"));
            break; // TODO: might not be correct. Was : Exit For

        // I haven't found the bootable partition. Fail.
        if (diskIndex == 999)
            return string.Empty;

        // --- Win32 Disk Drive
        searcher = new ManagementObjectSearcher("SELECT * FROM Win32_DiskDrive where Index = " + diskIndex.ToString());

        string deviceName = "";
        foreach (ManagementObject wmi_HD in searcher.Get())
            deviceName = wmi_HD.GetPropertyValue("Name").ToString();
            break; // TODO: might not be correct. Was : Exit For

        // I haven't found the disk drive. Fail
        if (string.IsNullOrEmpty(deviceName.Trim()))
            return string.Empty;

        // -- Some problems in query parsing with backslash. Using like operator
        if (deviceName.StartsWith("\\\\.\\"))
            deviceName = deviceName.Replace("\\\\.\\", "%");

        // --- Physical Media
        searcher = new ManagementObjectSearcher("SELECT * FROM Win32_PhysicalMedia WHERE Tag like '" + deviceName + "'");
        string serial = string.Empty;
        foreach (ManagementObject wmi_HD in searcher.Get())
            serial = wmi_HD.GetPropertyValue("SerialNumber").ToString();
            break; // TODO: might not be correct. Was : Exit For

        return serial;


    public static int getEightByteHash(string s, int MUST_BE_LESS_THAN = 1000000000)
        //This function generates a eight byte hash

        //The length of the result might be changed to any length
        //just set the amount of zeroes in MUST_BE_LESS_THAN
        //to any length you want
        uint hash = 0;

        foreach (byte b in System.Text.Encoding.Unicode.GetBytes(s))
            hash += b;
            hash += (hash << 10);
            hash ^= (hash >> 6);

        hash += (hash << 3);
        hash ^= (hash >> 11);
        hash += (hash << 15);

        int result = (int)(hash % MUST_BE_LESS_THAN);
        int check = MUST_BE_LESS_THAN / result;

        if (check > 1)
            result *= check;

        return result;


Two new videos about Serial Key Manager

This week I was able to record two new videos that describe the process of external validation of a license key using Serial Key Manager. Now, my final aim is to record a third, last video about the way the local time can be synced with a server to prevent user from gaining more days than allowed by a license.

Below are the videos:

Finals 2014

From today until the 20th of May, my mental, physical and psychological focus is put on the final exams. This means that I won’t be able to respond to messages, comments, etc at least until the 20th of May. As you can understand, it might take some time after the 20th of May too, since many things are going to be collected (there are several already on the list).

Preparing for the finals

This is the second last day on the Eastern break.


Page 1 of 6:1 2 3 4 »Last »