How do I start a child process and have it open a file?

I want to write a program that acts as an alarm clock. I intend to have it open Windows Media Player, and have it play a music file. Is it possible to use the CreateProcess() and just specify the music file as a command line argument? Also, if this is the case, does one of the arguments in the CreateProcess() function make this possible?
Just CreateProcess with lpApplicationName as Windows Media Player (I think it's C:\Windows\system32\myplay32.exe) and for lpCommandLine pass your file. Pretty much any windows program uses the first argument as the file that it is supposed to open.
I thought as much, confirmation is always nice though. Thank you.
The answer is as always coming from Microsoft:
http://support.microsoft.com/kb/241422

However, WMP is not always installed on users computers :)
You should leave pszApplication NULL and use pszCommandLine to specify the entire command line. If you use pszApplication then windows expects a full path to the application if it's not in the current directory. If you use pszCommandLine on the other hand then you don't need to specify a path or exe extension and windows will search for the application in common directories.
While you could follow knn9's suggestion to use a NULL for the pszApplication param of CreateProcess, as it will make things easier to code, you should really use a full, quoted path, as recommended by Microsoft in the MSDN entry for CreateProcess (see Security Remarks.)

Of course, this does mean you need to know where Media Player is installed. For a personal project, the budget process will be secure enough, but you should be aware that relying on the path to find an executable is seen as bad practice in the general case.

Andy
Last edited on
I'm having trouble. My only problem is that the CreateProcess() funtion won't initialize Windows Media Player. With the LPCSTR lpApplicationName, I just set that equal to the directory path in quotes, right? I set the CommandLine parameter to NULL for now, just to see if I could get it to even open WMP, but to no avail.
Last edited on
I might be a more helpful OP if I posted code... here goes.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
// Alarm Clock.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "Windows.h" 
#include <iostream>


int _tmain(int argc, _TCHAR* argv[])
{
	SYSTEMTIME	st; 
	
	LPCSTR Application;
	//LPSTR Command; 

	STARTUPINFO si;
	PROCESS_INFORMATION pi;

	Application = "C:\Program Files\Windows Media Player\wmplayer.exe";
	//Command = " /play C:\Users\Seamus\My Music\Nightmare\Welcome To The Family";

	ZeroMemory( &si, sizeof(si) );
	si.cb = sizeof(si);
	ZeroMemory( &pi, sizeof(pi) );


	while(1)
	{
		GetLocalTime(&st);

//		std::cout << st.wHour << ":" << st.wMinute << ":" << st.wSecond << "::" << st.wMilliseconds << std::endl;

		if(st.wHour == 13 && st.wMinute == 57)
		{
			if(st.wSecond == 0)
			{

				//std::cout << "WHOOT!!" << std::endl;

			 CreateProcess(
				 Application,
				 NULL,
				 NULL,
				 NULL,
				 FALSE,
				 NULL,
				 0,
				 NULL,
				 &si,
				 &pi
				 );
			 WaitForSingleObject(pi.hProcess, INFINITE);
			 break;  //If this isn't here, the lines inside the if statement are executed every millisecond for s=0 (999 times).
			}
				
				
		}

	}

	std::cin.clear();
	std::cin.ignore();
	std::cin.get();


The lines that I've commented out were previous tests. I wanted to make sure I had this program checking the time corrrectly before I moved on to opening WMP. I did this last at 1:37 p.m.
Edit: just spotted (belatedly) that you are using the full path.

The first part of the command should be the app, even if CreateProcess's application name parameter is unused.

Command = "\"C:\\Program Files\\Windows Media Player\\wmplayer.exe\" /play \"C:\\Users\Seamus\\My Music\\Nightmare\\Welcome To The Family\"";

(edit: correct \ -> \\ in path)

Note that both paths are quoted. (You could use just wmplayer.exe, rather than the full path, in the command line. I use the full path as that's what Explorer uses when it runs an app. But if you run an app at the command line, it's whatever path you used to launch the app.)

Also, when WaitForSingleObject returns, you should close both the process and thread handle that CreateProcess returns (with CloseHandle)

And GetLastError might help it CreateProcess fails!?

Andy

PS Previous attempt at an answer, in case it's oof use later

andywestken inadvertently wrote:
Just tried on my PC and wmplayer.exe isn't on the path.

So you'll either have provide the full path, or modify the path (using the WinAPI functions GetEnvironmentVariable/SetEnvironmentVariable. or the CRT equivalents getenv/setenv. with "PATH".)

You could read the install location out of the registry
key = HKLM\SOFTWARE\Microsoft\MediaPlayer
value = Installation Directory
(or Installation DirectoryLFN, for expanded path)

Andy

PS This post suggests you should check for presence of Media Player by checking its install key

key = HKLM\Software\Microsoft\Active Setup\Installed Components\{22d6f312-b0f6-11d0-94ab-0080c74c7e95}
value = IsInstalled

If Media Player is installed, this is value is set to 1

Programmatically detect if Windows Media Player is installed
http://stackoverflow.com/questions/4035494/programmatically-detect-if-windows-media-player-is-installed

Last edited on
On my computer, WMP is installed under "C:\Program Files\Windows Media Player\wmplayer.exe" From what I read, "/open /play" followed by the directory of the file I want to open and play with WMP should make it do so. Is there something fatally wrong with the code I've written? I will admit it's not the most elegant or clean or anything, but I just need it to work. I'm not asking for anybody to solve this problem for me; I actually ask that nobody do so. I'm just wondering if I'm missing something that is acting as a total roadblock; keeping this thing from funtioning properly.

I changed the code a bit, creating a bool variable and setting it equal to the CreateProcess() function call. I then std::cout the result. It's always 0, indicating failure.
Have you tried simply

"wmplayer /play file"

as the command line with pszApplication as NULL, just to see if that works? You can try GetLastError() as andywestken suggested.
Last edited on
@knn9

"wmplayer /play file" will only work if the Media Player's folder is on the path, which it isn't on my PC.

Andy
Last edited on
Ahh, I just checked and it's not in my PATH either... yet it still works..?

Forget that, it only works from the Run dialog, not the command line
Last edited on
This works for me

Andy

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#define WIN32_LEAN_AND_MEAN // prevent windows.h from including "kitchen sink"
#include <windows.h> // include using <>
#include <iostream>

int main()
{
    LPCSTR Application = "C:\\Program Files\\Windows Media Player\\wmplayer.exe";

    // Command is passed as a non-const char* so should be passed in a modifiable buffer
    // Media file extension must be provided
    // Paths are quoted
    char Command[1024] = "\"C:\\Program Files\\Windows Media Player\\wmplayer.exe\""
        " \"C:\\Test\\wakeup.wav\"";

    // use -A form of struct as working with char, LPCSTR, etc rather
    // than TCHAR, LPCTSTR, etc
    STARTUPINFOA si = {0}; // zero struct
    si.cb = sizeof(si);

    PROCESS_INFORMATION pi = {0}; // zero struct

    // use -A form of function as working with char, LPCSTR, etc rather
    // than TCHAR, LPCTSTR, etc
    if( CreateProcessA(
                Application,
                Command,
                NULL,
                NULL,
                FALSE,
                NULL,
                0,
                NULL,
                &si,
                &pi) )
    {
        std::cout << "CreateProcess succeeded\n";

        WaitForSingleObject(pi.hProcess, INFINITE);

        DWORD exitCode = 0;
        GetExitCodeProcess(pi.hProcess, &exitCode);
        std::cout << "Exit code: " << exitCode << "\n";

        CloseHandle(pi.hThread);
        CloseHandle(pi.hProcess);
    }
    else
    {
        DWORD errCode = GetLastError();
        std::cerr << "CreateProcess failed\nError code: " << errCode << "\n";
    }

    return 0;
}
Last edited on
As wmplayer was ignoring the /close command I checked the info provided in mordoran's post above. It turns out that MSDN article is about an old(er) version of Media Player; newer versions of the app (wmplayer.exe) do not support the command line switches /play and /close.

My old Windows XP machine has both mplayer2.exe (version 6.4) and wmplayer (version 11.0), whereas my Windows 7 PC just has wmplayer.exe (version 12.0)

This link is to the command line for the new player: wmplayer.exe (the name since version 7.0)

Command Line Parameters
Command Line Parameters for Wmplayer
http://msdn.microsoft.com/en-us/library/windows/desktop/dd562624%28v=vs.85%29.aspx

I have tweaked my code above to remove the unnecessary "/play"

Andy
Last edited on
This page talks about a utility called mplayer2.exe that "ships with all versions of Media Player".

http://autorunwizard.com/autorun/faq-autorun-answer.cfm?AutoRunNumber=239

What is MPLAYER2.EXE? This is a small utility that wraps the full player features (wmplayer.exe) within a small useful application. It it shipped with all version of media player, so you can be certain that it will be on the end users system when launched.

But there's no such exe in the Windows Media Player's folder on my Windows 7 PC? Nor can I find a file called mplayer2.exe (or any other extension) anywhere on my PC. But typing mplayer2 into Explorer's start menu does find it, and it does start up Media Player (the latest version.)

Edit: found the solution.

Windows now sets a registry key to map the old app name to the new one.

[HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\mplayer2.exe]
@ = "%ProgramFiles%\Windows Media Player\wmplayer.exe"
Path = "%ProgramFiles%\Windows Media Player"

As the stub is no more, I guess the support for /play and /close has gone, too.

Andy
Last edited on
The problem was WAY simpler than we thought folks. C++ forces you to use two backslashes when you mean one in a string... totally forgot about that. I added in the extra slashes, and CreateProcess() now succeeds! Thank you all for your valuable time, and for searching restlessly in an effort to help me.
Topic archived. No new replies allowed.