2

I just asked a question earlier today because I wanted to run an executable file that takes parameters from my C++ code and it wasn't working.

It works now, but I'm still having problems since I thought I was going the right way about this, but it seems like what I want to accomplish can't be done the way I'm approaching it...

This is my corrected code from my other question:

#include <stdlib.h>
#include <conio.h>

int main (){
    system("\"\"C:\\Users\\Adam\\Desktop\\pdftotext\" -layout \"C:\\Users\\Adam\\Desktop\\week 4.pdf\"\"");
    _getch();
}

which is me running "pdftotext -layout myfile.pdf" as if I was running it from a CMD window.

The thing is, I don't actually want the cmd to show up since I have a GUI interface on top of it and I want to display a nicer progress bar instead of seeing the windows pop-up for every file I need to parse.

I looked around and either I don't understand what I'm reading since I'm relatively new to C++, or I just didn't find what I was looking for. I found that using CreateProcess, I should be able to do this, but after copying some code I found somewhere else, the cmd window pops-up anyway.

I'd like it if someone could give me the name of a function I could use to accomplish something like this or if someone could give some example code for this small case in the code I posted since I'm not sure I understand everything as I should, being new to C++ and all.

Edit: As requested in a comment, the code for CreateProcess that I tried is what I found at this url:

http://www.goffconcepts.com/techarticles/development/cpp/createprocess.html

Which is (with my own parameters that I think should go there):

#include <windows.h>
#include <string>
#include <conio.h>

size_t ExecuteProcess(std::wstring FullPathToExe, std::wstring Parameters, size_t SecondsToWait)
{
    size_t iMyCounter = 0, iReturnVal = 0, iPos = 0;
    DWORD dwExitCode = 0;
    std::wstring sTempStr = L"";

    /* - NOTE - You should check here to see if the exe even exists */

    /* Add a space to the beginning of the Parameters */
    if (Parameters.size() != 0)
    {
        if (Parameters[0] != L' ')
        {
            Parameters.insert(0,L" ");
        }
    }

    /* The first parameter needs to be the exe itself */
    sTempStr = FullPathToExe;
    iPos = sTempStr.find_last_of(L"\\");
    sTempStr.erase(0, iPos +1);
    Parameters = sTempStr.append(Parameters);

     /* CreateProcessW can modify Parameters thus we allocate needed memory */
    wchar_t * pwszParam = new wchar_t[Parameters.size() + 1];
    if (pwszParam == 0)
    {
        return 1;
    }
    const wchar_t* pchrTemp = Parameters.c_str();
    wcscpy_s(pwszParam, Parameters.size() + 1, pchrTemp);

    /* CreateProcess API initialization */
    STARTUPINFOW siStartupInfo;
    PROCESS_INFORMATION piProcessInfo;
    memset(&siStartupInfo, 0, sizeof(siStartupInfo));
    memset(&piProcessInfo, 0, sizeof(piProcessInfo));
    siStartupInfo.cb = sizeof(siStartupInfo);

    if (CreateProcessW(const_cast<LPCWSTR>(FullPathToExe.c_str()),
                            pwszParam, 0, 0, false,
                            CREATE_DEFAULT_ERROR_MODE, 0, 0,
                            &siStartupInfo, &piProcessInfo) != false)
    {
         /* Watch the process. */
        dwExitCode = WaitForSingleObject(piProcessInfo.hProcess, (SecondsToWait * 1000));
    }
    else
    {
        /* CreateProcess failed */
        iReturnVal = GetLastError();
    }

    /* Free memory */
    delete[]pwszParam;
    pwszParam = 0;

    /* Release handles */
    CloseHandle(piProcessInfo.hProcess);
    CloseHandle(piProcessInfo.hThread);

    return iReturnVal;
} 

int main(void){
    ExecuteProcess(L"C:\\Users\\Adam\\Desktop\\pdftotext", L"-layout \"C:\\Users\\Adam\\Desktop\\week 4.pdf\"", 0);
    _getch();
}

I'm a little bit overwhelmed since it uses some things I've never used before, but I think I understand the core (keyword: think). It doesn't solve my problem, though, because the cmd shows up and by retesting it I actually noticed that the cmd doesn't even run the .exe and doesn't give me an error message.

I hope this bit of code helps... I didn't want to look into it further since it seemed like I wasn't even going in the right direction.

Jumbala
  • 4,764
  • 9
  • 45
  • 65
  • 3
    Please show the code (using `CreateProcess`) that doesn't work. – zwol Apr 02 '12 at 02:46
  • "It doesn't solve my problem, though, because the cmd shows up and by retesting it I actually noticed that the cmd doesn't even run the .exe". Do you mean that the command prompt window appears even if `CreateProcess` doesn't spawn the specified .exe file? If that's the case, it sounds like your main executable is compiled as a console application, not a windowed application. – jamesdlin Apr 02 '12 at 03:37
  • @jamesdlin I get an empty black console window that stays there because of the _getch();, but I see it appear empty and disappear if I remove the _getch();. It might sound stupid, but I don't really know what you mean by your comment. I'm using Visual Studio 2010 and don't really know of compile options, I always select Create Empty Project (or create Qt4 project for projects with GUIs). If you meant that my compiler doesn't compile it like it should, could you explain how to do it otherwise? I know it sounds noobish but usually I make small console applications or use Qt with self-made code. – Jumbala Apr 02 '12 at 03:43
  • Try adding `siStartupInfo.dwFlags = STARTF_USESHOWWINDOW;` and `siStartupInfo.wShowWindow = SW_HIDE;` before you call `CreateProcess`. – Jesse Good Apr 02 '12 at 04:00
  • @Jesse It didn't work, but like jamesdlin mentioned, the command prompt that shows up might not be related to the CreateProcess, so I'll keep testing until I see that it at least calls the .exe and then I'll know if it works. I'll post another comment to tell you when I can fully test it. As for jamesdlin, I don't know how to stop the default command prompt from showing (unless it always shows up in debug mode) – Jumbala Apr 02 '12 at 04:05
  • @AdamSmith: When you link your application, make sure use `/SUBSYSTEM:WINDOWS` if you don't want it to have a console window. Also see http://stackoverflow.com/questions/2422430/hide-console-of-c-program-in-window-os/2424210#2424210 – jamesdlin Apr 02 '12 at 04:42
  • jamesdlin Thanks, it doesn't display anything anymore, I just have to find what is wrong with the code (I'm probably just misunderstanding how I'm supposed to pass the parameters, I'll play around with that first) – Jumbala Apr 02 '12 at 04:53

3 Answers3

0

The only way I found how to execute an external program is: system("start C:\file path\ file"); The only problem is that the file or directory can't have spaces.

0

Use CreateProcess instead of system.

--EDIT--

the code for CreateProcess that I tried is what I found at this url:

The code is a mess, I'd advise to avoid that url in future.

At the end of "CreateProcess" article is a link named "Creating Processes", which contains simpler example that is easier to read. Use it as a starting point.

SigTerm
  • 26,089
  • 6
  • 66
  • 115
  • 3
    @SigTerm : If your answer doesn't further the OP's knowledge, it "is not useful" and warrants a downvote. The burden of writing a good answer is not on the people leaving comments... – ildjarn Apr 02 '12 at 03:03
  • @SigTerm Thanks for trying to help, but having tried CreateProcess using the code I edited in my OP, I still have the same problem and I had seen that link before. I tried some example codes I could find elsewhere since I don't fully understand all the parameters in that link, which is why I wanted an example or a shove in the right direction so I could be on the right path. At least now I know that CreateProcess is the right way to take. – Jumbala Apr 02 '12 at 03:10
  • @ildjarn: "burden".. bah. The time you wasted writing a comment was enough to write better answer. – SigTerm Apr 02 '12 at 04:56
  • @AdamSmith: I've updated the answer with a link to "cleaner" example. In the future instead of going to random websites, I'd advise start with msdn or official documentation. – SigTerm Apr 02 '12 at 05:07
  • @SigTerm : Agreed, but if you didn't set the bar so low, the case might be otherwise. – ildjarn Apr 02 '12 at 05:13
  • @SigTerm I'll keep that in mind, but like I said, I'm new to C++ and didn't know what the good / bad resources were before you mentioned them, which is why I went to random websites and then came asking here. I can obviously see that the link you posted is a lot better than the one I first used and I thank you for that. I'll try my code with the example in the link in your post. Thanks! – Jumbala Apr 02 '12 at 05:16
  • 1
    @AdamSmith: "didn't know what the good" For winapi info - msdn (or google `msdn functionName`). Quality of msdn had a bit deteriorated in past years, but still it is maintained by microsoft (which created winapi), so it is the best idea to start on msdn. For C++ info - http://www.cplusplus.com/reference/ . For 3rd party libraries and toolkit check the website of library/toolkit first. – SigTerm Apr 02 '12 at 05:21
0

After adding the following lines for siStartupInfo, cmd window won't pop up any more with my own test *.exe.

siStartupInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
siStartupInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
siStartupInfo.hStdOutput =  GetStdHandle(STD_OUTPUT_HANDLE);
siStartupInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE);
siStartupInfo.wShowWindow = SW_HIDE;

But I have another problem. As I try to run some other executable, whose command line would be

TEST.exe <input-file> output-file

in a cmd window, WaitForSingleObject() return 258, and GetLastError() return 1813 ("The specified resource type cannot be found in the image file."). See system() and CreateProcess() / CreateProcessW() for more details.

Any ideas would be highly appreciated!

Community
  • 1
  • 1
dehiker
  • 91
  • 1
  • 6
  • 1
    My problem solved with RemyLebeau's instruction in http://stackoverflow.com/questions/8649212/createprocess-and-command-line-arguments – dehiker Apr 02 '12 at 09:04