How to sign C++ assemblies with a strong name

21 10 2012

Strong Name (SN) is a technology introduced with the .NET platform, which gives a globally unique identity to the applications or components. If our application is signed with a strong name, then it is mandatory to sign all assemblies it refer.

In case if you are working in COM dll or Managed C++ library, you may need to provide signed version of your DLL to client applications.

First step is to create a key file using sn.exe tool which we can find out with .NET Framework SDK,

sn.exe -k [Directory]\MyKey.snk

Sign COM Interop DLLs

If we are working on COM dlls, generally we generate ineterop DLLs too for .NET client applications. This can be generated by tlbimp.exe.
Tlbimp.exe provides the functionality to set a /keyfile: as an argument to generate the interop dll which is signed with a Strong Name.

The following commands shall be added to the project’s post build events.

tlbexp MyComDll.dll /out:MyComDll.tlb
tlbimp MyComDll.tlb /keyfile:MyKey.snk /namespace:Company.MyComDll /output:Interop.MyComDll.dll

Sign Managed C++ library

A managed DLL can be signed by specifying the key file in visual studio project settings at Project-> Properties-> Configuration Properties-> Linker-> Advanced-> Key File

We can check whether our DLLs are signed or not using same SN.EXE tool. The following command will give key information.

sn.exe -T MySignedDll.dll




How to get and set Date and Time

11 02 2012

Sometimes we may really need to set/get date and time values to/from system. So whenever we think about to change these parameters generally we should think about time zones and daylight savings time, because most of the time our applications need to run globally in a safe manner.

The time related functions can return time in different formats. The below two are the commonly used formats.

1) System timeUTC based time (Coordinated Universal Time)
2) Local Time – Time based on local time zone

Win32 API provides different functions to set/get System Time and Local Time separately.
GetSystemTime/SetSystemTime – To set or retrieve current system date and time. This is expressed in UTC.
GetLocalTime/SetLocalTime – To set or retrieve current local date and time.

These all functions are using a pointer to a SYSTEMTIME structure as a parameter to receive or contains the current or new system date and time respectively.

void GetTime()
{
	SYSTEMTIME st, lt;

	GetSystemTime(&st);
	GetLocalTime(<);

	CString strSystemTime, strLocalTime;

	strSystemTime.Format( _T("Year = %04d Month = %02d Day = %02d Hour = %02d Min = %02d"),
		st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute);

	strLocalTime.Format( _T("Year = %04d Month = %02d Day = %02d Hour = %02d Min = %02d"),
		lt.wYear, lt.wMonth, lt.wDay, lt.wHour, lt.wMinute);

	AfxMessageBox(_T("SystemTime : " + strSystemTime + "\n") + "LocalTime : " + strLocalTime);
}

The MFC framework simplified the working with times by introducing two wrapper classes, the CTime and COleDatetime classes.





How to read/write a file

11 02 2012

Reading the contents of a file or writing to a file is common in any kind of applications. So how to open and close files as well as read and write to those files.

MFC provides a class CStdioFile to perform read/write operations from/to a file. This is a CFile derived class and the base class function Open would open an existing file or create a new file as per the flag uses in the second parameter of this function.
CStdioFile has two separate functions ReadString and WriteString to perform read and write operations respectively. Each functions read/write a single line of text.

  

//Create a new file

void WriteToFile()
{
	CStdioFile writeToFile;
	CFileException fileException;
	CString strFilePath = _T("C:\\Test.txt");

	if (writeToFile.Open( strFilePath, CFile::modeCreate|CFile::modeWrite), &fileException)
	{
		writeToFile.WriteString(_T("Hello\n"));
		writeToFile.WriteString(_T("Hi\n"));
		writeToFile.WriteString(_T("Bye\n"));
	}
	else
	{
		CString strErrorMsg;
		strErrorMsg.Format(_T("Can't open file %s , error : %u"), strFilePath, fileException.m_cause);
		AfxMessageBox(strErrorMsg);
	}

	writeToFile.Close();
}

//Read the contents of a file

void ReadFile()
{
	CStdioFile readFile;
	CFileException fileException;
	CString strFilePath = _T("C:\\Test.txt");
	CString strLine;

	if (readFile.Open(strFilePath, CFile::modeRead, &fileException))
	{
		while (readFile.ReadString(strLine));
	}
	else
	{
		CString strErrorMsg;
		strErrorMsg.Format(_T("Can't open file %s , error : %u"), strFilePath, fileException.m_cause);
		AfxMessageBox(strErrorMsg);
	}

	readFile.Close();
}

CFile is the base class for MFC file classes.It directly supports memory files and text files streaming through its derived classes.





How to find width and height of the specified string of text

11 02 2012

Whenever we draw formatted text on a window, sometimes it would be really useful if you know the exact dimensions (width and height) required to draw it before actual drawing.

The DrawText function draws formatted text in the specified rectangle. But if we need to find the width and height to draw that text use this function with DT_CALCRECT flag as the last parameter of this function.
Also you can use another function GetTextExtentPoint32 to computes the width and height of the specified string.

Uisng DrawText

void ComputeWidthAndHeight(CDC* pDC)
{
	RECT rt = { 0, 0, 0, 0 };
	CString str = "ComputeWidthAndHeightToWriteText";
	DrawText(pDC->m_hDC, str, str.GetLength(), &rt, DT_CALCRECT);
}

Using GetTextExtentPoint32

void ComputeWidthAndHeight(CDC* pDC)
{
	CString str = "ComputeWidthAndHeightToWriteText";
	SIZE sz;
	GetTextExtentPoint32( pDC->m_hDC, str, str.GetLength(), &sz);
}

Please you don’t forget that using DT_CALCRECT will not draw the text, so a subsequent call to DrawText is required.





How to track position of the Caret

28 01 2012

Sometimes back one of my friends asked me, how could he able to find whether the caret is blinking in an active window? or just for an example if you have a dialog application which contains different controls like button, editbox, listbox etc and you are keep on moving the cursor focus over these control using “Tab” key, once the edit box gets focus, cursor starts to blink. How to detect such events?

The direct method to track caret position like windows events are to use Microsoft Active Accessibility. However the simpler approach to track caret position is to use GUITHREADINFO structure. This structure contains hwndCaret and rcCaret members that gives the handle to the window that owns the caret and client coordinate of the caret.

GetGUIThreadInfo function is used to get GUITHREADINFO structure info.

GetWindowThreadProcessId function retrieves the identifier of the thread that created the specified thread.

  

void OnTimer(UINT_PTR nIDEvent)
{
	// Retrieves the identifier of the thread that created the specified window
	DWORD dwThreadID = GetWindowThreadProcessId(GetForegroundWindow()->m_hWnd, NULL);

	GUITHREADINFO guiThreadInfo;
	guiThreadInfo.cbSize = sizeof(GUITHREADINFO);

	//Retrieves information about the active window or a specified GUI thread.
	if (GetGUIThreadInfo(dwThreadID, &guiThreadInfo))
	{
		if (GUI_CARETBLINKING == guiThreadInfo.flags)
		{
			AfxMessageBox(_T("Caret Blinking"));
		}

		if (guiThreadInfo.hwndCaret)
		{
			//caret position
			POINT pt = { guiThreadInfo.rcCaret.left, guiThreadInfo.rcCaret.top };
			//it should be an edit control
			AfxMessageBox(_T("edit control"));
		}
	}
}

Microsoft Active Accessibility provides a mechanism that allows to generate events to detect object creation, destruction, focus change, location change,… so on.





How to incorporate logging to an application

28 01 2012

Once we deploy an application into the client machines and somehow if they face any crash or defects, generally we will be in trouble! Right? 😦

On such situations its our responsibility to fix it ASAP. So we should have good debugging skills to locate the issue and fix it at the earliest. There are different methods to improve debugging and better error tacking. One among them is logging.  Logging in the context of any application means recording what the application is doing. This post is about to incorporate logging mechanism to your application.

Generally programmers spend a high percentage of the time debugging to locate defect rather than writing code. So if we incorporate a logging mechanism in our applications, it will generate an error (log) file at a client and we can take the logg file and see where the error appeared, maybe even the error, or at least until where the application went ok… 🙂

We can inlude a CLogger class to our application to establish this and it is better to design this as a Singleton class. Please see the attached files to get it clear.

Logger.h

Logger.cpp

  

void Main()
{
	if (!CLogger::Instance()->OpenLogFile())
	{
		AfxMessageBox(_T("Loggin failed!"));
	}

	TestFun1();
	CLogger::Instance()->LogMessage("\r\nTestFun1 successfully executed");

	TestFun2();
	CLogger::Instance()->LogMessage("\r\nTestFun2 successfully executed");

	TestFun3();
	CLogger::Instance()->LogMessage("\r\nTestFun3 successfully executed");

	CLogger::Instance()->CloseLogFile();
}

Don’t include to much logging statememts, means that sould not affect the performance of your application. Keep only valid data in the looging. Otherwise it will be a overhead for your application.





How to get value of an environment variable

28 01 2012

Windows Environment Variables hold some system paths or user defined paths. How can we read the contents of a specified environment variable.

There is an API GetEnvironmentVariable, which retrieves the contents of the specified variable from the environment block of the calling process.

 

 

void ReadEnvironmentVariable()
{
	TCHAR tcPath[MAX_PATH];
	GetEnvironmentVariable( _T("TMP"), tcPath, MAX_PATH );
}

This function can retrieve either a system environment variable or a user environment variable.