Ver Fonte

1、初步完成子进程的重定向工作;

scbc.sat2 há 5 anos atrás
pai
commit
a0484b6558

+ 8 - 0
RunPython/RunPython.sln

@@ -3,6 +3,8 @@ Microsoft Visual Studio Solution File, Format Version 10.00
 # Visual Studio 2008
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RunPython", "RunPython\RunPython.vcproj", "{92FC4676-AAFC-4568-93EE-849029E5381D}"
 EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test", "test\test.vcproj", "{332DAF3B-C481-4F4F-8628-FBF1095BE4C2}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Win32 = Debug|Win32
@@ -16,6 +18,12 @@ Global
 		{92FC4676-AAFC-4568-93EE-849029E5381D}.DeubgExe|Win32.Build.0 = DeubgExe|Win32
 		{92FC4676-AAFC-4568-93EE-849029E5381D}.Release|Win32.ActiveCfg = Release|Win32
 		{92FC4676-AAFC-4568-93EE-849029E5381D}.Release|Win32.Build.0 = Release|Win32
+		{332DAF3B-C481-4F4F-8628-FBF1095BE4C2}.Debug|Win32.ActiveCfg = Debug|Win32
+		{332DAF3B-C481-4F4F-8628-FBF1095BE4C2}.Debug|Win32.Build.0 = Debug|Win32
+		{332DAF3B-C481-4F4F-8628-FBF1095BE4C2}.DeubgExe|Win32.ActiveCfg = Debug|Win32
+		{332DAF3B-C481-4F4F-8628-FBF1095BE4C2}.DeubgExe|Win32.Build.0 = Debug|Win32
+		{332DAF3B-C481-4F4F-8628-FBF1095BE4C2}.Release|Win32.ActiveCfg = Release|Win32
+		{332DAF3B-C481-4F4F-8628-FBF1095BE4C2}.Release|Win32.Build.0 = Release|Win32
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE

+ 165 - 3
RunPython/RunPython/RunPython.cpp

@@ -32,10 +32,13 @@ int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
 	{
 		// TODO: 在此处为应用程序的行为编写代码。
 		//RunPython("E:\\bin\\ScbcCopyKey\\test.py"); // 加载失败,但改成test2.py后,就能加载成功
-		//RunPython("E:\\bin\\ScbcCopyKey\\test2.py");
+		//RunPython("E:\\bin\\ScbcCopyKey\\ScbcTest.py", NULL);
 		//RunPython("D:\\SAT\\runner\\btc_runner_se\\runner\\output\\ODF_NPI_RT2841\\20191119172310094\\192.168.1.119_5555\\cases\\RT_2841\\ODF_NPI_RT2841\\picture\\22.py", NULL);
+		//Sleep(10000);
+		printf("\n\n\n\n=================================================================\n\n");
+		CallPythonEx("D:\\SAT\\runner\\btc_runner_se\\runner\\output\\ODF_NPI_RT2841\\20191119172310094\\192.168.1.119_5555\\cases\\RT_2841\\ODF_NPI_RT2841\\picture\\22.py", NULL);
+		//CallPythonEx("E:\\bin\\ScbcCopyKey\\ScbcTest.py", NULL);
 		printf("\n\n\n\n=================================================================\n\n");
-		CallPython("D:\\SAT\\runner\\btc_runner_se\\runner\\output\\ODF_NPI_RT2841\\20191119172310094\\192.168.1.119_5555\\cases\\RT_2841\\ODF_NPI_RT2841\\picture\\22.py", NULL);
 	}
 
 	system("pause");
@@ -174,7 +177,7 @@ RUNPYTHON_API int CallPython(LPCTSTR lpScriptFile, LPCTSTR lpCommand)
 
 	// 启动子进程;
 	if( !CreateProcess( 
-		szPython27Exe,			// No module name (use command line)
+		NULL,			// No module name (use command line)
 		szCommandLine,			// Command line
 		NULL,					// Process handle not inheritable
 		NULL,					// Thread handle not inheritable
@@ -197,5 +200,164 @@ RUNPYTHON_API int CallPython(LPCTSTR lpScriptFile, LPCTSTR lpCommand)
 	CloseHandle( pi.hProcess );
 	CloseHandle( pi.hThread );
 
+	return 0;
+}
+
+// 读出stdout  
+BOOL ReadFromPipe(HANDLE hStdOutRead)  
+{  
+	char out_buffer[4096];  
+	DWORD dwRead;    
+	BOOL bSuccess = FALSE;  
+
+	//用WriteFile,从hStdOutRead读出子进程stdout输出的数据,数据结果在out_buffer中,长度为dwRead  
+	bSuccess = ReadFile( hStdOutRead, out_buffer, 4096, &dwRead, NULL);  
+	if ((bSuccess) && (dwRead!=0))  //如果成功了,且长度>0  
+	{  
+		// 此处加入你自己的代码  
+		// 比如:将数据写入文件或显示到窗口中  
+		OutputDebugString(out_buffer);
+	}  
+	return bSuccess;  
+}  
+
+bool GetOutput( HANDLE hStdOutRead, int timeout )
+{
+	if( NULL == hStdOutRead )
+	{
+		return false;
+	}
+
+	char buffer[4096] = {0};
+	DWORD readBytes = 0;
+	while( timeout > 0 )
+	{
+		//对管道数据进行读,但不会删除管道里的数据,如果没有数据,就立即返回
+		if( FALSE == PeekNamedPipe( hStdOutRead, buffer, sizeof(buffer) - 1, &readBytes, 0, NULL ) )
+		{
+			return false;
+		}
+
+		//检测是否读到数据,如果没有数据,继续等待
+		if( 0 == readBytes )
+		{
+			::Sleep(200);
+			timeout -= 200;
+			continue;
+		}
+
+		readBytes = 0;
+		if( ::ReadFile( hStdOutRead, buffer, sizeof(buffer) - 1, &readBytes, NULL) )
+		{
+			OutputDebugString(buffer);
+			return true;
+		}
+		else
+		{
+			return false;
+		}
+	}
+
+	return false;
+}
+
+
+// lpScriptFile:脚本文件;
+// lpCommand:命令行参数;
+RUNPYTHON_API int CallPythonEx(LPCTSTR lpScriptFile, LPCTSTR lpCommand)
+{
+	if ( !lpScriptFile || !PathFileExists(lpScriptFile) )
+	{
+		printf("参数无效\n");
+		return -1;
+	}
+
+	// 获取Python27进程目录;
+	TCHAR szPython27Dir[MAX_PATH] = {0};
+	TCHAR szPython27Exe[MAX_PATH] = {0};
+	if ( !Python27Dir(szPython27Dir, MAX_PATH) )
+	{
+		printf("获取Python27目录失败\n");
+		return -2;
+	}
+	_stprintf_s(szPython27Exe, _T("%spython.exe"), szPython27Dir);
+
+	STARTUPINFO si;
+	::memset(&si, 0 ,sizeof(si));
+	si.cb = sizeof(si);
+	GetStartupInfo(&si); 
+
+	PROCESS_INFORMATION pi;
+	::memset(&pi, 0 ,sizeof(pi));
+
+	TCHAR szCommandLine[MAX_PATH] = {0};
+	if ( lpCommand )
+		_stprintf_s(szCommandLine, _T("python -W ignore %s %s"), lpScriptFile, lpCommand);
+	else
+		_stprintf_s(szCommandLine, _T("python -W ignore %s"), lpScriptFile);
+
+	SECURITY_ATTRIBUTES   sa;   
+	sa.bInheritHandle = TRUE;   
+	sa.lpSecurityDescriptor = NULL;   
+	sa.nLength = sizeof(sa);
+
+	// 创建stdout的管道;
+	HANDLE  hStdOutRead, hStdOutWrite;     
+	if ( !CreatePipe(&hStdOutRead, &hStdOutWrite, &sa, 0) )
+	{
+		printf("创建stdout管道失败\n");
+		return -3;
+	}
+
+	// 创建stderr的管道,由于stderr一般就是stdout,直接复制句柄;
+	HANDLE  hStdErrWrite;     
+	if ( !DuplicateHandle(GetCurrentProcess(), hStdOutWrite, GetCurrentProcess(), &hStdErrWrite, 0, TRUE, DUPLICATE_SAME_ACCESS) )
+	{
+		printf("创建stderr管道失败\n");
+		return -3;
+	}
+
+	si.dwFlags |= STARTF_USESTDHANDLES;  
+	// 将子进程的stdout输出到句柄hStdOutWrite;
+	si.hStdOutput = hStdOutWrite;
+	// 将子进程的stderr输出到句柄hStdErrWrite;
+	si.hStdError = hStdErrWrite;
+
+	// 启动子进程;
+	if( !CreateProcess( 
+		NULL,			// No module name (use command line)
+		szCommandLine,			// Command line
+		NULL,					// Process handle not inheritable
+		NULL,					// Thread handle not inheritable
+		TRUE,					// 如果不设置为TRUE,重定向无效;
+		0,						// No creation flags
+		NULL,					// Use parent's environment block
+		NULL,					// Use parent's starting directory 
+		&si,					// Pointer to STARTUPINFO structure
+		&pi )					// Pointer to PROCESS_INFORMATION structure
+		) 
+	{
+		printf( "CreateProcess failed (%d).\n", GetLastError() );
+		return -3;
+	}
+
+#ifdef _DEBUG
+	DWORD process_exit_code = 0;
+	while (GetExitCodeProcess(pi.hProcess, &process_exit_code))
+	{
+		// 读取stdout、stderr;
+		GetOutput(hStdOutRead, 3000);
+		if ( process_exit_code != STILL_ACTIVE )
+			break;
+	}
+#endif
+
+	// Wait until child process exits.
+	WaitForSingleObject( pi.hProcess, INFINITE );
+
+	// Close process and thread handles. 
+	CloseHandle( pi.hProcess );
+	CloseHandle( pi.hThread );
+
 	return 0;
 }

+ 2 - 0
RunPython/RunPython/RunPython.h

@@ -23,3 +23,5 @@ extern RUNPYTHON_API int nRunPython;
 RUNPYTHON_API int RunPython(LPCTSTR lpScriptFile, LPCTSTR lpExtraSentence);
 // 调用Python.exe来运行脚本;
 RUNPYTHON_API int CallPython(LPCTSTR lpScriptFile, LPCTSTR lpCommand);
+// 调用Python.exe来运行脚本,同时重定向输出流;
+RUNPYTHON_API int CallPythonEx(LPCTSTR lpScriptFile, LPCTSTR lpCommand);