Visual Studio 2010 CreateProcess() for batch script - winapi

I am trying to run a batch script within visual studio 2010. I am following the code found here as well as the MSDN document.
I have the running.bat file I created in both the Release and Debug folders when my .exe is created (both methods of compiling fail during runtime). However my program crashes with error code 2 every time:
main.c - a command line application
#include "windows.h"
#include "stdio.h"
int main()
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
if( !CreateProcess(NULL,
L"cmd.exe /c running.bat",
NULL,
NULL,
TRUE,
CREATE_NEW_CONSOLE,
NULL,
NULL,
&si,
&pi )
)
{
printf( "CreateProcess failed (%d)\n", GetLastError() );
return FALSE;
}
return 0;
}

STARTUPINFO is an In parameter for the CreateProcess function, but in your code is passing in junk.
STARTUPINFO si = {0};
si.cb = sizeof(STARTUPINFO);
etc...
From the MSDN Documentation:
Important The caller is responsible for ensuring that the standard handle fields in STARTUPINFO contain valid handle values. These fields are copied unchanged to the child process without validation, even when the dwFlags member specifies STARTF_USESTDHANDLES. Incorrect values can cause the child process to misbehave or crash.
As for the Exit Code 2, Add the full path of the batch file to the command. You can retrieve your application's current directory using args or GetModuleFileName.

Related

Why isn't this code executing a hello world executable

Why isn't this code running my hello world c executable
#include <windows.h>
#include <string>
int main()
{
// path for hello world compiled program
std::string app_path = "C:\\Users\\test\\Desktop\\a.exe";
BOOL inherit_handles = true;
PROCESS_INFORMATION pi;
STARTUPINFO si;
CreateProcessA(app_path.c_str(),
NULL,
NULL,
NULL,
inherit_handles,
CREATE_NEW_CONSOLE|CREATE_PROTECTED_PROCESS|DETACHED_PROCESS,
0,
NULL,
&si,
&pi);
return 0;
}
I am clueless to why not output is given, even when I use > out.txt, although I do see some cpu usage spikes in process hacker
I also tried to use calc.exe instead of a.exe but this also didn't help
STARTUPINFO needs to be initialized:
STARTUPINFO si;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
Don't inherit handles unless you need to.
Don't use CREATE_PROTECTED_PROCESS.
Don't use DETACHED_PROCESS unless you want to hide stdout.
Check the return value of CreateProcess!

Win32 MoveFile returns ERROR_ACCESS_DENIED when renaming folders with subfolders

My C++ application uses MoveFile function to rename a folder, but given certain conditions, it returns ERROR_ACCESS_DENIED. The conditions are the following:
The folder must contain at least one subfolder
Subfolder must have had previously opened before trying to rename.
Windows Explorer file manager Folder Option Expand to open folder is checked
Other observations
Telling user to uncheck Expand to open folder option is not possible.
IF RENAME FOLDER MANUALLY ON WINDOWS EXPLORER I DON'T GET THIS ERROR
The folder may have international characters, so, according to this answer, I shouldn't use C standard library's ::rename function.
Some questions
Why am I getting this error?
Is there a better C++ function or workaround for renaming folders?
Why renaming folder manually doesn't output this error? What function Windows Explorer uses???
Minimal, complete and verifiable example
#include <windows.h>
#include <strsafe.h>
void ErrorExit(LPTSTR lpszFunction)
{
// Retrieve the system error message for the last-error code
LPVOID lpMsgBuf;
LPVOID lpDisplayBuf;
DWORD dw = GetLastError();
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
dw,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&lpMsgBuf,
0, NULL);
// Display the error message and exit the process
lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT,
(lstrlen((LPCTSTR)lpMsgBuf) + lstrlen((LPCTSTR)lpszFunction) + 40) * sizeof(TCHAR));
StringCchPrintf((LPTSTR)lpDisplayBuf,
LocalSize(lpDisplayBuf) / sizeof(TCHAR),
TEXT("%s failed with error %d: %s"),
lpszFunction, dw, lpMsgBuf);
MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK);
LocalFree(lpMsgBuf);
LocalFree(lpDisplayBuf);
ExitProcess(dw);
}
void main()
{
// Generate an error
if (!MoveFile("D:\\folder", "D:\\new_folder"))
ErrorExit(TEXT("GetProcessId"));
}
Adapted from: https://learn.microsoft.com/en-us/windows/win32/debug/retrieving-the-last-error-code
NOTE The folder have the following structure:
D:
└───folder
└───subfolder

Unexepect output of powercfg -requests when the command is executed from a vc++ program

I'm trying to get the output of the powercfg -requests command from a vc++ program. However, it gives a output which is totally different from the output which is given when I manually execute the command in cmd.exe.
I tried to search about it and realized that I get the correct output when the cmd.exe and powercfg.exe present in "\Windows\System32" and get the different/undesired output when the cmd.exe and powercfg.exe present in "\Windows\SysWOW64" are used.
I tried to use CreateProcess and give the absolute path to both, as shown below:
STARTUPINFO si = { sizeof(STARTUPINFO) };
PROCESS_INFORMATION pi;
printf("infoBuf : %S\n",infoBuf);
wchar_t cmdline[] = L"C:\\Windows\\System32\\cmd.exe /K C:\\Windows\\System32\\powercfg.exe -requests
wchar_t path[] = L"C:\\Windows\\System32\\cmd.exe";
if (!CreateProcess(path, cmdline, NULL, NULL, false, CREATE_UNICODE_ENVIRONMENT,
NULL, NULL, &si, &pi))
{
std::cout << GetLastError();
abort();
}
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
But the compiled executable still gives out the output similar to the 64 bit cmd.exe and powercfg.exe.
Am I missing anything? How else do I explicitly set and make sure that my program should use only the 32bit versions of cmd.exe and powercfg.exe.

Launching a program before Debugging in VSCode

I am using VSCode 0.10.6 for C++ programming. I am trying to launch a program prior to debugging. The program, OpenOCD, is what GDB connects to. If I manually open and close it through a terminal, it works fine, but it seems like there should be an easy way to get VSCode to just start it for me.
I have played with tasks.json and it appears you need to use some ugly bat/sh files to accomplish this in combination with preLaunchTasks in launch.json.
Currently the answer is that you must indeed use preLaunchTasks to have a chance of making this work. I would have been happy to use an ugly script, if that indeed would work - but it doesn't. In my case, I needed one or more executables to be ran in the background, allowing VSCode to continue into debugging.
Unfortunately, each executable I tried to launch (via start) was not actually running as a "detached" process, and so VSCode would wait for each executable to finish running before it would finish the preLaunchTasks and start debugging. Not what I wanted.
I found an article by someone having a similar "detached process" problem with subversion, and I used his C++ code to solve this same issue with Visual Studio Code. I found a bug or two in that code, which I fixed. Here is what I'm currently using:
// dstart.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
//http://stackoverflow.com/questions/1536205/running-another-program-in-windows-bat-file-and-not-create-child-process
//http://svn.haxx.se/users/archive-2008-11/0301.shtml
int _tmain()
{
//https://msdn.microsoft.com/en-us/library/windows/desktop/ms683156(v=vs.85).aspx
LPWSTR pCmd = ::GetCommandLine();
// skip the executable
if (*pCmd++ == L'"')
while (*pCmd++ != L'"');
else
while (*pCmd != NULL && *pCmd != L' ') ++pCmd;
while (*pCmd == L' ') pCmd++;
STARTUPINFO si;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
PROCESS_INFORMATION pi;
ZeroMemory(&pi, sizeof(pi));
// Start the child process.
BOOL result = CreateProcess
(
NULL, // No module name (use command line)
pCmd, // Command line
NULL, // Process handle not inheritable
NULL, // Thread handle not inheritable
FALSE, // Set bInheritHandles to FALSE
CREATE_NEW_CONSOLE, // Detach process
NULL, // Use parent's environment block
NULL, // Use parent's starting directory
&si, // Pointer to STARTUPINFO structure
&pi // Pointer to PROCESS_INFORMATION structure (returned)
);
if (result) return 0;
wchar_t msg[2048];
FormatMessage
(
FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
::GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_SYS_DEFAULT),
msg, sizeof(msg),
NULL
);
fputws(msg, stderr);
_flushall();
return -1;
}
Once compiled, you can use it similarly to how the start command works at a DOS prompt. Place that in the script you attach to your preLaunchTasks
in Visual Studio Code.

How to write bootstrap EXE, which launch MSIEXEC.EXE and then wait for its completion

I'm trying to install my ActiveX plugin, packaged in nsi in a cab file, and encountered a problem.
The log is
Code Download Error: (hr = 80070005) Access is denied.
ERR: Run Setup Hook: Failed Error Code:(hr) = 80070005, processing: msiexec.exe /package "%EXTRACT_DIR%\TempR.msi"
I think is the same as this one:
http://social.msdn.microsoft.com/Forums/en-US/ieextensiondevelopment/thread/3d355fb6-8d6a-4177-98c2-a25665510727/
I want to try the solution that is suggested there, but has no idea how to
create a small bootstrap EXE, which
does nothing but to launch MSIEXEC.EXE
and then wait for its completion.
Can someone provide any help?
Thanks!!
Here is a simple wrapper that calls msiexec.exe to quietly install the msi passed in the first command line parameter.
It's written as a Visual C++ command line application:
// InstallMSI.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <Windows.h>
#include <string>
int wmain(int argc, wchar_t* argv[])
{
if(argc < 2) {
printf("Usage: installmsi.exe <full path to msi file>\n\n");
printf("Package will be installed using msiexec.exe with the /qn (quiet install) flags.\n");
return 1;
}
std::wstring args;
args = L"msiexec.exe /i \"";
args += argv[1];
args += L"\" /qn";
PROCESS_INFORMATION pi;
STARTUPINFO si;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
if(!CreateProcess(NULL, (LPWSTR)args.c_str(),
NULL, NULL, TRUE, NULL, NULL, NULL, &si, &pi)) {
printf("CreateProcess failed (%d).\n", GetLastError());
return 2;
}
WaitForSingleObject( pi.hProcess, INFINITE );
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return 0;
}
Hope that helps.
Take a look at dotNetInstaller - prewritten bootstrapper program that does lots more than what you need, but can do just exactly what you're asking.

Resources