Thread: How prevent console window from appearing in C?

  1. #1
    Algorithm engineer
    Join Date
    Jun 2006
    Posts
    286

    How prevent console window from appearing in C?

    Hi, I've written a simple program (using MinGW) which starts Emacs with the same arguments as the program got itself (I'm using Windows 7 and since Windows Vista only programs in certain folders, such as Program Files, can be associated with different file types). It should be as a middle hand that opens Emacs, and it shouldn't be visible to the user.

    The program does open Emacs; the only flaw is that a console window pops up and closes immediately, before Emacs is started, so it's not completely invisible. I don't want that console window to appear.

    I've tried many of the suggestions for this problem on the internet, but either they don't work or they don't compile. I think many of the suggestions are just for hiding the console window once it has launched.

    I'm compiling using MinGW and MSYS. One suggestion when using MinGW is to ad -lmingw32 as an argument to the compiler, but that doesn't work; another suggestion to solve the problem is to include windiws.h and call FreeConsole() in main(), but that doesn't work either.


    .
    .
    .


    Edit: By the way, if it should be of any interest to you, here's the code:

    Code:
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    
    #define MALLOC_NUM(ptr, number) {					\
    		ptr = (typeof(ptr)) malloc(sizeof(*ptr)*number);	\
    		if (!ptr) {						\
    			printf("Not enough memory\n");			\
    			exit(1);					\
    		}							\
    	}
    
    const char* app = "runemacs";
    
    int main(int argc, char** argv) {
    	int i;
    
    	//Calculate the total length of the command line
    	int* args_end_at;
    	MALLOC_NUM(args_end_at, argc);
    	args_end_at[0] = strlen(app);
    	for (i = 1; i < argc; i++) {
    		args_end_at[i] = args_end_at[i-1] + 1 + strlen(argv[i]);
    	}
    
    	//Allocate memory for line
    	char *command_line, *line_ptr;
    	MALLOC_NUM(command_line, args_end_at[argc] + 1);
    
    	//Copy arguments to line
    	strcpy(command_line, app);
    	for (i = 1; i < argc; i++) {
    		line_ptr = command_line + args_end_at[i-1];
    		*(line_ptr++) = ' ';
    		strcpy(line_ptr, argv[i]);
    	}
    	command_line[args_end_at[i-1]] = '\0';
    
    	//Run command
    	system(command_line);
    	return 0;
    }
    Last edited by TriKri; 10-01-2009 at 10:11 AM. Reason: Added code
    Come on, you can do it! b( ~_')

  2. #2
    Registered User
    Join Date
    Oct 2006
    Posts
    3,445
    to your compiler command line, add the following parameters:

    Code:
    -mwindows -mms-bitfields

  3. #3
    Algorithm engineer
    Join Date
    Jun 2006
    Posts
    286
    Hm, what does -mms-bitfields do?

    Anyway, I have found the problem. What was wrong was that I called the function system, which automatically opens a console window. Starting the new program with CreateProcess instead prevents that.

    Oh, yeah and another thing - my code doesn't work if any of the arguments following on the first one contains a space, because my program doesn't wrap them in quotation signs. The best is to use the function GetCommandLine, parse the string you get to find where the second argument starts, and then just add the rest of the line from there to the name of the application that you want to open. Okay, if anyone is interested, here's new and (hopefully) working code, now with spaces instead of tabs:

    Code:
    #include <string.h>
    #include <windows.h>
    
    #define MALLOC_NUM(ptr, number) {                               \
            ptr = (typeof(ptr)) malloc(sizeof(*ptr)*number);        \
            if (!ptr) {                                             \
                MessageBox(0, "Not enough memory",                  \
                           "open_with_emacs", MB_ICONERROR);        \
                exit(1);                                            \
            }                                                       \
        }
    
    int main(int argc, char **argv) {
        const char* app = "runemacs";
        const unsigned int app_name_length = strlen(app);
        char *curr_cl, *new_cl; /* Current and new command line */
        /* For creating the process */
        STARTUPINFO          si = {sizeof(si)};
        PROCESS_INFORMATION  pi;
    
        /* Find arguments */
        curr_cl = GetCommandLine();
        if (argc >= 1) {
            if      (*curr_cl == '"' ) curr_cl += strlen(argv[0]) + 2;
            else if (*curr_cl != '\0') curr_cl += strlen(argv[0]);
        }
        
        /* Create new command line */
        MALLOC_NUM(new_cl, app_name_length + strlen(curr_cl) + 1);
        strcpy(new_cl, app);
        strcpy(new_cl + app_name_length, curr_cl);
        
        /* Run command line */
        if (CreateProcess(0, /* lpApplicationName, optional */
                          new_cl, /* lpCommandLine, The command line to be executed */
                          0, /* lpProcessAttributes */
                          0, /* lpThreadAttributes */
                          0, /* bInheritHandles */
                          0, /* dwCreationFlags */
                          0, /* lpEnvironment */
                          0, /* lpCurrentDirectory */
                          &si, /* lpStartupInfo */
                          &pi  /* lpProcessInformation, receiving process id information */
                          )) {
            /* optionally wait for process to finish */
            /* WaitForSingleObject(pi.hProcess, INFINITE); */
            /* Closing handles is completely safe */
            CloseHandle(pi.hProcess);
            CloseHandle(pi.hThread);
        }
        free(new_cl);
        return 0;
    }
    And this makefile can be used:

    Code:
    CC=gcc
    CCFLAGS= -Wall -Wextra -pedantic -g -std=c++98
    CCFLAGS+=-lmingw32
    CCFLAGS+=-Wl,--subsystem,windows #Can sometimes be replaced with -mwindows
    FILES=main.x
    SRC=$(FILES:.x=.c)
    OBJ=$(FILES:.x=.o)
    OUT=open_with_emacs.exe
    
    all: $(OUT)
    	rm $(OBJ) #Remove .o files
    
    $(OBJ) :
    	$(CC) $(SRC) $(CCFLAGS) -c #Create .o files
    
    $(OUT) : $(OBJ)
    	$(CC) $(OBJ) $(CCFLAGS) -o $@ #Link .o files
    Come on, you can do it! b( ~_')

  4. #4
    Algorithm engineer
    Join Date
    Jun 2006
    Posts
    286
    And another thing - it's strange - with my old code (which I posted first) I frequently got the message "Not enough memory". However it didn't happen every time I run the program (although very often), and it always happened when I hadn't run the program for a while. I don't spot anything in the code that could cause the problem (do you?); with the new code I don't have the problem though.

    If you look at how much it tries to allocate, one time it's argc bytes (which it should manage), the other time it's the length of the string including the null sign it needs to allocate memory for.
    Come on, you can do it! b( ~_')

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Reading from console window...
    By alvifarooq in forum C++ Programming
    Replies: 2
    Last Post: 09-22-2004, 02:22 AM
  2. my wndProc is out of scope
    By Raison in forum Windows Programming
    Replies: 35
    Last Post: 06-25-2004, 07:23 AM
  3. OpenGL and Windows
    By sean345 in forum Game Programming
    Replies: 5
    Last Post: 06-24-2002, 10:14 PM
  4. Tab Controls - API
    By -KEN- in forum Windows Programming
    Replies: 7
    Last Post: 06-02-2002, 09:44 AM
  5. opengl code not working
    By Unregistered in forum Windows Programming
    Replies: 4
    Last Post: 02-14-2002, 10:01 PM