Thursday, 14 March 2013

Hello, world! in NSIS - the simplest NSIS script

NSIS requires two things to be present in a script:

1) call to OutFile function (in order to define installer's name and output directory)
2) at least one Section (NSIS script executes sections and each section can contain functions and instructions; functions contain instructions only)

So, the shortest script that compiles could be:

HelloWorld.nsi:




NSIS compiler creates HelloWorld-installer.exe in the same directory where HelloWorld.nsi resides. When run, installer looks like this:

NSIS-HelloWorld-1

If we click on Show details button, we can see the following:

NSIS-HelloWorld-2

We can use ShowInstDetails in order to make installer displaying details by default:



We can use DetailPrint in order to output our custom messages:



And so Installer displays our custom text and Details window by default:

NSIS-HelloWorld-3


If we want to perform some system checks when installer starts, we can place our code in predefined function .onInit. In the next example, we'll just put displaying message box:



When we run installer, message box is first displayed:

NSIS-HelloWorld-4

When we click on OK, main window shows:

NSIS-HelloWorld-5

I used instruction Name to customize title of Installer's windows.

We can do some more serious stuff in .onInit function, like Windows version check. Download GetWindowsVersion.nsh header, create directory headers in the same directory where HelloWorld.nsi is, place GetWindowsVersion.nsh in that new directory (as we want to keep downloaded scripts separately from our work), include that header in the script and call function it exposes - GetWindowsVersion:



Message box displays Windows version:

NSIS-HelloWorld-6

NOTE: Files with extension nsi are installer script files and files with extension nsh are installer headers.

NOTE: DetailPrint calls from .onInit are ignored.

Thursday, 10 January 2013

How to issue periodical execution of DOS command in a single line

Let's say we want to check the state of the socket connection on the port 4016 every second. We can use netstat command to display required information and ping invalid IP address with timeout of 1 second. These two commands can be grouped in the same line with & operator and that group can be put inside infinite FOR loop:

Command:
C:\Users\Scrillex>for /L %a in (0,0,0) do (netstat -an|find "4016" & ping 1.1.1.1 - n 1 -w 1000 >nul)

Output:
C:\Users\Bojan>(netstat -an | find "4016" & ping 1.1.1.1 -n 1 -w 1000 1>nul)
TCP 0.0.0.0:4016 0.0.0.0:0 LISTENING
TCP [::]:4016 [::]:0 LISTENING

C:\Users\Bojan>(netstat -an | find "4016" & ping 1.1.1.1 -n 1 -w 1000 1>nul)
TCP 0.0.0.0:4016 0.0.0.0:0 LISTENING
TCP [::]:4016 [::]:0 LISTENING

C:\Users\Bojan>(netstat -an | find "4016" & ping 1.1.1.1 -n 1 -w 1000 1>nul)
TCP 0.0.0.0:4016 0.0.0.0:0 LISTENING
TCP [::]:4016 [::]:0 LISTENING
^C

To stop the execution of this single line script use CTLR-C.

Friday, 28 December 2012

Safe release of resources

If class allocates unmanaged resources (database connections, sockets, window handles, bitmaps...) it has to implement IDisposable interface with a single method Dispose() which deallocates such resources. When user of this class does not need its instance any more, it has to make sure Dispose() is called - even in the case of an exception. This can be achieved by using try-catch-finally block or with using statement:

Some classes in .NET which implement IDisposable have method Close() along with method Dispose(). Dispose() usually calls Close():

...so it's perfectly safe omitting explicit call to Close() when using using statement.

Resources:
Proper use of the IDisposable interface (SO)
close or dispose (SO)
Does Stream.Dispose always call Stream.Close (and Stream.Flush) (SO)

Friday, 27 July 2012

Creating graphs and diagrams with Doxygen


Install Doxygen and GraphViz.

Open Doxywizard.

In Wizard tab, click on Diagrams topic. Enable Use dot tool from the GraphViz package and select desired graphs to generate.

In Expert tab, click on Project topic. Enable SHORT_NAMES.

In Expert tab, click on Dot topic. Enable HAVE_DOT and set DOT_PATH to relative path to GraphViz binaries (e.g. ../../../Program Files/Graphviz 2.28/bin). Set other attributes by your needs.

When run, Doxygen will create image files for all specified diagrams and create hyperlinks to them across the generated html files.

How to exclude directory from Doxygen parsing

Let's say we want to generate documentation for some code which is at the following path:

C:\development\project1

This project might be using some module (e.g. 3rd party code) which is contained in project1's subdirectory:

C:\development\project1\module1

How to exclude module1 from Doxygen parser? In Doxywizard, open Expert tab and click on Input topic. Find EXCLUDE_PATTERNS attribute and type:

*/module1/*

NOTE:
INPUT attribute should be set to the absolute path to the code of our project:

C:\development\project1

Tuesday, 12 June 2012

Appending string to STL stringstream

std::stringstream constructor has two optional parameters: string that this stream will be initialized with and the buffer mode. Default mode for stringstream is ios::in|ios::out. Put pointer (the one that points to the location in the buffer where the next output operation will start inserting characters) is always set to location 0 upon stream creation regardless of the buffer content. That explains why Test 2 in the code below yields overwriting of the content on the second output.

If we want to initialize stream during its creation and to make next output operation to append characters, we need to move put pointer to the end of the buffer explicitly - by setting buffer open mode to ios::ate (see Test 3).

main.cpp:


Output:
Test 1:
Contained string: "abc"; Output pointer position: 3
Contained string: "abcdef"; Output pointer position: 6

Test 2:
Contained string: "abc"; Output pointer position: 0
Contained string: "def"; Output pointer position: 3

Test 3:
Contained string: "abc"; Output pointer position: 3
Contained string: "abcdef"; Output pointer position: 6

Friday, 18 May 2012

One Definition Rule and Unnamed namespaces

It is possible to have multiple (different) definitions of a class with all methods declared as inline, in different translation units. Both compiler and linker do not complain. Compiler sees only a single unit and so only a single definition. Linker treats all definitions of inline class methods equally, picks only one for linking and discards the rest. But different definitions of the same class are introducing undefined behaviour as linker can pick e.g. constructor implementation from one module and method implementation from another. So the client code might potentially call method defined in one module on some object created with constructor defined in another module. Different definitions of the same class within the same program break the One Definition Rule (§3.2, C++11 standard draft N3242=11-0012). (See my Stack Overflow question)

It is possible to define classes with the same name in different translation units in a safe way. Classes are visible in all units because member functions of non-local classes have external linkage by default. It doesn't matter whether methods are declared as inline, static or they are declared without any specifiers. So this is the reason why linker is able to see multiple definitions of the same method, allowing it to (arbitrary) pick the one and discard the rest. We need to suppress this, we need to hide definitions inside translation units. If we had a variable or a function, we could achieve this by declaring it as static and therefore imposing internal linkage on them. But we cannot apply static keyword on classes (user defined types). What we can do is to place class definition in each translation unit inside a unnamed namespace. This way we are limiting class access only to the translation unit this class is defined in and disable breaking of the One Definition Rule.


Links and References:

external vs internal linkage and performance (SO)
Unnamed/anonymous namespaces vs. static functions (SO)
Superiority of unnamed namespace over static? (SO)
Why unnamed namespace is a“ superior” alternative to static? (SO)
static keyword useless in namespace scope? (SO)