November 10, 2014

How to open the registered CD playing application on Windows

Using C++

“I need to run whatever is registered to handle audio CDs”


I make all sorts of pieces of software, some on CD-ROM and occasionally that CD can contain Audio tracks. Occasionally, I need to be able to open the local CD playing application – whatever that is (often Windows Media Player). Turns out, getting this to load and auto play can be rather tricky.

“Can’t you just play the .CDA files?”

Not on a CD-ROM. Whilst an Audio CD under Windows appears as a set of .CDA files (pointers to the actual audio tracks), on a CD-ROM, Windows decides that the data volume takes precedence over the audio tracks. They aren’t shown and you can’t find them in Windows Explorer.

(As a point of interest, OS X does mount CD-ROMs that contains audio tracks as a separate Audio track volume and a Data volume).

Time to break out the Windows C++ compiler

Whilst we don’t want to dive too far into the mess that is Windows programming, we do need to do a tiny bit and look at a useful function called ShellExecuteEx (used for asking the Shell to Execute External programs), and the information structure ShellExecuteInfo.

Windows C++ Shell Structures

Performs an operation on a specified file.

BOOL ShellExecuteEx(

Structure for ShellExecuteEx function

typedef struct _SHELLEXECUTEINFO {
DWORD cbSize;
ULONG fMask;
HWND hwnd;
LPCTSTR lpParameters;
LPCTSTR lpDirectory;
int nShow;
LPCTSTR lpClass;
HKEY hkeyClass;
DWORD dwHotKey;
union {
HANDLE hMonitor;
HANDLE hProcess;

Whilst the ShellExecuteInfo structure looks hideous, it turns out we only need a few bits to open the CD playing app.

ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);
ShExecInfo.lpFile = NULL;
ShExecInfo.lpClass = _T(“AudioCD”);
ShExecInfo.lpVerb = _T(“play”);
ShExecInfo.lpDirectory = _T(“d:”);
ShExecInfo.nShow = SW_SHOW;
ShExecInfo.hwnd = NULL;
ShExecInfo.lpParameters = NULL;
ShExecInfo.hInstApp = NULL;


The main points to note here are lpFile = NULL, and the lpClass = _T(“AudioCD”) – We don’t need to specify a file, e.g. X:\Track01.cda (because we can’t see it anyway). We also pass in the “play” verb – lpVerb = _T(“play”) asking the system to run the “play” action against the AudioCD entry in the registry. Finally we pass in the lpDirectory = _T(“d:”) – which is the letter of the drive containing the audio CD. In reality the CD Drive may not be on drive D: and this should be a variable.

Complete code
#include "stdafx.h" #include <shlobj.h> int _tmain(int argc, _TCHAR* argv[]) { CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); // split the program name into two chunks by : char* p = strtok((char*)argv[0], ":"); char drive[3]={"d:"}; sprintf(drive, "%s:", p); // Create and clear out the shellexecuteinfo structure SHELLEXECUTEINFO ShExecInfo; memset(&ShExecInfo, 0, sizeof(SHELLEXECUTEINFO)); // Set all the parameters ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO); ShExecInfo.fMask = SEE_MASK_CLASSNAME; ShExecInfo.lpClass = _T("AudioCD"); ShExecInfo.lpVerb = _T("play"); ShExecInfo.hwnd = NULL; ShExecInfo.lpFile = NULL; ShExecInfo.lpParameters = NULL; ShExecInfo.lpDirectory = (LPCWSTR)drive; // drive letter ShExecInfo.nShow = SW_SHOW; // show the app on screen ShExecInfo.hInstApp = NULL; BOOL result = ShellExecuteEx(&ShExecInfo); if (!result) { DWORD error = GetLastError(); return error; } return 0; }
As always with things on the internet you download or read for free – you use it at your own risk.

Submit a Comment

Posted By