How to attach a process to the current debugger programmatically? - c++

I have 2 projects in the solution that compile to A.exe and B.exe
A will start B and connect to it through a named pipe. I want to test the connection between them so I'd like to attach to both at the same time. Doing that manually every time is very tedious and inconvenient, especially when B will close after a timeout if it doesn't receive any data from A. Therefore I tried this
if (IsDebuggerPresent())
DebugActiveProcess(processId);
However it seems B is attached to A's debugger instead of Visual Studio's. So how can I attach B to VS debugger automatically?
I have windbg at hand for debugging crash dumps so it may also be a solution, as long as it can be done without multiple user interactions

Attach to a process B programatically
Method 1: Using VS
Open B.vcxproj and not your solution (.sln containning projects A and B)
Put your breakpoints
Run this dos command from your project A via system() (or other variant):
devenv /nosplash /run "G:\Logiciels\B\B.vcxproj" /nosplash /debugexe
devenv is a command in your VS path. In my case it in:
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC
When you run this command, B project is opened and break point reached.
Method 2: Using Windbg
Just call this command:
windbg -p ProcessID
Attach to a process B graphically
Open your B project in another instance, and attach to it like this :
And select your B.exe:

Related

Is my application runs from inside Visual Studio vs. by executing an EXE file

As I often test my binaries inside/outside Microsoft Visual Studio 2017, I want to control the behavior of my code in C/C++ console projects.
One for code for when I run .exe from within Visual Studio in Release mode.
Another when I just click my .exe from Explorer.
What flag or function should I use to know if my .exe was started from inside Visual Studio or not.
What I would like to achive is the:
#if !_RELEASE
system("pause"); // prevents auto shutdown of my .exe in Explorer
// double click
#endif
where _RELEASE is some kind of trait that triggers code in Studio launches,
but not visible in Explorer double click.
What flag or function should I use to know if my process was startded from inside Visual Studio or not.
You shouldn't do such behavior control from inside your program code. That's bad design, and clutters your program code with decisions that should be left on the caller.
I'd recommend if you need different behaviors of your program (e.g. running in background or with visible GUI), this should be controlled with e.g. configuration files or command line parameters.
You can do that for both, Visual Studio settings to specify cmd line parameters, or using a different configuration file, or even a combination of both.
As you seem to insist for a solution of your idea how to fiddle with this in the best way:
You can use the WINAPI functions to iterate through your parent process IDs and check if one of these is matching the "Visual Studio" module.
Here's a Q&A which links to the technique:
How can I reliably check whether one Windows process is the parent of another in C++?
It not exactly solution, but:
Raymond Chen(Microsoft winapi guru*) is most close in spirit to the problem I facing, helping me detect in what mode or circumstances I run my console session.
How can I tell whether my console program was launched from Explorer or from a command prompt?
printf("this process = %d\n", GetCurrentProcessId());
DWORD count = GetConsoleProcessList(nullptr, 0);
if (count == 1) {
printf("I'm the last one!\n");
Sleep(2000);
}
else {
printf("I'm not the last one! %d\n", count);
}

Is it possible to suppress MessageBox when running a specific command?

I'm using Tortoise SVN, and TortoisePlink for remote ssh connections.
From time to time TortoisePlink is displaying errors like:
---------------------------
TortoisePlink Fatal Error
---------------------------
Network error: Software caused connection abort
---------------------------
OK
---------------------------
And they appears as messagebox and needs to be clicked by end-user.
I have tried to suppress messagebox by using -batch from command line, but problem still can be reproduced. For me it's sufficient if I'll disable messagebox prompting and print for example in command line same information - since my batch will retry later on again automatically.
Does there exists such software which can override default windows behavior and print in console window whatever is displayed in message box.
I guess in simplest terms such command line tool can be easily created, using for example
http://www.codeproject.com/Articles/44326/MinHook-The-Minimalistic-x-x-API-Hooking-Libra
and override MessageBoxA / MessageBoxW - but have anyone done this kind of thing ?
I think you're going about this the wrong way. Instead of trying to suppress the dialog boxes that TortoisePlink is showing, use the original Plink. TortoisePlink is a fork of Plink to explicitly show message boxes and not print anything on a command line, because it's designed for an UI app and not for console apps.
And if you really only want to use svn from a batch file, don't use TortoiseSVN but the original svn command line client (can be installed with the TSVN installer as well) and use the 'svn' command from the command line.
TortoisePLink.exe is targetted for end-user - so it's intended to display message boxes, however - there also exists a command line version of PLink.exe, and it can be downloaded from here:
http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html
Please notice that "TortoiseSVN" > "Settings" > "Network" > "SSH Client" should use TortoisePLink.exe - errors will be displayed to end-user.
For following file however -
%appdata%\Subversion\
file ‘config’:
In section [tunnels]
Add line like this:
ssh = Plink.exe -l <your login> -pw <password>
You should use command line version of PLink.exe (that is also displaying command prompt when launched).
It's easier to save PLink.exe next with TortoisePLink.exe, that is into
C:\Program Files\TortoiseSVN\bin.
I have tried to make a command line tool for supressing messageboxes, but it's useless for TortoisePLink.exe (Haven't debugged what is the problem), but in case if you're interested (Have other means to use it):
https://sourceforge.net/p/diagnostic/svn/HEAD/tree/Tools/msgboxSupress/
msSupress.cpp is compiled into .dll and it uses minimalistic hook for windows to disable MessageBoxA and MessageBoxW - actually they will be printed to console or redirected to file.
msSupressExe.cpp is compiled into .exe and it starts process in suspended mode, replaces .exe's entry point with EB FE (jump short into itself), waits until that address is reached, injects .dll and .dll will hook new process.
I have tested only on 64-bit platform - I suspect that command being executed must match same platform as as msSupress.exe.
So typically TortoisePlink.exe will display messagebox - but when executed like this:
mbSupress.exe "C:\Program Files\TortoiseSVN\bin\TortoisePlink.exe"
Same stuff as shown over message box will be displayed in console.
I think this solution is good prototype for further virus or trojan construction - using technique like this will allow to intercept even keyboard presses on any application - but I now made a command line utility, not a virus.

Run a console application and then close the console and run in background in C++

I want to make a console application in C++ and then when the information is displayed, close the console and run in background. Is this possible? Is another way to do that? Python maybe?
You will have to either close the console window while the process is still running, which is system dependent, or start another process, and even though the standard library offers the system function to do that, its argument is a system dependent command line.
So the upshot is: this is system dependent.
In Windows the full-version of Microsoft's Visual Studio IDE has always, as far back as I can remember, used a peculiar approach for this, with two executable files devenv.com and devenv.exe. The former is a console subsystem executable, which by default runs the latter, which is a GUI subsystem executable:
[C:\]
> where devenv
C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\devenv.com
C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\devenv.exe
[C:\]
> _
The basic idea here is that for historical reasons the command interpreter's search for an executable finds the .com file first, so the command devenv just works, either for starting the IDE or just getting the help text via the /? option.
Yes, this is possible with a small variant:
fork another process. But this is heavily system dependent:
posix/linux allow to simply clone the process;
windows requires new process to be created from an executable. You then have to communicate the state. Its less trivial as explained in this article, in the paragraph on porting fork())
then exit the program (it's the only way to give back control to the console).
On Windows use ShowWindow(FindWindowA("ConsoleWindowClass", NULL), false) to hide the console window. It will still be running in the background and is not visible on the taskbar.
However you will have to run a task manager like Taskmgr.exe to find it and shut it down.
#include <windows.h>
#include <iostream>
using namespace std;
int main () {
cout<<"Some information is displayed.. \n\n";
Sleep(5000);
cout<<"wait.. the console is going to hide and run in background.. \n";
Sleep(5000);
ShowWindow(FindWindowA("ConsoleWindowClass", NULL), false);
while(true) {
// Do your hidden stuff in here
}
return 0;
}
The other answers given here overcomplicate things. The most easy way to close the console window in Windows is to simply detach from it. Once the last user of a console window datached, the console window gets closed.
If you start a program from a CLI (e.g. cmd.exe) then this CLI is also attaches to to the console and thus the console window will not close.
Anyway, detaching from a console is as simple as calling
FreeConsole();
… done!
Also you can attach to a newly created console at any time using AttachConsole, which takes a process ID. Now in a CLI situation the parent will usually be the CLI shell, so you may want to attach to the console of that.

Terminate the previous iteration when building a new one

TL;DR: How can I make CLion kill off any running versions of the code before building the new one?
I've started playing with CLion for C++. I noticed that I often forget to stop the last iteration before trying to compile again, which leads to "Permission denied" errors -- when I first encountered this, it took me almost half an hour of fiddling with permission settings before realizing that it was because the old version was still running, and therefore couldn't be replaced with the new executable.
As far as I can tell, there's no way to do this in CMake without embedding a Batch (since I'm on Windows) script. I'd like to avoid that, because it'd be a lot of unnecessary complexity for... not that much reward.
In short, is there an option in CLion or something in CMake that will stop the previous iteration when running the new one?
Yes there is. Simply press ctrl + F2 or goto Run > Stop to terminate the previous iteration in case it keeps running.
Alternatively, you can set to run only single instance. This way previous instance will always be terminated before running the new one. To enable this, goto Run | Edit Configurations and select Single Instance Only.
As far as I know, this is not possible by default.
One solution I have found was to create a batch file with the following content:
#echo on
tasklist /FI "IMAGENAME eq %1" 2>NUL |find /I "%1">NUL
if "%ERRORLEVEL%"=="0" taskkill /F /im %1
(Second line checks whether the process is running - found here: How to check if a process is running via a batch script)
And edit the build configuration to make CLion call the batch file and pass the processname to it before every build.
This is how it works:
Run > Edit Configurations > select the configuration to change (in my case "Build All")
In the "Before launch: External..."-section click the green plus
Choose "Run external tool" and click the green plus in the pop-up window
Choose a name for the tool
Add the path of the batchfile in the "Program:" field
Write $ProjectName$.exe into the "Parameters:" field
Click ok until you are back in the config window
Give the script a sufficient priority by selecting it and clicking the arrow up
Now it should try to kill the running process before every build.

VC++ doesn't detect newly created env variable using GetEnvironmentVariable

I'm using the Win32 function GetEnvironmentVariable to retrieve the value of a variable that I just created. I'm running Windows XP and VC++ 2005. If I run the program from within Visual Studio, it can't find the new variable. If I run it from a command-prompt, it does. I restarted VC++ but same result. I even restarted all instances of Visual Studio but still the same problem. It might get resolved if I reboot the PC but I'm curious why this is so. Here's the code that I'm using:
#define BUFSIZE 4096
#define VARNAME TEXT("MY_ENV_NAME")
int _tmain(int argc, _TCHAR* argv[])
{
TCHAR chNewEnv[BUFSIZE];
DWORD dwEnv = ::GetEnvironmentVariable(VARNAME, chNewEnv, BUFSIZE);
if (dwEnv == 0)
{
DWORD dwErr = GetLastError();
if(dwErr == ERROR_ENVVAR_NOT_FOUND)
{
printf("Environment variable does not exist.\n");
return -1;
}
}
else
{
printf(chNewEnv);
}
return 0;
}
If I replace MY_ENV_NAME with something that must exist, such as TEMP, it works as expected. Any ideas? Thanks.
Expanding on what Anders and Martin said, environment variables are one thing that is inherited when starting an application. The new program basically gets a copy of the environment at the time it was started. When debugging, your exe is generally started by Visual Studio, so your application will have the same environment as Visual Studio. Visual Studio, is generally started by explorer. If you change the environment variables by going to System Properties->Advanced->Envronment Variables then you will have to restart Visual Studio to see the changes.
If you need to see the envronment variables that Visual Studio is seeing you can (at least for VS2005/2008) go to Tools...->options...->Projects and Solutions->VC++ Project Settings and set Show Environment in Log to 'Yes.' This will print out all the environment variables to the build log (ctrl+click on the link in your build output). You have to build to get this info, but this is the best way I know of seeing the VS environment.
If you really need to change environment variables then run and are having a hard time debugging, you can build your debug exe and have a call to DebugBreak() somewhere near where you want to start debugging from. Then you can set your environment how you want, start the exe from explorer or the command prompt. Then (assuming you have JIT debugging enabled) you will get a popup when your code gets to the DebugBreak() call and you can attach to it with VS and debug normally from there.
Make sure you restart the application before you can read the environment variable. The same happens if you have a console window open and change the environment variables on My Computer, these are not noted in any existing console windows. You need to restart them to get a copy of the new environment variables.
It all depends on how you set the environment variable:
If you ran set MY_ENV_NAME=val in a command prompt, then you have set MY_ENV_NAME for that instance of cmd.exe and any child processes it executes in the future. The environment of existing child processes is not modified.
In this case, exiting the Visual Studio IDE and starting it from the command line (not Explorer) should cause it and its child processes to see the new environment variable.
If you used the System or Users control panel or the setx command to set MY_ENV_NAME, then you have set MY_ENV_NAME persistently, and it will be set for all processes after you reboot your computer. In addition, you may find that some processes, such as Explorer, pick up the environment variable change immediately.
This works by storing the new environment variable in the registry under HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment or HKEY_CURRENT_USER\Environment, depending on whether you chose to set a system environment variable or a per-user environment variable. Existing processes are notified that there was an environment variable change by broadcasting the WM_SETTINGCHANGE message with lParam=="Environment". This message causes them to re-read the persistent environment variables from the registry if they know how. KB104011 has more details.
As a result, if you use the System or Users control panel to set a new environment variable, exiting the Visual Studio IDE and starting it again from Explorer (not a command prompt) should cause it and its child processes to see the new environment variable.
Thanks for all the responses. As I mentioned in my question, I tried restarting everything, short of rebooting the PC. It turns out that because my environment variable was a SYSTEM variable, VS doesn't recognize it without rebooting the PC. When I moved the env variable from SYSTEM to USER and restarted VS, it worked fine.