• <转>Running console applications silently


    Introduction

    Arrrgh! So you need to run your console app via a primary application, well ye've come to the right place. This article is intended for those who need to run one of those pesky little console applications without the console window popping up over your main app or worse popping up when calling it from a service.

    So now matey lets dive into it and see how to avoid the console windows from sinking our application. Prepare the app for silent running.

    Walking the Plank

    Ok! That's enough of the pirate stuff. On with the show..

    You have probably searched the web and have seen many developers show examples of how to spawn applications using the CreateProcessfunction. Well I shall do the same thing but with a twist. I will do it in such a way that the application that you would like to spawn does not show up when run.

    There are several caveats to this process and many gotcha's. The main one is that if this program you wish to run is interactive, that is requires input from the user outside of what can be passed in through the command line, then blindly using this code will cause your program to hang. To recap! How can you input information into a program if you can't see the window. Ok! Think you get the point.

    There are ways of doing this but they will not be covered in this article.

    Running Silent

    The trick to running a console window silent is burried in the STARTUPINFO structure that we will populate then pass into the CreateProcess function. STARTUPINFO specifies the main window properties. There are many items in the STARTUPINFOstructure that we just don't care about. The ones that are of interest to us are the

    • DWORD cb
    • DWORD dwFlags
    • WORD wShowWindow

    First the STARTUPINFOis instantiated

      STARTUPINFO StartupInfo;

    then the memory is cleared for the length of the structure.

      memset(&StartupInfo, 0, sizeof(StartupInfo));

    or

      ::ZeroMemory(&StartupInfo, sizeof(StartupInfo));  

    If this is not done our data within our STARTUPINFOobject could be corrupt rendering it useless and possible crashing the application.

    Next we will fill our structure with the relevant code that will tell our console window to start up without showing itself.

      // set the size of the structure
      StartupInfo.cb = sizeof(STARTUPINFO);
      // tell the application that we are setting the window display 
      // information within this structure
      StartupInfo.dwFlags = STARTF_USESHOWWINDOW;
      // set the window display to HIDE
      StartupInfo.wShowWindow = SW_HIDE;

    Well that's not much of a trick but remember unless you specify the dwFlags to the flag STARTF_USESHOWWINDOW the setting in wShowWindowwill not be recognized and your window will not be hidden.

    Davy Jones' Locker

    Well this is where I will leave you to it.

    To test this use the function source below and paste it into your application or Download the project file above and test it out. The application will open the IPConfig.exe application in a hidden window, pipe the text to a file and then display the contents of that file in the main application window.

    DWORD RunSilent(char* strFunct, char* strstrParams)
    {
    	STARTUPINFO StartupInfo;
    	PROCESS_INFORMATION ProcessInfo;
    	char Args[4096];
    	char *pEnvCMD = NULL;
    	char *pDefaultCMD = "CMD.EXE";
    	ULONG rc;
    	
    	memset(&StartupInfo, 0, sizeof(StartupInfo));
    	StartupInfo.cb = sizeof(STARTUPINFO);
    	StartupInfo.dwFlags = STARTF_USESHOWWINDOW;
    	StartupInfo.wShowWindow = SW_HIDE;
    
    	Args[0] = 0;
    
    	pEnvCMD = getenv("COMSPEC");
    
    	if(pEnvCMD){
    		
    		strcpy(Args, pEnvCMD);
    	}
    	else{
    		strcpy(Args, pDefaultCMD);
    	}
    
    	// "/c" option - Do the command then terminate the command window
    	strcat(Args, " /c "); 
    	//the application you would like to run from the command window
    	strcat(Args, strFunct);  
    	strcat(Args, " "); 
    	//the parameters passed to the application being run from the command window.
    	strcat(Args, strstrParams); 
    
    	if (!CreateProcess( NULL, Args, NULL, NULL, FALSE,
    		CREATE_NEW_CONSOLE, 
    		NULL, 
    		NULL,
    		&StartupInfo,
    		&ProcessInfo))
    	{
    		return GetLastError();		
    	}
    
    	WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
    	if(!GetExitCodeProcess(ProcessInfo.hProcess, &rc))
    		rc = 0;
    
    	CloseHandle(ProcessInfo.hThread);
    	CloseHandle(ProcessInfo.hProcess);
    
    	return rc;
    	
    }

    License

    This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

    A list of licenses authors might use can be found here

    本人新博客网址为:http://www.hizds.com
    本博客注有“转”字样的为转载文章,其余为本人原创文章,转载请务必注明出处或保存此段。c++/lua/windows逆向交流群:69148232
  • 相关阅读:
    autocad.net 利用linq获取矩形框内的块参照
    autocad.net 只在图纸空间遍历块的方法
    autocad.net中判断当前被激活的空间
    计划搞一个程序来应对客户的修改标记问题
    条件编译解决AutoCAD多版本问题
    初学者往往不知道怎么获得断点,请看下面的链接应该可以解决你的问题!
    2014年3月9日正式入住博客园
    学习:SpringCloud(一)
    简单使用:SpringBoot整合Redis
    Redis 使用过程中遇到的具体问题
  • 原文地址:https://www.cnblogs.com/zhangdongsheng/p/2569831.html
Copyright © 2020-2023  润新知