是否可以创建一个程序,如果从控制台启动时作为控制台应用程序运行,并在启动时作为Windows程序(使用GUI)工作?
如果有可能 - 我该怎么做?
问候 托拜厄斯
答案 0 :(得分:3)
如果您将程序设置为构建为GUI程序,则可以尝试使用AttachConsole()连接到控制台。您附加了OK然后从控制台启动,您可以继续将标准句柄重定向到新连接的控制台。
通过这种方式,您可以启动并查看是否从可以附加到的控制台启动,如果是,则成为控制台程序。如果你无法附加,你可以显示一个GUI。
我已经取得了一些成功,我的主要问题是当程序退出时重新显示命令窗口的提示(这是正常的控制台程序运行的方式),但我希望你能做一些聪明的事情(读取控制台缓冲区)在启动时,当你退出时找到重新显示的提示?)如果你真的想......
答案 1 :(得分:2)
如果您需要程序充当控制台应用程序(例如,将使用信息打印到控制台),则必须将其作为控制台应用程序进行压缩。 Windows应用程序无法访问控制台,cmd.exe将不会等待它完成,然后再打印提示并接受下一个命令。
最佳解决方案是拥有两个版本,一个用于命令行,一个用于GUI(用户通常通过桌面或开始菜单上的链接运行)。
如果您坚持使用单个二进制文件,则必须至少在短时间内出现控制台窗口。您可以使用
删除控制台窗口FreeConsole();
如果它是连接到控制台的唯一进程,您可以告诉您应用程序是从GUI运行的。您可以使用GetConsoleProcessList
查找附加到控制台的进程列表。
答案 2 :(得分:0)
程序本身永远不会知道它是如何启动的。除非您愿意将执行参数传递给程序。例如:program.exe -GUI ...您可以捕获传递的参数,并根据传递的参数决定程序的运行方式。
你的程序应该是这样的:
class MainClass
{
public static int Main(string[] args)
{
// Test if input arguments were supplied:
if(args[0]=="GUI")
new myGUI().show(); //runs an instance of your gui
else
//you know what should go here
}
}
答案 3 :(得分:0)
您可以通过这样做来猜测是否从控制台启动:
CONSOLE_SCREEN_BUFFER_INFO csbi;
GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi);
fConsole = csbi.dwCursorPosition.X | csbi.dwCursorPosition.Y;
这是一个猜测 - 如果您的光标位置不是0,0而不是您在控制台中并且可以作为控制台应用程序工作。否则,去创建你的窗户。
另一种猜测方法是查看流程树并查看启动应用的流程。如果是cmd.exe,则进入控制台模式,否则进入GUI模式。
答案 4 :(得分:0)
将其设为控制台应用程序并将其放入代码中:
void ConsoleWindowVisible(bool show)
{
DWORD dummy;
if
(
!show && // Trying to hide
GetConsoleProcessList(&dummy, 1) == 1 // Have our own console window
)
ShowWindow(GetConsoleWindow, SW_HIDE); // Hide the window
else // Trying to show or use parent console window
ShowWindow(GetConsoleWindow, SW_NORMAL); // Show the window
}
int main(int argc, char** argv)
{
ConsoleWindowVisible(false);
}
干杯。
gor.f.gyolchanyan@gmail.com
答案 5 :(得分:0)
这是Dan Tillett的答案,它非常有效。没有闪烁,没有.com和.exe来欺骗cmd.exe。似乎在.bat文件中完美地输入命令,具有焦点,没有焦点,并且双击GUI应用程序。
这是蜜蜂的膝盖!
这是描述它的网页,但我在这里发布了它,因为如果那个页面在下个月或者从现在开始的2年后变为404,那么我见过的优秀且“最完整”的解决方案将“脱离网格”
#define WINVER 0x0501 // Allow use of features specific to Windows XP or later.
#define _WIN32_WINNT 0x0501
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <io.h>
#include <fcntl.h>
#include <stdio.h>
#pragma comment(lib, "User32.lib")
// Attach output of application to parent console
static BOOL attachOutputToConsole(void) {
HANDLE consoleHandleOut, consoleHandleError;
int fdOut, fdError;
FILE *fpOut, *fpError;
if (AttachConsole(ATTACH_PARENT_PROCESS)) {
//redirect unbuffered STDOUT to the console
consoleHandleOut = GetStdHandle(STD_OUTPUT_HANDLE);
fdOut = _open_osfhandle((intptr_t)consoleHandleOut, _O_TEXT);
fpOut = _fdopen(fdOut, "w" );
*stdout = *fpOut;
setvbuf(stdout, NULL, _IONBF, 0 );
//redirect unbuffered STDERR to the console
consoleHandleError = GetStdHandle(STD_ERROR_HANDLE);
fdError = _open_osfhandle((intptr_t)consoleHandleError, _O_TEXT);
fpError = _fdopen(fdError, "w" );
*stderr = *fpError;
setvbuf(stderr, NULL, _IONBF, 0 );
return TRUE;
}
//Not a console application
return FALSE;
}
//Send the "enter" to the console to release the command prompt on the parent console
static void sendEnterKey(void) {
INPUT ip;
// Set up a generic keyboard event.
ip.type = INPUT_KEYBOARD;
ip.ki.wScan = 0; // hardware scan code for key
ip.ki.time = 0;
ip.ki.dwExtraInfo = 0;
//Send the "Enter" key
ip.ki.wVk = 0x0D; // virtual-key code for the "Enter" key
ip.ki.dwFlags = 0; // 0 for key press
SendInput(1, &ip, sizeof(INPUT));
// Release the "Enter" key
ip.ki.dwFlags = KEYEVENTF_KEYUP; // KEYEVENTF_KEYUP for key release
SendInput(1, &ip, sizeof(INPUT));
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR lpCmdLine, INT nCmdShow) {
int argc = __argc;
char **argv = __argv;
UNREFERENCED_PARAMETER(hInstance);
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
UNREFERENCED_PARAMETER(nCmdShow);
BOOL console;
int i;
//Is the program running as console or GUI application
console = attachOutputToConsole();
if (console) {
//Print to stdout
printf("Program running as console application\n");
for (i = 0; i < argc; i++) {
printf("argv[%d] %s\n", i, argv[i]);
}
//Print to stderr
fprintf(stderr, "Output to stderr\n");
}
else {
MessageBox(NULL, "Program running as windows gui application",
"Windows GUI Application", MB_OK | MB_SETFOREGROUND);
}
//Send "enter" to release application from the console
//This is a hack, but if not used the console doesn't know the application has returned
//"enter" only sent if the console window is in focus
if (console && GetConsoleWindow() == GetForegroundWindow()){
sendEnterKey();
}
return 0;
}