views:

276

answers:

8

I am new to Windows programming and I'm trying to discover the best way to check for the existence of Windows Shell API functions. I want to use some of the new taskbar features in Windows7.

http://msdn.microsoft.com/en-us/library/dd378460%28VS.85%29.aspx#custom_jump_lists

But I still want my program to be usable by previous versions of Windows. Is there an easy way to know if the functions are available to be called in the end users system. I'm programming in C++.

A: 

you should use LoadLibrary and GetProcAddress to dynamically load and invoke the new functionality.

Jewel S
+1  A: 

I believe MSDN is your best bet for this. Every MSDN page for a function's documentation contains a section in the end which states that which version of Windows support this function.

As an example, Check the doumentation of GetModuleHandle. This contains a section named Requirements under which there is a field Minimum Supported Client and Minimum Supported Server.

However, if you want to check for the existence of functions dynamically, then you can do this through LoadLibrary and GetProcAddress.

Aamir
+2  A: 

LoadLibrary and GetProcAddress will be your friends.

Also, check out this tutorial.

heavyd
A: 

Yes you can always check for the existence of function within a library at runtime and take suitable actions. Check the LoadLibrary and GetProcAddress APIs. http://msdn.microsoft.com/en-us/library/ms683212(VS.85).aspx

msvcyc
A: 

If you want to find out at compile time so as to get a build break if the function is not available on the OS you are targetting (eg Win 95), then you can define some macros, documented here:NTDDI_VERSION, _WIN32_WINNT, WINVER.

If you want your app to work fine when the functionality is not available (eg JumpLists on OSes older than Win7), then you should do combination of LoadLibrary/GetProcAddress to figure out whether the function you are looking for is available.

A: 

Use LoadLibarary to get library handle and GerProcAddress to get pointer to a function. For those functions that are not supported by current OS you will get ERROR_CALL_NOT_IMPLEMENTED error from GetLastError.

Kirill V. Lyadvinsky
+5  A: 

It depends on the kinds of the functions.

For plain (non-COM) functions, the only way is to use LoadLibrary and GetProcAddress. If either fails, you know the OS is missing that function. Writing those function pointer type declarations for function pointers duplicating existing function signatures can be tedious, though in VC++2010 you can use decltype for that. For example:

HMODULE user32 = LoadLibraryW(L"user32");
if (user32 != NULL)
{
    auto messageBoxW = reinterpret_cast<decltype(MessageBoxW)*>(GetProcAddress(user32, "MessageBoxW"));
    if (messageBoxW != NULL)
    {
        messageBoxW(HWND_DESKTOP, L"Hello!", NULL, MB_OK);
    }
}

However, many Shell APIs are exposed via COM components and interfaces. Those cases are different. Sometimes you need to deal with entirely new components; e.g. IApplicationDestinations is a new interface in Win7, and the coclass that implements it is also new. In those cases, you can just do CoCreateInstance, and check the return value for REGDB_E_CLASSNOTREG - this means that such coclass isn't registered on the system (and, effectively, isn't supported).

Sometimes, however, new OS versions introduce new interfaces on existing coclasses. An example is ITaskbarList3, new in Win7, but provided on existing coclass that implements ITaskbarList and dates back to Win95. In those cases, you should first instantiate the coclass for the most basic interface, and then use QueryInterface to obtain new interface versions, and detect that they're not supported by checking return value for E_NOINTERFACE.

Pavel Minaev
A: 

I disagree with the currrent solutions. You'll end up with quite a bit of unreadable code.

A nicer alternative is to wrap the functionality in a custom Windows 7-only DLL. For other systems, provide another version of the DLL that implements the same functions. This can often be a no-op. E.g. a function to set the taskbar extensions would be a no-op on older Windows versions.

The dynamic switching between these DLLs is done by using the delay-load feature of MSVC. You can use a custom hook in your EXE to pick the correct DLL version when the first function in your DLL is called, at which time you know whether you're running on Windows 7.

MSalters