Archive

Archive for the ‘win32’ Category

Force Windows to refresh the Desktop (and Start Menu)

February 23rd, 2010

Today I learned a new trick.

When you programatically delete a shortcut from the Desktop folder Windows is “generally” smart enough to update the Desktop and the “recently used programs” section of the Start Menu. But sometimes it does not work and you are left with a “ghost” icon.

As a regular end user, you can hit the F5 key to force a refresh of the Desktop, but for the Start Menu you are left with no alternative than killing/restarting explorer.exe.

I was looking for a better solution for a custom installer application. And after a lot of MSDN scattering and googling around, Eureka, I finally found a magic incantation to programmatically force a refresh of the Desktop.

SHChangeNotify (SHCNE_ASSOCCHANGED, 0, 0, 0);

Programming, Windows, c++, win32

Make LoadLibrary() failures silent on Win2k

December 3rd, 2009

For a custom installer application, I have been working on a crude and efficient way to determine whether the particular version of the C runtime (CRT) we need is installed or not. The technique I use is simply to check if a dummy DLL linked to the CRT libraries would load up properly.

This works gloriously well, except for one simple detail. When the CRT is not installed, on Windows 2000 only, the LoadLibrary error would also cause a MessageBox to be displayed. This stops the flow of the installer and of course, is not very elegant…

Win2k LoadLibrary failure

But there is a simple trick to get rid of the MessageBox, using the very obscure SetErrorMode system call.

::SetErrorMode(SEM_FAILCRITICALERRORS);
HMODULE hDll = ::LoadLibrary("CrtCheck.Dll"); // Won't bark
if (hDll)   ; // CRT is installed
else        ; // CRT is NOT installed

Do you guys know a better (yet simple) way to determine if the CRT is installed?

Update: this is not a Windows 2000 specific issue (thanks Ferruccio). It’s also true for older versions of Windows. As far as I know WinXP, Vista and 7 do NOT display a MessageBox under the same circumstances.

Programming, Windows, c++, win32

The $2,000 one line bug fix

August 4th, 2009

Today is the last of 4 days I spent (mostly) on a bug. The actual bug was fixed by removing one line of code, which should have never been there in the first place!

What was happening? Sometimes and randomly, our application was crashing on exit. The crash was always some dodgy memory access violation. This happened after calling a SendMessage() to HWND_BROADCAST… I did not quite understand what was wrong with it, but calling that SendMessage was stupid enough in the first place. I removed it, replaced it by something much better, and claimed to have fixed the bug. Not surprisingly, the next day the QA had another similar crash in DestroyWindow(), albeit much harder to reproduce.

This time was spent doing some proper investigation. A few days later, after unrolling tons and tons of code, I found miles away from the code that was crashing this little jewel:

FrameWidget::~FrameWidget()
{
  m_hWnd = 0;
  if (IsWindow())
    DestroyWindow();
  // etc...
}

Suddenly the whole picture gets clearer. The first line resets the window handle. The next one checks if the handle represents a window. Of course not! So no need to destroy the window object associated to the handle, right?! Then, by the time you get out of the destructor, your message map/callback functions have been destroyed and point to garbage memory… All it takes to crash it now, is one message routed to this window. And thanks to Murphy’s law, it did happen!

What SendMessage() to HWND_BROADCAST and DestroyWindow() have in common, is that they actually did send a message to this phantom window. In case you did not know, DestroyWindow() does purge the message loop…

Why the handle was set to null in the first place is beyond me, but it sure was a bitch to find!

Reference:

Programming, Windows, win32