Archive for April, 2008
Let Visual Studio talk to you – Events in Visual Studio Object Model.
0![]()
Did you ever wish to see a “Bye Bye!” from Visual Studio when you exit? Did you ever wish to see a message, when the build is completed, instead of that boring chime sound? The answer is – Visual Studio Object Model Events.
![]()
Visual Studio Object model Events are the ones, which Visual Studio triggers on specified events. They can be easly accessed by writing simple VBScript macros. See the following step by step instructions.
1) Start Visual Studio.
2) Take Tools -> Macro
3) Click Options -> New File and save a new macro file by specifying a name such as “VSEvents” or something like that.
4) Click Edit button and give macroname as “HelloWorld” or something like that.
5) Now you can see a VBScript editor window for editing macros. Actually we’ve added “HelloWorld” for just starting the editor. If there are no macro inside a file, it cannot be edited.
6) Now in the editor add the following lines to the bottom
Sub Application_BeforeApplicationShutDown ' Say ByeBye to master when he leaves! MsgBox "Bye Bye!" End Sub sub Application_BuildFinish(nNumErrors, nNumWarnings) ' Build Finished. MsgBox "Master, Wakeup! the build is finished." end sub
7) Save everything and exit Visual Studio.
8 ) Now Start VisualStudio and try to exit. The Visual studio says “Bye Bye!”.
9) Try to compile a project, Visual Studio will shows a message when compilation is finished!
There is a couple of other events too. They are,
Application_BeforeApplicationShutDown Application_BeforeBuildStart Application_BeforeDocumentClose Debugger_BreakpointHit Application_DocumentOpen Application_DocumentSave Application_NewDocument Application_WindowActivate Application_WindowDeactivate Application_WorkspaceClose Application_WorkspaceOpen
Have a look at them too. See their description in MSDN.
![]()
Since its intended for beginners, i’ve described step by step. If you are advanced, then just write a .dsm file with these macro as contents and put to <VisualStudioDir>\Common\MSDev98\Macros. Then load that macro file in Visual Studio.
![]()
Targeted Audience – Beginners.
Catching exceptions from the constructor
0![]()
In constructors we initialize member variables by using member initialize list. The initialize list is out of constructors function body and how the exception thrown by members in initialize list can be caught by try-catch? See the code block.
class MyClass
{
public:
MyClass( int var1, int var2 )
: m_var1( var1 ),
m_obj2( var1 ) // If this one throws an exception, i can't catch it.
{
try
{
// Constructor body.
}
catch( … )
{ }
}
int m_var1;
CMyObject m_obj2;
};
Here if m_obj2 throws an exception, it cannot be catch by the try-catch block, because the initialize list is outside the try-catch block.
![]()
For catching exceptions from the initialize list, there is a special type of try-catch pattern. See the code block.
class MyClass
{
public:
MyClass( int var1, int var2 )
try : m_var1( var1 ),
m_obj2( var1 ) // Now I can catch the exception.
{
// Constructor body.
}
catch( ... )
{ }
// Member variables.
int m_var1;
CMyObject m_obj2;
};
![]()
If you compile it in Visual Studio 6.0 it will show a couple of errors. Try next versions such as Visual Studio 2005, etc.
![]()
Targeted Audience – Intermediate.
Locate implementation of a particular Dialog in huge Codebase Easily.
0![]()
Huge Maintenance projects usually contain a number of dialogs. Sometimes we want to modify a particular dialog in that project. During most of the case, we might be encountering that dialog for the first time( Guys digging old code base like me can understand it very well ). At that time, what usually people do to locate the dialog implementation is as follows.
- Iterate through all dialogs in the resource by opening it or by checking the dialog ids.
- Find the matching dialog.
- Take the dialog ID.
- Search the code base for reference to the Dialog ID.
- You found it!
If your code base have 100eds of dialogs, how much time will it take?
![]()
All dialogs have the same base class, CDialog. So the CDialog constructor will be called before the constructor of your dialog class get called. Now follow the steps.
- Start debugging your project by F5.
- Open the file – <VisualStudioDir>\VC98\MFC\SRC\DLGCORE.CPP
- Put breakpoints on all CDialog constructors. Note – there are many overloads for your CDialog constructor. Since its unknown how your dialog class is initialized, its better to put break points on all CDialog constructors.
- Now launch your dialog from your application and the debugger will break on the CDialog constructor.
- Now take the Call Stack by pressing Alt + 7.
- From the call stack you can identify the class you were searching.
![]()
The above steps only works for debug version. If you are in release version, then breakpoint at DLGCORE.CPP will be disabled at the starting itself. For that, see following steps.
1) Our problem is how to put breakpoint at CDialog in release build.
2) For that take any put any other dialog class in your workspace and put a breakpoint in its constructor and start debug by F5.
3) when the breakpoint at your dialog’s constructor is reached, right click and select “Go To Disassembly”. It will be as follows.
62: CDlg1Dlg::CDlg1Dlg(CWnd* pParent /*=NULL*/)
63: : CDialog(CDlg1Dlg::IDD, pParent)
64: {
00401216 push ebp
00401217 mov ebp,esp
00401219 push 0FFh
0040121B push offset $L87331 (00401d29)
00401220 mov eax,fs:[00000000]
00401226 push eax
00401227 mov dword ptr fs:[0],esp
0040122E push ecx
0040122F mov dword ptr [ebp-10h],ecx
00401232 mov eax,dword ptr [pParent]
00401235 push eax
00401236 push 66h
00401238 mov ecx,dword ptr [this]
0040123B call CDialog::CDialog (00401a0a)
00401240 mov dword ptr [ebp-4],0
4) From the disassembly you will get the address of CDialog constructor to be called.
5) now take the breakpoint window by pressing Ctrl+B.
6) Just add a breakpoint by specifying this memory location in “Break At” editbox. don’t forget to add 0x in front of memory location. here it will be 0x00401a0a.
7) Now you’ve successfully added a break point at CDialog constructor in release version too. Enable it only when you need it.
![]()
Targeted Audience – Beginners.
Do you know – what is Cfront?
0![]()
Cfront was the first compiler writter for C++. Actually it converts C++ programs to C. It’s developed by the creator himself – Bjarne Stroustrup.
There were versions from 1.0 to 4.0. But Cfront 4.0 failed to implement exception handling and thus came to an end. But you can still get cfront from the shelves of SoftwarePreservation group – a museum of classic softwares. Here is the link.
Thanks Wiki for the history.
![]()
Targeted Audience – Everyone who wish to hear stories.
Can C++ Style comments replace C-Style comments?
2![]()
While entering to C++ world, the first thing we used to learn is – Avoid C-Style comments, always use C++ style comments and a number of drawbacks of C-Style comments. But don’t think that C++ comments are omni. Still there are places where C++ style comments cannot be used.
![]()
Usually inside macros, we don’t write comments. But if the macro is too complex, adding comments will be better for future. But can we use C++ style comments? See the following code block.
#define CHECK_AND_DELETE_PTR( ptr ) \
// Check whether the pointer is valid \
if( ptr ) \
{ \
// Delete the pointer \
delete ptr; \
}
The code block won’t compile. Because C++ style comments always look for end-of-line as termination and the backslash delimiter that we add will concatenate the next line and that too will become the part of comment. Since macro body should be in a single line, we cannot omit the backslash delimiter.
See the same macro with C-Style comments which is perfect.
#define CHECK_AND_DELETE_PTR( ptr ) \
/* Check whether the pointer is valid */ \
if( ptr ) \
{ \
/* Delete the pointer */ \
delete ptr; \
}
Immortal C. Isn’t it?
![]()
Targeted Audience – Intermediate.
Use Semaphores as Global Counters.
4![]()
For certain instance, we need global counters which can be accessed from any process. For instance how many instance of application is running or if our application wants to expose some values such as its performance figures etc. We can use Semaphores as global counters.
![]()
Actually semaphore is meant for synchronization. But unlike other synchronization objects like mutex or event, semaphore can hold a count in it. And like other Kernel objects, semaphore can have a name which makes it possible to be accessed from any process across the system. We are going to utilize these properties to transform it as a Global Counter.
Create Global Counter.
Function CreateSemaphore() is Used to create the semaphore. While Creating, you can specify an initial count, a maximum count and a name. The name is used for opening the same semaphore from other applications.
Accessing Global Counter.
Function CreateSemaphore() is again used to access the existing semaphore. If the semaphore exists, the function returns a new handle to the semaphore. OpenSemaphore() also can be used.
Incrementing Global Counter.
Function ReleaseSemaphore() can be used. Actually this function is used to increment the semaphore value and there by signal a thread, which is waiting for the semaphore. But, we use this function to increment the value.
Decrementing Global Counter.
Function WaitForSingleObject() can be used. Threads uses this function to wait on semaphores until it get signled. Once signled, WaitForSingleObject decrements the semaphore count. So this is used to decrement the value of Global Counter. But a single call to WaitForSingleObject() will decrease the value by one only. So we’ve to call the WaitForSingleObject() number of times to decrement numbers greater than one.
Reading Global Counter.
Function ReleaseSemaphore() can be used again. It returns the current value. Since ReleaseSemaphore() increment the semaphore value, we’ve to call WaitForSingleObject() once again to normalize the value of semaphore.
For simplicity, i’ve implemented the logic in a class named CGlobalCounter.
class CGlobalCounter
{
public:
// Constructor and Destructor.
CGlobalCounter( const TCHAR* strGlobalCounterName );
~CGlobalCounter();
// Initialize counter.
bool Initialize();
// Increment and Decrement.
void Increment( LONG lIncrementBy );
void Decrement( LONG lDecrementBy );
// Get the Value.
LONG GetValue();
private:
HANDLE m_hGlobalCounter; // Handle for semaphore.
CString m_csGlobalCounterName; // Semaphore name.
};
Download sample from here. Right click and Save to your harddisk and rename to .zip. Since there are some limitation in file uploading, i can’t upload zip files.
![]()
Advantages
1) Very simple to use.
2) less resource usage.
Disadvantage
1) Since the GetValue() – increment and decrement semaphore, the GlobalCounter can hold only upto MaxValue-1.
2) While decrementing, there can be a performance bottleneck.
Decide yourself whether you need it or not.
Quite lengthy one, but its worthy.
![]()
Targeted Audience – Advanced.
List all Device Drivers running in your system.
2![]()
Listing up device driver information is very easy. In Platform SDK , there is a set of functions available named “Process Status Helpers”. By using them, we can get the BaseName and FileName of all running device drivers.
![]()
Basically there are 3 functions, which we are interested in. They are -
- EnumDeviceDrivers() – Used to get the list of ImageBaseAddress of all Device Drivers. Using this image base address, we find out the the BaseName and FileName. This function is also used to get the buffer length required for calling the function.
- GetDeviceDriverBaseName() – If ImageBaseAddress of a Device Driver is passed, it will provide the Driver Base Name.
- GetDeviceDriverFileName() – If ImageBaseAddress of a Device Driver is passed, it will provide the Driver FileName.
See the code block for iterating all device drivers in a system.
#include "psapi.h"
// Gets the required buffer length for ImageBaseAddrArray.
DWORD GetImageBaseAddrArrayLen()
{
// Gets the number of Bytes needed for Buffer.
// Call EnumDeviceDrivers with size as 0.
// The required buffer length will be returned
// via dwRequiredBufferSize.
DWORD dwRequiredBufferSize = 0;
EnumDeviceDrivers( 0, // array of load addresses
0, // size of array as 0.
// number of Required buffer size.
&dwRequiredBufferSize );
return dwRequiredBufferSize;
}
// Get Driver informations such as Driver BaseName and FileName.
void GetDriverInfo( LPVOID DriverImageBaseAddr, CString& csDriverBaseName, CString& csDriverFileName )
{
// Get driver BaseName
TCHAR tchBuffer[ MAX_PATH ] = { 0 };
GetDeviceDriverBaseName( DriverImageBaseAddr, tchBuffer, MAX_PATH );
csDriverBaseName = tchBuffer;
// Get driver filename.
GetDeviceDriverFileName( DriverImageBaseAddr, tchBuffer, MAX_PATH );
csDriverFileName = tchBuffer;
}
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
// Allocate array for getting ImageBase addresses of
// all drivers present in system.
DWORD dwBufferLen = GetImageBaseAddrArrayLen();
LPVOID* pImageBaseAddrArray = (LPVOID*)new BYTE[ dwBufferLen ];
DWORD dwBytesReturned = 0;
// Get the ImageBaseAddresses of all drivers.
EnumDeviceDrivers( pImageBaseAddrArray, // array of load addresses
dwBufferLen, // size of array as 0.
&dwBytesReturned );
// Get the total number of drivers. calculate it by
// total size in bytes/sizeof(void*)
DWORD nDrivers = dwBufferLen / sizeof(LPVOID);
// Iterate through each driver.
for( DWORD Index = 0; Index < nDrivers; ++Index )
{
// Get Device Driver informations.
CString csDriverBaseName;
CString csDriverFileName;
GetDriverInfo( pImageBaseAddrArray[ Index], csDriverBaseName, csDriverFileName );
// Print the Driver Information or do what ever you want!
cout << csDriverBaseName.operator LPCTSTR() <<
_T(" : ") <<
csDriverFileName.operator LPCTSTR()
<< endl;
}
}
Create a console appliaction with MFC support and try the source.
![]()
Don’t forget to add psapi.lib to your linker settings.

Targeted Audience – Intermediate.
Launch control panel apps programmatically.
4![]()
Normally for launching control panel application you have to go to control panel and double click the icons. Its useful if we can launch it programmatically. For instance, if the program wants the user to check the computer name, the system properties can be launched. If the program wants to uninstall some software, for easiness – the add/remove programs dialog can be launched and so and so…
![]()
There is an undocumented api – “Control_RunDLL” in the Shell32.dll which can be used to launch control panel applications. You’ve to pass the filename of control Panel application and it will be launched. See the following code block.
// Load the Shell32 dll.
HINSTANCE hShell32 = LoadLibrary(_T("Shell32.dll"));
// Typedef for function pointer for Control_RunDLL.
typedef void( CALLBACK * CONTROL_RUNDLL_FN_PTR)( HWND hwnd,
HINSTANCE hinst,
LPSTR lpszCmdLine,
int nCmdShow );
// Get the function pointer of - Control_RunDLL.
CONTROL_RUNDLL_FN_PTR pControl_RunDLL =
(CONTROL_RUNDLL_FN_PTR)GetProcAddress( hShell32,
_T("Control_RunDLL"));
// Now call the function and launch the ControlPanel App.
(*pControl_RunDLL)( 0, // hwnd
0, // Hinstance
_T("sysdm.cpl"), // ControlPanelApp filename.
SW_NORMAL ); // Show Normal
![]()
The control panel applications are located inside your windows directory. If you search the windows directory for “*.cpl” you can find a number of files. Each file is a control panel application. Even though the file extension is “.cpl“, its a dll. From the name itself you can interpret which control panel application it refers to. Go on, have a try.
![]()
For launching some control panel apps, you’ve to provide valid hwnd and hinstance. Then only it will be shown. For instance – timedate.cpl.

Targeted Audience – Intermediate.
Automatically link required libraries.
0In our projects we use number of 3ed party API’s especially from platform SDK and other components and one burden is finding the libraries for those API’s. For Microsoft provided API’s since they have strong documentation, finding the library for particular API is not so tedious. But for other vendors, It may be. We need to dig a lot for finding the lib of that particular API. How can we get rid from this?
You can you #pragma comment( lib, “LibraryName” ) to specify the necessary library file in the header file itself. For e.g. See the following header file.
// EventLog.h class EventLog { … }; #ifdef _DEBUG // If it’s a debug version… #pragma comment( lib, "MyEventLogLibd.lib" ) #else // Ooooh!!! Its release version. #pragma comment( lib, "MyEventLogLib.lib" ) #endifIf we include the EventLog.h header file, the library required will be automatically included. I dream for the day on which all SDK headers auto includes their libraries…
Target audiance – Intermediate.