How to register a process on Windows task scheduler using c++ - c++

I'm currently looking for a method to register a process on Windows task scheduler using c++(writing some code).
I have searched some of possible methods on the internet but I could not find any using c/c++.
Using CreateProcess to register a process on task scheduler might be the one solution and I found an example
char buf[MAX_PATH] = "cmd /c schtasks.exe /create /sc onlogon /tn \"APP\" /tr \"C:\\SOME_PATH" /rl highest";
CreateProcess(NULL, buf, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi);
However, as there is no explanation I do not wish to use this example.
Can anyone please explain to me what the given example is doing or any other way to register a process on Windows task scheduler?

Related

Kill a process that run in infinite loop

I create a process from c++ code, that run a python script.
STARTUPINFO si = {0};
PROCESS_INFOMATION pi = {0};
LPTSTR cmdArgs = _T("cmd.exe /k python myScript.py");
CreateProcess(NULL, cmdArgs, NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi);
The script run in infinite loop, for example:
while (1):
print("hello")
I want to kill the process but nothing really work.
I t ried TerminateProcess(), taskkill with pid - they report that process terminated but it still running.
How can I kill the process while it runnning?
LPTSTR cmdArgs = _T("cmd.exe /k python myScript.py");
CreateProcess(NULL, cmdArgs, NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi);
this code create cmd.exe process and it create python.exe process. question - for what create intermediate cmd.exe ?! you need direct start python.exe. use "python myScript.py" command line and start python.exe direct (if use unicode W api and empty application name - string must not be readonly (in your code it readonly - so you use A api, otherwice you got exception))
TerminateProcess not work - because you have handle of cmd.exe and you can terminate it. but not python.exe.
taskkill with pid - they report that process terminated but it still
running.
of course - pid belong to cmd.exe and it terminated. but python.exe still runing.
so again - solution very simply - direct exec target process, without cmd.exe

The Command CreateProcess C++

The Command CreateProcess With the command WaitForSingleObject
can to open an image?
If Yes How can I open the image?
I tried to open but i don't know Where to put the path to open
if (CreateProcess(NULL, "C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Accessories\Paint.lnk", NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
{
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
}
If you just want to open an existing image using defualt app then use ShellExectue API. For example:
ShellExecuteW(NULL, L"open", L"Z:\\cat.PNG", NULL, NULL, SW_SHOW);
You could also open image with mspaint using the same API:
ShellExecuteW(NULL, L"open", L"C:\\Windows\\system32\\mspaint.exe", L"Z:\\cat.PNG", NULL, SW_SHOW);
ShellExecuteEx will let you wait for finishing process.
You can do the same using CreateProcess. As #DavidHeffernan pointed out the second parameter of CreateProcess should point to writable memory else it will raise access violation. To make it clear I will just omit the first parameter. Example:
STARTUPINFOW process_startup_info{ 0 };
process_startup_info.cb = sizeof(process_startup_info); // setup size of strcture in bytes
PROCESS_INFORMATION process_info{ 0 };
wchar_t commandline_args[] = L"\"C:\\Windows\\system32\\mspaint.exe\" Z:\\cat.PNG";
if (CreateProcessW(NULL, commandline_args, NULL, NULL, TRUE, 0, NULL, NULL, &process_startup_info, &process_info))
{
//WaitForSingleObject(process_info.hProcess, INFINITE); // uncomment to wait till process finish
CloseHandle(process_info.hProcess);
CloseHandle(process_info.hThread);
}
I strongly recommend to read this CodeProject article (A newbie's elementary guide to spawning processes).
The CreateProcess function can only start .exe and .bat files. Use ShellExecute[Ex] if you want to launch files the same way the shell/Explorer does.
A process must have a PE EXE file as its main file and if you ask CreateProcess to start something else it is just going to fail. ShellExecute will look up the file extension in the registry to find the correct executable (or COM handler) to execute and this often ends up calling CreateProcess on your behalf with the file you specified as a command line parameter.
Using ShellExecuteEx with the SEE_MASK_NOCLOSEPROCESS flag might might give you a process handle you can wait on but you also have to be prepared for hProcess being NULL. This can happen if the registered application for the file type is already running and DDE or COM was used to open the file in this existing application instance...

Launching IE using system() causes hang for first time

I have used system() to launch IE in my C++ code on a button click. The IE gets launched but a cmd window gets opened too and it gets hanged. I close the cmd window and then it works smoothly. Why is there an initial hang when i first launch the IE?
The cause is that the system() opens a console and calls the command from there. The console only closes when the Internet Explorer closes.
Either use CreateProcess or you can work-around it with system() as well by using the START command:
system("start \"Internet Explorer\" \"C:\\Program Files\\Internet Explorer\\iexplore.exe\" www.google.com");
This code will launch IE using CreateProcess.
However, you may want to use ShellExecute (ShellExecute(NULL, "open", "www.google.com", NULL, NULL, SW_SHOWDEFAULT);) which will use the users default browser.
const char *pathToExplorer = "C:\\Program Files\\Internet Explorer\\iexplore.exe";
const char *webPage = "www.google.com";
char szCmdLine[1024];
sprintf(szCmdLine, "\"%s\" \"%s\"", pathToExplorer, webPage);
STARTUPINFO si = {0};
PROCESS_INFORMATION lp;
si.cb = sizeof(STARTUPINFO);
::CreateProcess( NULL,
szCmdLine,
NULL,
NULL,
FALSE,
CREATE_DEFAULT_ERROR_MODE | NORMAL_PRIORITY_CLASS,
NULL,
NULL,
&si,
&lp);

diskpart does not process script correctly when executed from CreateProcess()

diskpart "myScript.txt":
select disk 1
convert dynamic noerr
select disk 2
convert dynamic noerr
create volume stripe disk=1,2 noerr
assign letter=X noerr
.
.
When running from the command prompt: diskpart /s myScript.txt it works as expected.
However, when run using win api's CreateProcess() both the convert commands do work but when it gets to
create volume, it displays:
"The arguments you specified for this command are not valid"
.
.
Now, to make things more interesting:
If the script is executed again from CreateProcess() a 2nd time (given the disks are now converted and it gives a correct error for the convert comamnds),
when it gets to the create volume, it does work.
This makes me think it has something do with the disks and or executable?
Any point in the right direction is appreciated as this is very confusing. Thanks.
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(si));
ZeroMemory(&pi, sizeof(pi));
si.cb = sizeof(si);
strncpy( command, "diskpart.exe /s myScript.txt", (sizeof(command) - 1) );
CreateProcess( "c:\\WINDOWS\\system32\\diskpart.exe",
command,
NULL,
NULL,
TRUE,
0,
NULL,
NULL,
&si,
&pi ) );
end original question________________________________________________________
EDIT:
Updates and more info:
Added about 15 - 20 seconds worth of delay before create volume command, still got the same error message.
Also, split the work into two scripts, with two calls to
CreateProcess(). On the second script, just calling "create volume"
and assign, it hung for a while and then came back with a "this
command cannot be completed at this time"..or something to the
effect.
Another thing to note: On the first script, putting them into
dynamic, it was running about twice as slow compared to running with
command prompt.
Maybe should just run the whole thing twice (with errors on the second run) as that did work
EDIT2
The 2 scripts is now working, or worked when I tried it again. Not sure why it didn't work the first time.
Because your script works the second time through it seems the most likely cause is timing related -- The volumes are not ready by the time the create volume command is executed.
Based on that assumption:
You can add a detail disk command before the create volume command to find out the state of the disk. That will tell you something about the current state of the disk. Select the first disk as well to show its details too if disk 2 doesn't show you anything interesting. The information you get from this is likely to be helpful.
As for actually resolving the problem, introducing a delay by taking the disks online and offline may help. For example:
select disk 1
convert dynamic
select disk 2
convert dynamic
select disk 1
offline disk
select disk 2
offline disk
select disk 1
online disk
select disk 2
online disk
create volume stripe disk=1,2
assign letter=X
Here is an excerpt of what http://msdn.microsoft.com/en-us/library/windows/desktop/ms682425%28v=vs.85%29.aspx says about the first parameter:
The lpApplicationName parameter can be NULL. In that case, the module name must be the first white space–delimited token in the lpCommandLine string.
If the executable module is a 16-bit application, lpApplicationName should be NULL, and the string pointed to by lpCommandLine should specify the executable module as well as its arguments.
given the above, Suggest:
(first, assure command[] buffer is plenty large enough for the following)
(may have to add the path for the 'myStript.txt)
(may be necessary to add some wait time before calling CreateProcess()
to assure the prior commands have completed.
strncpy( command, "c:\\Windows\\System32\\diskpart.exe /s myScript.txt", (sizeof(command) - 1) );
CreateProcess( NULL,
command,
NULL,
NULL,
TRUE,
0,
NULL,
NULL,
&si,
&pi ) );
As it could be a timing problem, you should ensure that you are correctly waiting the end of the diskpart command before proceeding further in parent program.
I always use WaitForSingleObject after CreateProcess when I want to simulate cmd.exe processing :
CreateProcess(NULL, cmdline, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi);
WaitForSingleObject(pi.hProcess, INFINITE);
This sequence is closer the the good old system function ...

Genearting screenshot (BMP) with Windows Service and CreateProcessWithLogonW

I'm trying to create a screenshot application using windows service, that can capture complete screen at regular time intervals. To get started with, I took basic window service example (http://code.msdn.microsoft.com/windowsdesktop/CppWindowsService-cacf4948) and included screenshot utility class in the project and called the capture function in the onStart method of sample windows service. However, I got blank screen shots. Later I realized that windows service runs in different session and hence the screenshots are blank.
S, I decoupled the screenshot utility class and made it as a seperate project and generated a .exe out of it (which is capable of writing logs to a file where ever needed). This time, I used createProcessWithLogonW function to call the executable, so that it will run the exe in specified user domain than the default service session. The following is the code snippet I have been using.
void CSampleService::StartProcess()
{
DWORD dwSize; HANDLE hToken=NULL;
LPVOID lpvEnv; PROCESS_INFORMATION pi = {0};
STARTUPINFO si = {0};
WCHAR szUserProfile[256] = L"";
si.cb = sizeof(STARTUPINFO);
if (!CreateEnvironmentBlock(&lpvEnv, hToken, TRUE))
{
logger::Wlog(logger::fileName,"CreateEnvironmentBlock Error");
}
dwSize = sizeof(szUserProfile)/sizeof(WCHAR);
GetUserProfileDirectory(hToken, szUserProfile, &dwSize);
CreateProcessWithLogonW(L"admin", L"MyDomain",L"mypassword",
LOGON_WITH_PROFILE, NULL, L"C:\\Temp\\application.exe",
CREATE_UNICODE_ENVIRONMENT, lpvEnv, NULL, &si, &pi);
DestroyEnvironmentBlock(lpvEnv);
CloseHandle(hToken);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
I have no errors from the logs i got. when the services get initiated, it gives a warning of interactive service trying to show a message. When I click that, I received a black screenshot again. I know that there are many things involved here, I just gave a high level view of what I'm doing. Also, i'm pretty new to windows programming. Any kind of help is appreciated.
yes, i got that working. we have to acquire the active session-ID (perhaps from opened desktop) and run the process as interactive service in that session context. This should probably solve the capturing screenshots issue. If someone is looking for GUI and service interactions perhaps IPC will be the most convenient way.