pyinstaller打包的exe太大?你需要站在巨人的肩膀上-VC++纔是王道

本部分主要實現的是 在python的程序啓動的時候(嚴格說應該是啓動後)隱藏、關閉命令行窗口。

VS版本:VS2017社區版

OS版本:win7-64位

我的參考文章-站在巨人的肩膀上:

本人在查找方法的時候參考了以下3篇文章,但是遇到了很多奇怪的問題,主要是因爲沒用過createProcess這個函數,盲目copy網上同行的代碼去嘗試,沒有仔細去看它的定義。最後仔細閱讀了微軟的官方文檔 (https://docs.microsoft.com/zh-cn/windows/win32/procthread/creating-processes )才理解3篇文章中的差異,解決了自己的問題。微軟依舊是巨人,看源文檔纔是王道。

https://www.cnblogs.com/King2019Blog/p/11296711.html

https://www.cnblogs.com/liuweilinlin/archive/2012/08/20/2647168.html

https://blog.csdn.net/yuyan987/article/details/78644922

下圖是效果圖,圖後面是源代碼。大家可以參考。

 

// call_python_test4.cpp : 此文件包含 "main" 函數。程序執行將在此處開始並結束。
// 此文件測試CreateProcess函數調用外部exe程序。一般情況會先打開cmd窗口,然後通過cmd控制檯打開外部exe程序。
// 經過測試,可以做到啓動外部程序後,瞬間關閉命令行窗口

#include "pch.h"
#include <iostream>
#include "windows.h"
#include <WinBase.h>
#include <minwinbase.h>
#include <string.h>
#include <tchar.h>
#include <assert.h>

void createProcess_nocmdwindow();
int main()
{
	createProcess_nocmdwindow();
	return 0;
}

/*OK*/
void createProcess_nocmdwindow()
{
	STARTUPINFO   StartupInfo;//創建進程所需的信息結構變量   
	PROCESS_INFORMATION   ProcessInfo;
	GetStartupInfo(&StartupInfo);
	StartupInfo.lpReserved = NULL;
	StartupInfo.lpDesktop = NULL;
	StartupInfo.lpTitle = NULL;
	StartupInfo.dwX = 0;
	StartupInfo.dwY = 0;
	StartupInfo.dwXSize = 0;
	StartupInfo.dwYSize = 0;
	StartupInfo.dwXCountChars = 500;
	StartupInfo.dwYCountChars = 500;
	StartupInfo.dwFlags = STARTF_USESHOWWINDOW;
	StartupInfo.wShowWindow = SW_HIDE;
	//說明進程將以隱藏的方式在後臺執行    
	StartupInfo.cbReserved2 = 0;
	StartupInfo.lpReserved2 = NULL;
	StartupInfo.hStdInput = stdin;
	StartupInfo.hStdOutput = stdout;
	StartupInfo.hStdError = stderr;

	BOOL   bRet;
    TCHAR appName[] = _T("E:\\study_python\\genera_sine_wav_file\\release\\release_win7\\general_2ch_sinwav_file.v1.300.exe");//OK no cmd window
	//TCHAR szCmdline[] = _T("D:\\Python37\\python.exe  E:\\general_2ch_sinwav_file.v1.300.py"); //this str is tesed, OK
	//TCHAR szCmdline[] = _T("D:\\Python37\\python.exe  D:\\Python37\\general_2ch_sinwav_file.v1.300.pyw"); //this str is tesed, OK
	//TCHAR szCmdline[] = _T("\"D:\\Python37\\python.exe\"  D:\\Python37\\general_2ch_sinwav_file.v1.300.pyw"); //this str is tesed, OK

	/* MS參考code:https://docs.microsoft.com/zh-cn/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessw */
	//LPTSTR szCmdlineline[] = _tcsdup(TEXT("\"C:\\Program Files\\MyApp\" -L -S"));

	bRet = CreateProcess(NULL, szCmdline, NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &StartupInfo, &ProcessInfo);

	WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
	CloseHandle(ProcessInfo.hProcess);
	CloseHandle(ProcessInfo.hThread);
}

以下部分是個人測試code,請忽略。----不要被下面混亂的代碼影響了你的判斷

// call_python_test4.cpp : 此文件包含 "main" 函數。程序執行將在此處開始並結束。
// 此文件測試CreateProcess函數調用外部exe程序。一般情況會先打開cmd窗口,然後通過cmd控制檯打開外部exe程序。
// 經過測試,可以做到啓動外部程序後,瞬間關閉命令行窗口

#include "pch.h"
#include <iostream>
#include "windows.h"
#include <WinBase.h>
#include <minwinbase.h>
#include <string.h>
#include <tchar.h>
#include <assert.h>

//#pragma comment(linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"")
int method1_test();
int method2_test();
void createProcess();
void createProcess_nocmdwindow();
int main()
{
	//return method1_test();
	//return method2_test();	
	createProcess_nocmdwindow();
	return 0;
	createProcess();
	return 0;
}

/*OK*/
void createProcess()
{
	STARTUPINFO   StartupInfo;//創建進程所需的信息結構變量   
	PROCESS_INFORMATION   ProcessInfo;
	GetStartupInfo(&StartupInfo);
	StartupInfo.lpReserved = NULL;
	StartupInfo.lpDesktop = NULL;
	StartupInfo.lpTitle = NULL;
	StartupInfo.dwX = 0;
	StartupInfo.dwY = 0;
	StartupInfo.dwXSize = 0;
	StartupInfo.dwYSize = 0;
	StartupInfo.dwXCountChars = 500;
	StartupInfo.dwYCountChars = 500;
	StartupInfo.dwFlags = STARTF_USESHOWWINDOW;
	StartupInfo.wShowWindow = SW_HIDE;
	//說明進程將以隱藏的方式在後臺執行    
	StartupInfo.cbReserved2 = 0;
	StartupInfo.lpReserved2 = NULL;
	StartupInfo.hStdInput = stdin;
	StartupInfo.hStdOutput = stdout;
	StartupInfo.hStdError = stderr;

	BOOL   bRet;
	//char *appName = (char *)malloc(256);
	//appName = "E:\\work\\project0\\spider\\bin\\Release\\spider1.exe";
	
/*method 1: successfull*/
	TCHAR appName[] = _T("E:\\study_python\\genera_sine_wav_file\\release\\release_win7\\general_2ch_sinwav_file.v1.300.exe");//OK no cmd window
	bRet = CreateProcess(appName, NULL, NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &StartupInfo, &ProcessInfo);

	//TCHAR appName[] = _T("E:\\createProcess_test_1.exe"); // OK no cmd window
	//bRet = CreateProcess(appName, NULL, NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &StartupInfo, &ProcessInfo); //ok

/*method 2: fail, can not run*/
	//TCHAR appName[] = _T("D:\\Python37\\python.exe  D:\\Python37\\general_2ch_sinwav_file.v1.300.py");//error, can not run
	//TCHAR appName[] = _T("\"D:\\Python37\\python.exe\"  D:\\Python37\\general_2ch_sinwav_file.v1.300.pyw");//error, can not run
	//bRet = CreateProcess(appName, NULL, NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &StartupInfo, &ProcessInfo);

/*method 3: error*/
	/*TCHAR appName[] = _T("D:\\Python37\\python.exe");
	TCHAR szCmdline[] = _T("D:\\Python37\\general_2ch_sinwav_file.v1.300.pyw");
	bRet = CreateProcess(appName, szCmdline, NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &StartupInfo, &ProcessInfo);*/
	
/*method 4: successfull*/
	/*TCHAR szCmdline[] = _T("\"D:\\Python37\\python.exe\"  D:\\Python37\\general_2ch_sinwav_file.v1.300.pyw");
	bRet = CreateProcess(NULL, szCmdline, NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &StartupInfo, &ProcessInfo);*/

	WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
	CloseHandle(ProcessInfo.hProcess);
	CloseHandle(ProcessInfo.hThread);
}
/*OK*/
void createProcess_nocmdwindow()
{
	STARTUPINFO   StartupInfo;//創建進程所需的信息結構變量   
	PROCESS_INFORMATION   ProcessInfo;
	GetStartupInfo(&StartupInfo);
	StartupInfo.lpReserved = NULL;
	StartupInfo.lpDesktop = NULL;
	StartupInfo.lpTitle = NULL;
	StartupInfo.dwX = 0;
	StartupInfo.dwY = 0;
	StartupInfo.dwXSize = 0;
	StartupInfo.dwYSize = 0;
	StartupInfo.dwXCountChars = 500;
	StartupInfo.dwYCountChars = 500;
	StartupInfo.dwFlags = STARTF_USESHOWWINDOW;
	StartupInfo.wShowWindow = SW_HIDE;
	//說明進程將以隱藏的方式在後臺執行    
	StartupInfo.cbReserved2 = 0;
	StartupInfo.lpReserved2 = NULL;
	StartupInfo.hStdInput = stdin;
	StartupInfo.hStdOutput = stdout;
	StartupInfo.hStdError = stderr;

	BOOL   bRet;
	TCHAR szCmdline[] = _T("D:\\Python37\\python.exe  E:\\general_2ch_sinwav_file.v1.300.py"); //this str is tesed, OK
	//TCHAR szCmdline[] = _T("D:\\Python37\\python.exe  D:\\Python37\\general_2ch_sinwav_file.v1.300.pyw"); //this str is tesed, OK
	//TCHAR szCmdline[] = _T("\"D:\\Python37\\python.exe\"  D:\\Python37\\general_2ch_sinwav_file.v1.300.pyw"); //this str is tesed, OK
	
	/* MS參考code:https://docs.microsoft.com/zh-cn/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessw */
	//LPTSTR szCmdlineline[] = _tcsdup(TEXT("\"C:\\Program Files\\MyApp\" -L -S"));

	bRet = CreateProcess(NULL, szCmdline, NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &StartupInfo, &ProcessInfo);

	WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
	CloseHandle(ProcessInfo.hProcess);
	CloseHandle(ProcessInfo.hThread);
}

void ExecDOSCMD(const char * szCommand)
{
	STARTUPINFO si;
	memset(&si, 0, sizeof(STARTUPINFO));
	//進程信息     
	PROCESS_INFORMATION pi;
	si.cb = sizeof(STARTUPINFO);
	//   取得當前進程的StartupInfo,並根據當前進程進行修改   
	GetStartupInfo(&si);
	si.wShowWindow = SW_SHOW;
	si.dwFlags = STARTF_USESHOWWINDOW;
	si.wShowWindow = SW_HIDE;
	char lpAppName[4096] = "";//此處不加cmd /k
	strcat_s(lpAppName, 4096, szCommand);
	CreateProcess((LPWSTR)(lpAppName), NULL, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi);
}
/*fail*/
int method1_test()
{
	//ExecDOSCMD(("calc.exe"));
	//ExecDOSCMD(("E:\\study_python\\genera_sine_wav_file\\release\\release_win7\\general_2ch_sinwav_file.v1.300.exe"));
	ExecDOSCMD(("E:\\call_python_test3.exe"));
	return 0;
}

/*test fail*/
int method2_test()
{
	HDESK hDesk = CreateDesktop(_T("MyDesk"), NULL, NULL, 0, GENERIC_ALL, NULL);
	assert(hDesk);
	STARTUPINFO si = { sizeof(si) };
	si.lpDesktop = NULL;
	si.dwFlags = STARTF_USESHOWWINDOW;
	si.wShowWindow = SW_HIDE;
	PROCESS_INFORMATION pi = { 0 };

	TCHAR szCmdline[MAX_PATH] = _T("E:\\call_python_test3.exe");
	if (CreateProcess(NULL, szCmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
	{
		CloseHandle(pi.hThread);
		CloseHandle(pi.hProcess);
	}

	return 0;
}

 

發佈了28 篇原創文章 · 獲贊 12 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章