0

In my WinAPI C++ application I am trying to open an audio file with the default system player using ShellExecuteEx:

int OpenFileWithDefaultProgram(const std::wstring& path, int showMode, HANDLE* hProc) {
    SHELLEXECUTEINFO shInfo;
    ::ZeroMemory(&shInfo, sizeof(SHELLEXECUTEINFO));
    shInfo.cbSize = sizeof(SHELLEXECUTEINFO);
    shInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
    shInfo.hwnd = NULL;
    shInfo.lpVerb = L"open";
    shInfo.lpFile = path.c_str();
    shInfo.nShow = showMode;
    ::ShellExecuteEx(&shInfo);
    *hProc = shInfo.hProcess;
    return (int)shInfo.hInstApp;
}

The OpenFileWithDefaultProgram function is called this way:

HANDLE hProc;
int error = OpenFileWithDefaultProgram(path, SW_SHOWMINNOACTIVE, &hProc);
if (error <= 32) {
    // Process error
} else {
    // Some actions
}

However SW_SHOWMINNOACTIVE parameter is ignored by some players (e.g. MediaPlayerClassic HomeCinema - MPC HC), which leads to opening a player with changing the foreground window and even showing player window not minimized on some PCs.

The first question is: is it possible to force opening player in "silent" mode (minimized and not becoming active)?

I have also tried using GetForegroundWindow and SetForegroundWindow, which didn't help until I added Sleep right after OpenFileWithDefaultProgram (as I understand, the player needs some time to initialize and during this time the foreground window doesn't change):

HWND hWndForeground = GetForegroundWindow();
HANDLE hProc;
int error = OpenFileWithDefaultProgram(path, SW_SHOWMINNOACTIVE, &hProc);
if (error <= 32) {
    // Process error
} else {
    Sleep(100);
    SetForegroundWindow(hWndForeground);
    // Some actions
}

This code restored the foreground window perfectly, but I do not like the constant I need to use as a parameter of Sleep function.

Consequently, the second question is: is it possible to "wake up" the thread at the exact moment when the player is initialized? Alternatively, how should I determine the time needed for player initialization (considering that the default player can be anything and take really different time to start)?

Note:

  • I tried calling WaitForSingleObject(hProc, INFINITE), it just doesn't finish waiting since the player is not terminating after the playback;
  • I tried calling WaitForInputIdle(hProc, INFINITE), it returns immediately without waiting (probably, since the player does not have a message queue).
sautin1
  • 13
  • 2
  • 1
    Why do you want to launch the user's default audio player at all if you don't want to display it to the user? If you are just trying to play a sound file audibly, you can play it directly using [`PlaySound()`](https://msdn.microsoft.com/en-us/library/windows/desktop/dd743680.aspx), the [Waveform Audio](https://msdn.microsoft.com/en-us/library/dd757715.aspx) interfaces/functions, [MCI](https://msdn.microsoft.com/en-us/library/dd757151.aspx), or the [DirectSound](https://msdn.microsoft.com/en-us/library/windows/desktop/bb318665.aspx) API. – Remy Lebeau Sep 06 '16 at 00:52
  • Not an answer to your question, but maybe a better way to play audio files, instead of silently launching a media player, is to play the audio file within your program using Media Foundation ( https://msdn.microsoft.com/en-us/library/windows/desktop/ms703190(v=vs.85).aspx ) – user1610015 Sep 06 '16 at 00:52
  • Please ask about the real problem you are trying to solve instead of your solution. – IInspectable Sep 06 '16 at 07:26
  • Thank you for your comments. However first of all I'd like to know if there is a solution with the constraints described (default player, silent launching) and only in case it does not exist, change the constraints. I see 2 reasons not to play the audio file within my program: 1) the fact that the player is launched silently doesn't mean that the user must have no possibility to pause it / change volume / put on repeat and so on. At the moment I am not ready to create my own player with such features as a part of this program. 2) That's what was asked by the customer. – sautin1 Sep 06 '16 at 10:10

1 Answers1

0

The first question is: is it possible to force opening player in "silent" mode (minimized and not becoming active)?

No, the best you can do is request it, and requests can be ignored. You already discovered that part.

The second question: is it possible to "wake up" the thread at the exact moment when the player is initialized?

No, there's no moment defined when a process is fully initialized. You already discovered WaitForInputIdle and its restrictions. But imagine a media player that fetches a CD cover image in the background (not that far-fetched, no need to delay audio for that)—when does it finish initialization?

Also, keep in mind that ShellExecute might not even start a new process. If there is an existing one, it may use it to open the file.

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
MSalters
  • 173,980
  • 10
  • 155
  • 350