CreateProcess, first parameter question - c++

I am trying to create a process called s2.exe. However I'm having trouble figuring out what needs to be passed in as the first argument. I tried putting the name and location of where the process would be located but I get "Error 2 starting CC". What exactly should go in the first parameter? (According to MSDN it is the path to the module.)
int main()
{
PROCESS_INFORMATION po;
STARTUPINFO s;
GetStartupInfo (&s);
if(CreateProcess(L"c:/s2", NULL, NULL, NULL,
false, 0, NULL, NULL, &s, &po) == FALSE)
{
printf("Error %d starting CC\n", GetLastError());
return -1;
}
}

A value of 2 returned from GetLastError() indicates ERROR_FILE_NOT_FOUND. You need to pass in c:/s2.exe, assuming that s2.exe is actually in the c:\ drive.
Note that the MSDN documentation for the lpApplicationName parameter in CreateProcess() says:
The string can specify the full path and file name of the module to execute or it can specify a partial name. In the case of a partial name, the function uses the current drive and current directory to complete the specification. The function will not use the search path. This parameter must include the file name extension; no default extension is assumed.
Also note that void main() is not standard C++. However, int main() is standard C++, and allows you to return some kind of exit code. (I edited your code snippet to reflect that.)

MSDN says about the lpApplicationName of the CreateProcess function:
This parameter must include the file name extension; no default extension is assumed.

You need L"c:\s2" rather than L"c:/s2". Microsoft prefers backslashes in paths. Forward slashes are accepted in some contexts but are generally problematic in code.

Related

Download to current directory

I want to download the file to current directory instead of "c://". How would that be done?
My code:
using namespace std;
#pragma comment(lib, "urlmon.lib")
int main()
{
cout << "downloading update";
HRESULT hr = URLDownloadToFile(NULL, _T("http://download.piriform.com/ccsetup233.exe"), _T("c://ccsetup233.exe"), 0, NULL);
FreeConsole();
}
The reference for URLDownloadToFile() says this about the szFileName parameter (emphasis mine):
A pointer to a string value containing the name or full path of the
file to create for the download. If szFileName includes a path, the
target directory must already exist.
If you pass only a file name instead of a full path, it will download to the current directory. This is not explicitly documented but it is the normal way how the Windows API works.
Though I wouldn't take any chances that the current directory at the time of the call to URLDownloadToFile() is the same as it was at the start of the program. Any code may have called SetCurrentDirectory() to change the current directory to something else.
To make the code more robust I would call GetCurrentDirectory() only once at the start of the program and store the path in a variable. Before calling URLDownloadToFile() I would append the filename to that path and pass the full path for the szFileName parameter.
On a side note, you should call CoInitialize() at the start and CoUninitialize() at the end of a program that uses URLDownloadToFile() because it is a COM API. You might get away without that but that would be pure luck and may cease to work in different Windows versions.

Run more of one command in ShellExecute function (C++)

I'm trying to run the following lines:
hRet = ShellExecute(HWND_DESKTOP,
L"open",
(*) L"C:\\...\\wmplayer.exe C:\\...\\.mp4",
NULL,
NULL,
SW_SHOW);
But the file(.mp4) doesn't open, maybe because I give the two pathes in one parameter.
I tried also to run the following:
(*) L"\"C:\\...\\wmplayer.exe\" \"C:\\...\\.mp4\""
And:
(*) L"C:\\...\\wmplayer.exe\" \"C:\\...\\.mp4"
But to no avail, can you please assist??
Thanks...!
Reading the documentation I'd say the call should be
hRet = ShellExecute(HWND_DESKTOP,
L"open",
L"C:\\...\\wmplayer.exe",
L"C:\\...\\.mp4",
NULL,
SW_SHOW);
The documentation says:
lpParameters [in, optional] Type: LPCTSTR If lpFile specifies an
executable file, this parameter is a pointer to a null-terminated
string that specifies the parameters to be passed to the application.
The format of this string is determined by the verb that is to be
invoked. If lpFile specifies a document file, lpParameters should be
NULL.
so you could pass directly the .mp4 file as the lpFile parameter and leave this NULL (but the default player would be used) or you must pass the player name as file and the movie name as parameter.

How to include argument with CreateProcess API in VC++?

I have called the other application from my main application using createprocess API. But the other process also need some arguments as a parameter.
I created the process as:
BOOL ret= CreateProcess( NULL, szCmdline, NULL, NULL, TRUE, 0, NULL, NULL,&siStartInfo, &piProcInfo);
szCmdline is variable which contians the application full path.
Any idea how to pass the argument with this process.
Thanks,
CreateProcess has both lpApplicationName and szCommandLine arguments. You must pass at least one of the arguments. However you should pass both for security reasons.
lpApplicationName is the name of the executable you wish to run.
szCommandLine is the command line you wish to pass to that executable. It should include the executable as the first item. This will be received by the application as an argument to WinMain or retrieved by the GetCommandLine function (though the system may prepend a fully-qualified path if one is not supplied). For C programs using main or wmain, it will be parsed by the CRT into arguments.
If you pass NULL for lpApplicationName, the system will attempt to locate the executable in szCommandLine, and will use that.
If you pass NULL for szCommandLine, the system will use lpApplicationName for both.
So the command line is the command line. If you have arguments to pass to the command, put them on the command line.
If lpApplicationName is NULL, the first white space–delimited token of
the command line specifies the module name. If you are using a long
file name that contains a space, use quoted strings to indicate where
the file name ends and the arguments begin (see the explanation for
the lpApplicationName parameter).
It is preferable to pass both lpApplicationName and szCommandLine, to ensure that the command line is not misinterpreted by the system and the wrong executable is run. (There was a class of security problems caused by this a few years ago).
Also, when passing both lpApplicationName and szCommandLine, remember that szCommandLine still needs to include the application name as the first argument.
So for instance, if your program is C:\Program Files\My Application\Program.exe and the arguments are /the /arguments, you would set lpApplicationName to "C:\Program Files\My Application\Program.exe", and set szCmdline to "C:\Program Files\My Application\Program.exe" /the /arguments.
What were the security concerns?
Well imagine if someone created a file "C:\Program Files\My.exe". If you omit the quotes, the system interpreted C:\Program Files\My Application\Program.exe /the /arguments as: C:\Program Files\My.exe Application\Program.exe /the /arguments. And you will get a surprise. This type of trick can be used to fool administrators into running programs they did not wish to run, which is a security problem. This does not occur if you pass the lpApplicationName argument.
The CreateProcess function creates a new process, which runs independently of the creating process. However, for simplicity, the relationship is referred to as a parent-child relationship.
The first parameter, lpApplicationName, can be NULL, in which case the executable name must be in the white space–delimited string pointed to by lpCommandLine.
this way you can send more than one arguments in CreateProcess API.
sprintf(exePath,"Project.exe %s %s \"%s\" \"%s\" \", appName,serverid,srjPath,caseName);
if( !CreateProcess( NULL, // No module name (use command line).
exePath, // Command line.
NULL, // Process handle not inheritable.
NULL, // Thread handle not inheritable.
FALSE, // Set handle inheritance to FALSE.
NORMAL_PRIORITY_CLASS,// No creation flags.
NULL, // Use parent's environment block.
NULL, // Use parent's starting directory.
&si, // Pointer to STARTUPINFO structure.
&pi ) // Pointer to PROCESS_INFORMATION structure.
)
when revived this command line arguments you should parsing this argument and separated by
A double quotation mark preceded by a backslash, \", is interpreted as a literal double quotation mark (").
for parsing command line argument visit this site : http://msdn.microsoft.com/en-us/library/a1y7w461.aspx
and creatprocess API visit this :http://msdn.microsoft.com/en-us/library/windows/desktop/ms682425%28v=vs.85%29.aspx
You can form a string consisting of program name + arguments like this
wstring cmd;
cmd.assign(L"\"C:\\Program Files\\MyProgram.exe\" arg1 arg2 arg3 arg4");
if(!CreateProcess(NULL,(LPWSTR)cmd.c_str(),NULL,NULL,1,0,NULL,NULL,&si,&pi))
{
return -1;
}
Use ShellExecute(Ex). The Control is much simpler, and since we have UAC the Control how to Launch a process is easier to.
With ShellExecuteEx aou also get the process handle if you Need it.
Just my 2 Cents.

WIN32_FIND_DATA Problems - cFileName

i have a problem with my code ;)
hFind = FindFirstFileEx( szPath, FindExInfoMaxInfoLevel, &FindData, FindExSearchNameMatch, NULL , 0);
strncpy_s( pszFileName, 280, FindData.cFileName, strlen(FindData.cFileName));
everything seems fine but when i copy the executable to another computer (windows 2003) i get
But for pszFileName i get really strange output
Specifying FindExInfoMaxInfoLevel is incorrect. The MSDN Library says:
FindExInfoMaxInfoLevel
This value is used for validation. Supported values are less than this value.
In addition, from your usage of FindFirstFileEx, I cannot see why you do not use the simpler FindFirstFile function.
There's not enough code to diagnose the problem, especially without any evidence of error checking. However, there is something really smelly in what you posted. Your call to strncpy_s() says that pszFileName is a pointer to an array with 280 elements. Where did that number come from? Is it just a guess? It can never be more than 260 on Windows, why is it more? I suspect that when you make this a real number, like an argument passed to your function, instead of a guess that you'll fix the problem as well.
You shuold not use the output fields in FindData without first checking that hFind is valid. From the MSDN docs:
If the function fails or fails to
locate files from the search string in
the lpFileName parameter, the return
value is INVALID_HANDLE_VALUE and the
contents of lpFindFileData are
indeterminate.
Thus you should have (after fixing other problems in your API call described in the answers here):
hFind = FindFirstFileEx( szPath, /* replace FindExInfoMaxInfoLevel here */,
&FindData, FindExSearchNameMatch, NULL , 0);
if (hFind != INVALID_HANDLE_VALUE)
{
strncpy_s( pszFileName, 280, FindData.cFileName, strlen(FindData.cFileName));
}

How can I start explorer.exe via C++?

I'm trying to programmatically start explorer.exe but I'm not having any luck.
This is my code:
cout << pName << "died, lets restart it." << endl;
STARTUPINFO startupInfo = {0};
startupInfo.cb = sizeof(startupInfo);
PROCESS_INFORMATION processInformation;
if(CreateProcess(pName, NULL, NULL, NULL, false, NORMAL_PRIORITY_CLASS, NULL, NULL, &startupInfo, &processInformation) == 0){
cout << "Error starting " << pName << ": " << GetLastError() << endl;
}
and pName is explorer.exe
Can someone tell me what I'm doing wrong? I get the error code '2' which is ERROR_FILE_NOT_FOUND
The first parameter is the application name; the second is the command line. Try specifying "explorer.exe" as the second parameter.
See this MSDN article:
lpApplicationName [in, optional]
The name of the module to be executed.
This module can be a Windows-based
application. It can be some other type
of module (for example, MS-DOS or
OS/2) if the appropriate subsystem is
available on the local computer.
The string can specify the full path
and file name of the module to execute
or it can specify a partial name. In
the case of a partial name, the
function uses the current drive and
current directory to complete the
specification. The function will not
use the search path. This parameter
must include the file name extension;
no default extension is assumed.
You probably should give "ShellExecuteEx" a try. This function lets you specify a file or folder and a verb that describes what to do with it. If you use "explore" as the verb, it will open Windows Explorer with the given folder.
It's surprisingly hard to find relevant information on how to reliably restart windows explorer. On 64-bit Windows 7/8, the ShellExecute method does not work properly and leads to things such as file copying and icon overlays being completely broken.
The most reliable way seems to use stdlib.h system call:
system("start explorer");
If you are trying to shutdown and restart explorer, you might want to programmatically disable AutoRestartShell registry key, which prevents you from controlling when explorer is restarted.