Launching a program before Debugging in VSCode - debugging

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.

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!

c++ ShellExecute not working

I am working on a c++ program that is supposed to launch internet explorer and display a local html file on Windows 7. I am trying to use ShellExecute, but it doesn't work. I googled around, but could not find an answer that worked. Here is the code:
ShellExecute(NULL, "open", "start iexplore %userprofile%\\Desktop\\html_files\\file.hml", NULL, NULL, SW_SHOWDEFAULT);
I copied the command into a system() call just to see if it would work, and it did. Here is the system() call I tried:
system("start iexplore %userprofile%\\Desktop\\html_files\\file.html");
Since the system call worked, its clearly a problem with ShellExecute. Basically, Internet Explorer does not come up. Everything compiles correctly, though. Any ideas?
The paths of the user's shell folders, including the Desktop, can be customized by the user, so %userprofile\desktop is not guaranteed to be the correct path on all systems. The correct way to get the user's actual Desktop path is to use SHGetFolderPath(CSIDL_DESKTOPDIRECTORY) or SHGetKnownFolderPath(FOLDERID_Desktop).
You do not need to know the path to iexplorer.exe, Windows known how to find it. So just specify "iexplorer.exe" by itself as the lpFile parameter and the HTML filename as the lpParameter parameter:
ShellExecute(NULL, "open", "iexplore.exe", "full path to\\file.hml", NULL, SW_SHOWDEFAULT);
With that said, this is very IE-specific. If you want to load the file in the user's default HTML browser/viewer, set the lpVerb parameter to NULL and the HTML file as the lpFile parameter:
ShellExecute(NULL, NULL, "full path to\\file.hml", NULL, NULL, SW_SHOWDEFAULT);
This is the same as if the user had double-clicked on the file in Windows Explorer.
I dont think IE will recognize environment variables in URI's. In fact % have special meaning.
Something like this should work:
#include <windows.h>
int main()
{
ShellExecute(NULL, "open",
"C:\\progra~1\\intern~1\\iexplore.exe",
"file:///C:/Users/UserName/Desktop/html_files/file.html",
"",
SW_MAXIMIZE);
return 0;
}
Another way, obtain the %userprofile% enviroment variable value and concat your URI:
#if (_MSC_VER >= 1400)
#pragma warning(push)
#pragma warning(disable: 4996) // Disabling deprecation... bad...
#endif
#include <windows.h>
#include <stdlib.h>
#include <iostream>
#include <string>
int main()
{
std::string uri = std::string("file:///") + getenv("USERPROFILE") + "/Desktop/html_files/file.txt";
ShellExecute(NULL, "open",
"C:\\progra~1\\intern~1\\iexplore.exe",
uri.c_str(),
"",
SW_MAXIMIZE);
return 0;
}
Im disabling warnings here, but you should use _dupenv_s instead of getenv.
Good luck.

Visual Studio 2010 CreateProcess() for batch script

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.

Best way to have crash dumps generated when processes crash?

In Windows environments (XP and Win 7):
What is the best way to automatically have a crash dump generated when processes crash on the system?
Can an installer (MSI) package do this?
One of the best way to have an automatic dump for any/specific process on Windows is to configure a set of entries in the registry. I tried the below on Windows 7 64 bit.
Open notepad.exe, paste the below entry and save it as "EnableDump.reg". You can give any name you wish.
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps]
"DumpFolder"=hex(2):44,00,3a,00,5c,00,64,00,75,00,6d,00,70,00,00,00
"DumpCount"=dword:00000010
"DumpType"=dword:00000002
"CustomDumpFlags"=dword:00000000
Double click the "EnableDump.reg" and select 'Yes'. I have given the dump folder as 'd:\dump'. You can change it to whatever folder you wish.
Try to execute a crashing application, Windows will display the error dialog. Choose 'Close the Program' option. After that you will see the dump in the configured folder. The name of the dump file will be .exe..dmp.
For more details, you can refer the below link.
http://msdn.microsoft.com/en-us/library/bb787181(VS.85).aspx
Below explanation is based on another answer, but the logic is mine (without attribution need, as said on my profile);
Having your own dump generation framework which automatically creates a process dump when any Unhandled exception is encountered, would avoid clients having to install WinDbg.
At the application start up use SetUnhandledExceptionFilter(...) Win32 API to register a callback (i.e. application level exception-handler).
Now the registered callback function is called whenever there is any exception which is not handled. You may then create the process dump using MiniDumpWriteDump(...) API from DbgHelp.dll.
C++ Sample (unicode-enabled)
header-file
#ifndef CRASH_REPORTER_H
#define CRASH_REPORTER_H
//Exclude rarely used content from the Windows headers.
#ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
# include <windows.h>
# undef WIN32_LEAN_AND_MEAN
#else
# include <windows.h>
#endif
#include <tchar.h>
#include <DbgHelp.h>
class CrashReporter {
public:
inline CrashReporter() { Register(); }
inline ~CrashReporter() { Unregister(); }
inline static void Register() {
if(m_lastExceptionFilter != NULL) {
fprintf(stdout, "CrashReporter: is already registered\n");
fflush(stdout);
}
SetErrorMode(SEM_FAILCRITICALERRORS);
//ensures UnHandledExceptionFilter is called before App dies.
m_lastExceptionFilter = SetUnhandledExceptionFilter(UnHandledExceptionFilter);
}
inline static void Unregister() {
SetUnhandledExceptionFilter(m_lastExceptionFilter);
}
private:
static LPTOP_LEVEL_EXCEPTION_FILTER m_lastExceptionFilter;
static LONG WINAPI UnHandledExceptionFilter(_EXCEPTION_POINTERS *);
};
#endif // CRASH_REPORTER_H
source-file
#include "crash-report.h"
#include <stdio.h>
LPTOP_LEVEL_EXCEPTION_FILTER CrashReporter::m_lastExceptionFilter = NULL;
typedef BOOL (WINAPI *MiniDumpWriteDumpFunc)(HANDLE hProcess, DWORD ProcessId
, HANDLE hFile
, MINIDUMP_TYPE DumpType
, const MINIDUMP_EXCEPTION_INFORMATION *ExceptionInfo
, const MINIDUMP_USER_STREAM_INFORMATION *UserStreamInfo
, const MINIDUMP_CALLBACK_INFORMATION *Callback
);
LONG WINAPI CrashReporter::UnHandledExceptionFilter(struct _EXCEPTION_POINTERS *exceptionPtr)
{
//we load DbgHelp.dll dynamically, to support Windows 2000
HMODULE hModule = ::LoadLibraryA("DbgHelp.dll");
if (hModule) {
MiniDumpWriteDumpFunc dumpFunc = reinterpret_cast<MiniDumpWriteDumpFunc>(
::GetProcAddress(hModule, "MiniDumpWriteDump")
);
if (dumpFunc) {
//fetch system time for dump-file name
SYSTEMTIME SystemTime;
::GetLocalTime(&SystemTime);
//choose proper path for dump-file
wchar_t dumpFilePath[MAX_PATH] = {0};
_snwprintf_s(dumpFilePath, MAX_PATH, L"crash_%04d-%d-%02d_%d-%02d-%02d.dmp"
, SystemTime.wYear, SystemTime.wMonth, SystemTime.wDay
, SystemTime.wHour, SystemTime.wMinute, SystemTime.wSecond
);
//create and open the dump-file
HANDLE hFile = ::CreateFileW( dumpFilePath, GENERIC_WRITE
, FILE_SHARE_WRITE
, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_HIDDEN
, NULL
);
if (hFile != INVALID_HANDLE_VALUE) {
_MINIDUMP_EXCEPTION_INFORMATION exceptionInfo;
exceptionInfo.ThreadId = GetCurrentThreadId();
exceptionInfo.ExceptionPointers = exceptionPtr;
exceptionInfo.ClientPointers = NULL;
//at last write crash-dump to file
bool ok = dumpFunc(::GetCurrentProcess(), ::GetCurrentProcessId()
, hFile, MiniDumpNormal
, &exceptionInfo, NULL, NULL
);
//dump-data is written, and we can close the file
CloseHandle(hFile);
if (ok) {
//Return from UnhandledExceptionFilter and execute the associated exception handler.
// This usually results in process termination.
return EXCEPTION_EXECUTE_HANDLER;
}
}
}
}
//Proceed with normal execution of UnhandledExceptionFilter.
// That means obeying the SetErrorMode flags,
// or invoking the Application Error pop-up message box.
return EXCEPTION_CONTINUE_SEARCH;
}
usage
#include "3rdParty/crash-report.h"
int main(int argc, char *argv[])
{
CrashReporter crashReporter;
(void)crashReporter; //prevents unused warnings
// [application main loop should be here]
return 0;
}
Windows XP:
The following steps enable automatic crash dumps:
1) Open a command prompt, running as administrator
2) Run drwtsn32 -i. This will install Doctor Watson as the default debugger when something crashes
3) Click Ok
4) From the command prompt, run drwtsn32
5) Set the Crash Dump path to your favorite directory, or leave the default.
6) Set the Crash Dump Type to mini. Note that under some circumstances, we may ask you for a full crash dump.
7) Make sure the Dump All Thread Contexts and Create Crash Dump File options are selected.
8) Click Ok
9) If a user.dmp file already exists in the Crash Dump path, delete it.
Windows 7: Location is:
C:\Users[Current User when app crashed]\AppData\Local\Microsoft\Windows\WER\ReportArchive

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