By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
458,068 Members | 830 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 458,068 IT Pros & Developers. It's quick & easy.

C++11 running DOS commands without a DOS window

P: 25
I did search this. I know. I tried that.

I am not trying to read a batch file.
I am not trying to write a batch file.
I am not trying to run a batch file.
I am not trying to start a batch file via C++.
I am not trying to compile C++ via a command line interface.

I am using C++11 with a GUI on 32 bit Windows.
I am Not using Visual Studio.
I am Not using .net .


I want to be able to put something like "C:\dir\w" in my C++11 code that gives me a response that is in a std::string that I can use WITHOUT A DOS OR CLI INTERFACE WINDOW.

No command interface window. Not a blink of a CLI. Nothing there.

I start a winmain and it gives me a messagebox that tells me the response to "C:\dir\w".

This should be easy.
Jun 5 '20 #1

✓ answered by dev7060

Expand|Select|Wrap|Line Numbers
  1. #include <windows.h>
  2. #include <fstream>
  3. #include <iostream>
  4. using namespace std;
  5. int APIENTRY WinMain(HINSTANCE hInst, HINSTANCE hInstPrev, PSTR cmdline, int cmdshow) {
  6.   HWND Stealth;
  7.   AllocConsole();
  8.   Stealth = FindWindowA("ConsoleWindowClass", NULL);
  9.   ShowWindow(Stealth, 0);
  10.   char * command = "systeminfo > temp";
  11.   system(command);
  12.   ifstream ifs("temp");
  13.   string content((istreambuf_iterator < char > (ifs)),
  14.     (istreambuf_iterator < char > ()));
  15.   const char * cstr = content.c_str();
  16.   ifs.close();
  17.   system("del temp");
  18.   return MessageBox(NULL, cstr, "caption", 0);
  19. }
I want to be able to put something like "C:\dir\w" in my C++11 code that gives me a response that is in a std::string that I can use WITHOUT A DOS OR CLI INTERFACE WINDOW.
The output of the command is available in the string object 'content' and later being displayed on the window.

Share this Question
Share on Google+
11 Replies


Expert 100+
P: 260
There's a workaround using redirection operator. But the console window will be triggered anyway either in hidden or visible form. So guess that wouldn't suit in accordance with what you're looking for.
Jun 5 '20 #2

P: 25
Thank you dev7060. A console in hidden form? I do not recall doing that. Maybe if I run two threads one starts a console window and the other fast reacts to the Windows operating system's creating of the console window and maybe sub-classes the console window? That is if Windows starts the creation of the console window via a temporary handle like I have seen elsewhere. Your wisdom has further sparked my curiosity. Thanks.

Have you or someone else here created a console window as a control on a GUI window via C++? I could maybe work with that.

Thanks.
Jun 6 '20 #3

Expert 100+
P: 260
Expand|Select|Wrap|Line Numbers
  1. #include <windows.h>
  2. #include <fstream>
  3. #include <iostream>
  4. using namespace std;
  5. int APIENTRY WinMain(HINSTANCE hInst, HINSTANCE hInstPrev, PSTR cmdline, int cmdshow) {
  6.   HWND Stealth;
  7.   AllocConsole();
  8.   Stealth = FindWindowA("ConsoleWindowClass", NULL);
  9.   ShowWindow(Stealth, 0);
  10.   char * command = "systeminfo > temp";
  11.   system(command);
  12.   ifstream ifs("temp");
  13.   string content((istreambuf_iterator < char > (ifs)),
  14.     (istreambuf_iterator < char > ()));
  15.   const char * cstr = content.c_str();
  16.   ifs.close();
  17.   system("del temp");
  18.   return MessageBox(NULL, cstr, "caption", 0);
  19. }
I want to be able to put something like "C:\dir\w" in my C++11 code that gives me a response that is in a std::string that I can use WITHOUT A DOS OR CLI INTERFACE WINDOW.
The output of the command is available in the string object 'content' and later being displayed on the window.
Jun 6 '20 #4

P: 25
Thank you dev7060.

I like bytes.com .

Many times I have tried to code but did not know where to start or even what questions to ask. But, when I asked without some example code of a mistake on other sites, I received negative replies (arrogant in my opinion). Here I asked and had no code to show even some errors and I received help. Thank you for your helpful attitude.

I did not want a DOS window, but I would accept it if it was hidden. I got that. From your code, I studied DOS commands and spent quite a few hours studying how and why you coded what you did.

I restudied this project for many hours trying to understand how to get a std::string from reading a text file. I read a lot of examples on the internet and they almost all used cout (which I did not want), and I had difficulty just reading a file into a std::string. Finally I went back to your code and worked through the compiler responses to learn what you did. Again, this site, bytes.com, was the best.

Here is my working example:

It is on an older business laptop (I got from eBay) with XP Professional, Service Pack 2 (never sp3). It is coded with CODE::BLOCKS 17.12 (not a later version) with 32 bit, with most warnings and optimizations set and C++11 set. That should help a future reader to understand how this works.

Expand|Select|Wrap|Line Numbers
  1.     // Using the following defines
  2.     // #define _UNICODE
  3.     // #define UNICODE
  4.  
  5.     // Report that this process is starting
  6.     MessageBox(nullptr, L"Starting DOS access for information", L"Starting DOS access for information", MB_ICONEXCLAMATION | MB_OK);
  7.  
  8.     HWND Stealth;
  9.  
  10.     // Start a DOS window.
  11.     AllocConsole();
  12.  
  13.     // Get the handle of the DOS window.
  14.     Stealth = FindWindowA("ConsoleWindowClass", NULL);
  15.  
  16.     // Hide the DOS window so fast that it is not seen (I guess).
  17.     ShowWindow(Stealth, 0);
  18.  
  19.     // Clean up previous running of this program and remove any and all subdirectories and files 
  20.     //   inside of the C:\a1\ directory while removing the a1\ directory itself.
  21.     // Using a character pointer or a pointer to a character; not sure why, but it works.
  22.     char * command0 = "if exist C:\\a1 RMDIR C:\\a1 /s /q";
  23.     system(command0);
  24.  
  25.     // Make the directory C:\\a1.
  26.     char * command1 = "md C:\\a1";
  27.     system(command1);
  28.  
  29.     // Connect to the directory C:\\a1.
  30.     char * command2 = "cd C:\\a1";
  31.     system(command2);
  32.  
  33.     // Run the DOS command systeminfo and save the result to sysinfo1.txt in the directory C:\\a1.
  34.     char * command3 = "systeminfo > C:\\a1\\sysinfo1.txt";
  35.     system(command3);
  36.  
  37.     // Run the DOS command dir and save the result to dir.txt in the directory C:\\a1.
  38.     char * command4 = "dir > C:\\a1\\dir.txt";
  39.     system(command4);
  40.  
  41.     // Close the DOS window. I think that MS Windows only allows one DOS window 
  42.     //   open per running executable.
  43.     FreeConsole();
  44.  
  45.     // Use std::ifstream to get the text from sysinfo1.txt and put it into ifs1.
  46.     // I am not clear on what type ifs1 is but I think that it is probably a std::string.
  47.     // This might be a setup for what ifs1 does in the next code. I do not know how to describe this.
  48.     std::ifstream ifs1("C:\\a1\\sysinfo1.txt");
  49.  
  50.     // Not really clear on what this does. If someone smarter than me reads this,
  51.     //   I would like a full discussion of this line, what each part does and why 
  52.     //   and the limitations of it, please.
  53.     std::string content1((std::istreambuf_iterator < char > (ifs1)),
  54.     (std::istreambuf_iterator < char > ()));
  55.  
  56.     // String to Wide String std::wstring.
  57.     // I have found that this can be placed into a separate procedure if desired.
  58.         std::wstring widestrDOS = std::wstring(content1.begin(), content1.end());
  59.  
  60.     // Wide String to wchar_t
  61.     // I have had a lot of difficulty placing this into a separate procedure and getting it to work correctly.
  62.         const wchar_t* SystemInformationAs_wchar_t = widestrDOS.c_str();
  63.  
  64.     // Note on previous std::string to std::wstring to const wchar_t*. I have tried many times to code a
  65.     //   separate procedure with these two in it that I can send a std::string to the procedure and get
  66.     //   a const wchar_t* in return. It seems to have to be in the same procedure as the originating
  67.     //   std::string. Maybe if I do not use a return value and instead save the resulting const wchar_t* 
  68.     //   as a global, then I can use it, but I wanted a procedure with a return that I could use.
  69.  
  70.     MessageBox(nullptr, SystemInformationAs_wchar_t, L"System Information", MB_ICONEXCLAMATION | MB_OK);
  71.  
  72.  
  73.     // Similar notes for the following.
  74.  
  75.     std::ifstream ifs2("C:\\a1\\dir.txt");
  76.  
  77.     std::string content2((std::istreambuf_iterator < char > (ifs2)),
  78.     (std::istreambuf_iterator < char > ()));
  79.  
  80.     // String to Wide String std::wstring
  81.         std::wstring widestrDIR = std::wstring(content2.begin(), content2.end());
  82.  
  83.     // Wide String to wchar_t
  84.         const wchar_t* DIR_As_wchar_t = widestrDIR.c_str();
  85.  
  86.     MessageBox(nullptr, DIR_As_wchar_t, L"DIR", MB_ICONEXCLAMATION | MB_OK);
  87.  
  88.  
Thanks for not trying to tell me how stupid I am for not using Visual C++ or Boost. I already studied those and do not want any part of them.

Thank you dev7060. Your example code was very helpful.
4 Weeks Ago #5

Expert 100+
P: 260
Expand|Select|Wrap|Line Numbers
  1.     // Using a character pointer or a pointer to a character; not sure why, but it works.
  2.     char * command0 = "if exist C:\\a1 RMDIR C:\\a1 /s /q";
  3.     system(command0);
  4.  
Because the standard library function system() is declared as int system(const char*) and hence cannot accept a string object as the argument. This is a good old classic way of representing arrays.

// Close the DOS window. I think that MS Windows only allows one DOS window
// open per running executable.
Use the "/c" flag to start a new cmd instance.

Expand|Select|Wrap|Line Numbers
  1.     // I am not clear on what type ifs1 is but I think that it is probably a std::string.
  2.     // This might be a setup for what ifs1 does in the next code. I do not know how to describe this.
  3.     std::ifstream ifs1("C:\\a1\\sysinfo1.txt");
  4.  
ifs1 is an object of ifstream class.

Expand|Select|Wrap|Line Numbers
  1.     // Not really clear on what this does. If someone smarter than me reads this,
  2.     //   I would like a full discussion of this line, what each part does and why 
  3.     //   and the limitations of it, please.
  4.     std::string content1((std::istreambuf_iterator < char > (ifs1)),
  5.     (std::istreambuf_iterator < char > ()));
Function objects are used as arguments (often called functors). They are most commonly used with Standard Template Library.
4 Weeks Ago #6

P: 25
Thank you dev7060.

I asked for code limited to "I am using C++11 with a GUI on 32 bit Windows."

I am not changing the part of using C++11 or using GUI. I have some questions about varying the 32 bit part.

I have read that Microsoft has tried to convince people that DOS no longer is a part of Windows currently. I have also read that Microsoft lies about this and Windows 10 actually does have DOS in it. I am wondering the following:

(1.) If I was to use a 32 bit version of Windows 7 or Windows 10, not in WoW, just a 32 bit version, would this code work there? If someone reads this and has that type of operating system please test and tell me how this works. If it does not, then please make suggestions.

(2.) If I was to use a 64 bit version of Windows XP, or 7, or 10, (I guess that this one program would be running in WoW) , would this code work there? If someone reads this and has that type of operating system please test and tell me how this works. If it does not, then please make suggestions.

I do not know if I should make those two questions separate from this tread or not. If so, please advise.
Thank you all.
4 Weeks Ago #7

Expert 100+
P: 260
In my view,

A build is generated using the system calls/API/libraries of that particular OS and architecture. This is what it means when they say the term "platform dependent". The build is always compatible with the machine using which it is generated.

32-bit versions are compatible with the machine of 64-bit architecture. The performance may be slightly slower but it would work using the WoW64 emulation.

To emulate and mimic the run of a particular OS, Right-click on the build -> Properties -> Under the Compatibility tab, there's an option to run the exe in compatibility mode for Windows 7/8/Vista, etc.

A virtual machine can always be used to test or generate the builds for the target environment.
4 Weeks Ago #8

Banfa
Expert Mod 5K+
P: 8,949
I have read that Microsoft has tried to convince people that DOS no longer is a part of Windows currently. I have also read that Microsoft lies about this and Windows 10 actually does have DOS in it. I am wondering the following
You are wrong there is no DOS in Windows, there are a number of ways to know this for example you could consider memory management. The memory map that exists in DOS and Windows are completely different, the last time they definately bore resemblance was in Windows 3 and they were definately diverging by Windows XP.

One obvious point is Windows can handle gigabytes of ram while DOS can handle more than 640k without an extended memory manager, another is how we address memory in our programs and another is just the fact that Windows uses virtual addressing and DOS doesn't.

Another way to tell is just try running a DOS program in Windows, it won't run, in any compatibility mode, I know because I recently tried running my copy of Dig and the only way to get that going was to install FreeDOS in a virtual machine. Similarly any modern Windows console program won't run on a DOS machine.

They're completely operating systems.

You can create command line programs in Windows but the command line is not DOS.
4 Weeks Ago #9

P: 25
Banfa and dev7060. Thank you each.

Yes, I misspoke calling a command line interface a DOS window. Old habits. I knew better, but knowing and doing are not the same. Still trying to flush out some old coding habits.

I am back to my starting conditions:
If
I compile the C++ code as I described in the original post, on an 32 bit Windows operating system; not using Visual Studio, and not using .net, and (creating a stand alone executable on Windows XP Professional 32 bit),
And If
I use the code that I adapted from dev7060's excellent response,
Then
I am not sticking to my original request of "No command interface window. Not a blink of a CLI. Nothing there."

I accepted his answer, but I am concerned with being able to use the executable compiled in 32 bit Windows in later machines. Thus, the follow on questions.

Banfa, you have reminded me of some of my concerns about how to get information (now that I am using C++11) which I used to be able to get from a command line interface.

I thought that my request was too much for many other programmers since that seemed to be what I found via internet searches. But, bytes.com has some intensely knowledgeable members and I still think that here I can find how to do this.

If I have to use a command prompt, then I want to know if the executable compiled on a 32 bit XP Pro will work on 64 bit Windows 10 or any other Windows version past XP Pro.

I do not want to do this with any command prompt. I do not want to do this with calling a command line hidden window. I want to do this with C++. I feel that the accepted manner is a compromise which, in this case, makes me uncomfortable.

Please you two and others, please help. Weeks of not finding the answer elsewhere has lead me to ask at bytes.com.
4 Weeks Ago #10

Banfa
Expert Mod 5K+
P: 8,949
So my Windows knowledge is a little rusty (been about a decade since I did anything significant on Windows) but you should look into the CreateProcess function either

CreateProcessA - ASCII version

or

CreateProcessW - wide character version

I believe the symbol CreateProcess is #defined to 1 of these 2 to match your current settings.

Anyway CresateProcess gives you lots of options for starting your process, note that it is a Windows only function, part of the WIN342 API but I think it should work in the way you want across the platforms you want, in particular investigate the CREATE_NO_WINDOW flag.

Getting a process built for a older windows system to run on a newer one is a matter of getting the right emulation for the process or having the right sub-system installed. I do not know your exact situation limiting your build environment compared to your run-time environment but you are far better off if possible building your application for the environment it is going to run on, in the long run you will get far fewer headaches.
4 Weeks Ago #11

Expert 100+
P: 260
I do not want to do this with any command prompt. I do not want to do this with calling a command line hidden window. I want to do this with C++. I feel that the accepted manner is a compromise which, in this case, makes me uncomfortable.
If the aim is to not include command prompt in the process, then I believe the internals needs to be figured out. Like what and how calls are being made using the console api or winapi and how the text rendering engine is being used to get the output of the command.

Banfa's post is spot on. CreateProcess() can be used. However, stdout redirection can't be used with it because createprocess just launches processes and doesn't interpret the text passed to it. A filehandle needs to be specified in the STARTUPINFO structure. CreateProcess() works like parent-child relation similar to fork system call in Linux.
4 Weeks Ago #12

Post your reply

Sign in to post your reply or Sign up for a free account.