123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573 |
- // RunPython.cpp : 定义 DLL 应用程序的导出函数。
- //
- #include "stdafx.h"
- #include "RunPython.h"
- #include "ScriptExecutor.h"
- #ifdef _DEBUG
- #define new DEBUG_NEW
- #endif
- // 唯一的应用程序对象
- CWinApp theApp;
- using namespace std;
- BOOL Python27Dir(LPTSTR lpPython27Dir, int nBufferLen);
- int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
- {
- int nRetCode = 0;
- // 初始化 MFC 并在失败时显示错误
- if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
- {
- // TODO: 更改错误代码以符合您的需要
- _tprintf(_T("错误: MFC 初始化失败\n"));
- nRetCode = 1;
- }
- else
- {
- // TODO: 在此处为应用程序的行为编写代码。
- CScriptExecutor excutor;
- excutor.InitScript("E:\\bin\\ScbcCopyKey\\ScbcTest.py",
- "D:\\SAT\\log.txt",
- "",
- EMBEDDED);
- excutor.StartScript();
- Sleep(500);
- while( !excutor.IsScriptOver() )
- Sleep(100);
- }
- system("pause");
- return nRetCode;
- }
- void CatchPythonException()
- {
- if ( !Py_IsInitialized() )
- {
- printf("未初始化Python环境\n");
- return;
- }
- if ( !PyErr_Occurred() )
- {
- printf("没有异常产生\n");
- return;
- }
- // 捕获异常;
- const char *pszErrMsg = NULL;
- TCHAR *pszTraceback = NULL;
- PyObject *pPyType = NULL;
- PyObject *pPyValue = NULL;
- PyObject *pPyTraceback = NULL;
- // 非控制台,使用PyErr_Fetch捕获异常;
- PyErr_Fetch(&pPyType, &pPyValue, &pPyTraceback);
- PyErr_NormalizeException(&pPyType, &pPyValue, &pPyTraceback); // 可有可无,不影响获取异常;
- if ( pPyValue )
- {
- PyObject *pPyStr = PyObject_Str(pPyValue);
- if ( PyString_Check(pPyStr) )
- {
- pszErrMsg = PyString_AsString(pPyStr);
- if ( pszErrMsg )
- printf("Error Info=>%s\n",pszErrMsg);
- if ( pPyTraceback )
- {
- PyObject *pPyTraceModule = PyImport_ImportModule("traceback");
- if ( !pPyTraceModule )
- {
- printf("导入traceback模块失败\n");
- return;
- }
- #if 1
- PyObject *pPyModuleDict = PyModule_GetDict(pPyTraceModule);
- if ( pPyModuleDict )
- {
- PyObject *pPyFunc = PyDict_GetItemString(pPyModuleDict, "format_exception");
- if ( !pPyFunc || !PyCallable_Check(pPyFunc) )
- {
- printf("加载format_exception失败\n");
- return;
- }
- PyObject *pErroList = PyObject_CallFunctionObjArgs(pPyFunc, pPyType, pPyValue, pPyTraceback, NULL);
- if ( pErroList )
- {
- int nSize = PyList_Size(pErroList);
- for ( int i = 0; i < nSize; i++ )
- {
- pszErrMsg = PyString_AsString(PyList_GetItem(pErroList, i));
- printf("%s", pszErrMsg);
- }
- }
- }
- Py_XDECREF(pPyTraceModule);
- #else // 不细分Item;
- PyObject *pPyFunc = PyObject_GetAttrString(pPyTraceModule, "format_exception");
- if ( !pPyFunc || !PyCallable_Check(pPyFunc) )
- {
- printf("加载format_exception失败\n");
- return;
- }
- PyObject *pPyResult = PyObject_CallFunctionObjArgs(pPyFunc, pPyType, pPyValue, pPyTraceback, NULL);
- pPyStr = PyObject_Str(pPyResult);
- pszErrMsg = PyString_AsString(pPyStr);
- if ( pszErrMsg )
- printf("%s\n",pszErrMsg);
- Py_DECREF(pPyResult);
- Py_XDECREF(pPyTraceModule);
- #endif
- }
- }
- }
- }
- // 从注册表获取 Python27路径;
- BOOL Python27Dir(LPTSTR lpPython27Dir, int nBufferLen)
- {
- HKEY hKey;
- int ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\WOW6432Node\\Python\\PythonCore\\2.7\\InstallPath"), 0, KEY_QUERY_VALUE, &hKey);
- if (ret != ERROR_SUCCESS)
- return FALSE;
- //读取KEY
- DWORD dwType = REG_SZ; //数据类型
- DWORD cbData = nBufferLen;
- ret = RegQueryValueEx(hKey, _T(""), NULL, &dwType, (LPBYTE)lpPython27Dir, &cbData);
- if (ret != ERROR_SUCCESS)
- {
- RegCloseKey(hKey);
- return FALSE;
- }
- RegCloseKey(hKey);
- return TRUE;
- }
- // 运行Python脚本;
- RUNPYTHON_API int RunPython(LPCTSTR lpScriptFile, LPCTSTR lpExtraSentence)
- {
- // 参数有效性判断;
- if ( !lpScriptFile || !PathFileExists(lpScriptFile) )
- return -1;
- // 初始化Python环境;
- Py_Initialize();
- if ( !Py_IsInitialized() )
- return -2;
- // 解析脚本路径和脚本名称;
- std::string scriptdir;
- TCHAR szDrive[_MAX_DRIVE] = { 0 };
- TCHAR szDir[_MAX_DIR] = { 0 };
- TCHAR szExt[_MAX_EXT] = { 0 };
- TCHAR szFilename[_MAX_FNAME] = { 0 };
- TCHAR szScriptDir[MAX_PATH] = { 0 };
- _tsplitpath_s(lpScriptFile, szDrive, szDir, szFilename, szExt);
- _stprintf_s(szScriptDir, _T("%s%s"), szDrive, szDir);
- // 缓存一份路径;
- scriptdir = szScriptDir;
- // 将'\'转换成'/', Python才设置运行目录成功;
- int len = _tcslen(szScriptDir);
- for ( int i = 0; i < len; i++ )
- {
- if ( szScriptDir[i] == '\\' )
- szScriptDir[i] = '/';
- }
- //szScriptDir[len-1] = '\0';
- TCHAR szExecuteDir[MAX_PATH] = { 0 };
- _stprintf_s(szExecuteDir, _T("sys.path.append(\"%s\")"), szScriptDir);
- // 添加系统模块,并指定当前脚本路径为运行路径;
- PyRun_SimpleString("import sys");
- PyRun_SimpleString(szExecuteDir);
- // 运行额外的语句,一般用于传递命令行参数;
- if ( lpExtraSentence )
- PyRun_SimpleString(lpExtraSentence);
- // 注意:脚本名称尽量不要与系统目录其他py文件相同;
- // 导入脚本,以脚本名称为模块名加载;
- PyObject *pModuleObj = PyImport_ImportModule(szFilename);
- if ( !pModuleObj )
- {
- printf("=>加载模块失败\n");
- Py_Finalize();
- return -3;
- }
-
- // 获取脚本的主函数名称(规定所有脚本的主函数名为main)
- // 加载函数:注意,如果目录下有同名的脚本文件,可能会加载失败;
- PyObject *pFunction = PyObject_GetAttrString(pModuleObj, "main");
- if ( !pFunction || !PyCallable_Check(pFunction) )
- {
- printf("=>加载函数失败\n");
- Py_Finalize();
- return -4;
- }
-
- // 执行main函数;
- PyObject *pResult = PyObject_CallObject(pFunction, NULL);
- if ( !pResult )
- {
- printf("=>运行函数失败\n");
- Py_Finalize();
- return -5;
- }
- Py_Finalize();
- return 0;
- }
- RUNPYTHON_API int RunPythonEx(LPCTSTR lpScriptFile, LPCTSTR lpExtraSentence)
- {
- // 参数有效性判断;
- if ( !lpScriptFile || !PathFileExists(lpScriptFile) )
- return -1;
- // 初始化Python环境;
- Py_Initialize();
- if ( !Py_IsInitialized() )
- return -2;
- // 解析脚本路径和脚本名称;
- std::string scriptdir;
- TCHAR szDrive[_MAX_DRIVE] = { 0 };
- TCHAR szDir[_MAX_DIR] = { 0 };
- TCHAR szExt[_MAX_EXT] = { 0 };
- TCHAR szFilename[_MAX_FNAME] = { 0 };
- TCHAR szScriptDir[MAX_PATH] = { 0 };
- _tsplitpath_s(lpScriptFile, szDrive, szDir, szFilename, szExt);
- _stprintf_s(szScriptDir, _T("%s%s"), szDrive, szDir);
- // 缓存一份路径;
- scriptdir = szScriptDir;
- // 将'\'转换成'/', Python才设置运行目录成功;
- int len = _tcslen(szScriptDir);
- for ( int i = 0; i < len; i++ )
- {
- if ( szScriptDir[i] == '\\' )
- szScriptDir[i] = '/';
- }
- //szScriptDir[len-1] = '\0';
- //////////////////////////////////////////////////////////////////////////
- TCHAR szExecuteDir[MAX_PATH] = { 0 };
- _stprintf_s(szExecuteDir, _T("sys.path.append(\"%s\")"), szScriptDir);
- // 添加系统模块,并指定当前脚本路径为运行路径;
- PyRun_SimpleString("import sys");
- PyRun_SimpleString(szExecuteDir);
- // 运行额外的语句,一般用于传递命令行参数;
- if ( lpExtraSentence )
- PyRun_SimpleString(lpExtraSentence);
- /*
- PyObject* main = PyModule_GetDict(PyImport_AddModule("__main__"));
- PyObject *res = PyRun_String(由文件内容, Py_file_input, main, main);
- */
- // 注意:脚本名称尽量不要与系统目录其他py文件相同;
- // 导入脚本,以脚本名称为模块名加载;
- PyObject *pModuleObj = PyImport_ImportModule(szFilename);
- if ( !pModuleObj )
- {
- printf("=>加载模块失败\n");
- Py_Finalize();
- return -3;
- }
- // 获取脚本的主函数名称(规定所有脚本的主函数名为main)
- // 加载函数:注意,如果目录下有同名的脚本文件,可能会加载失败;
- PyObject *pFunction = PyObject_GetAttrString(pModuleObj, "main");
- if ( !pFunction || !PyCallable_Check(pFunction) )
- {
- printf("=>加载函数失败\n");
- Py_Finalize();
- return -4;
- }
- // 执行main函数;
- //PyObject *pResult = PyObject_CallFunctionObjArgs(pFunction, pType, pValue, pTraceback, NULL);
- PyObject *pResult = PyObject_CallObject(pFunction, NULL);
- if ( !pResult )
- {
- printf("=>运行函数失败\n");
- #if 0
- // 捕获异常;
- const char *pszErrMsg = NULL;
- TCHAR *pszTraceback = NULL;
-
- PyObject *pType = NULL;
- PyObject *pValue = NULL;
- PyObject *pTraceback = NULL;
- // 非控制台,使用PyErr_Fetch捕获异常;
- PyErr_Fetch(&pType, &pValue, &pTraceback);
- PyErr_NormalizeException(&pType,&pValue,&pTraceback);
- if ( pValue )
- {
- PyObject *pStr = PyObject_Str(pValue);
- if ( pStr )
- {
- //pszErrMsg = PyUnicode_AsUTF8String(pStr);
- int line, offset;
- TCHAR *pszMsg, *pszFile, *pszText;
- int res = PyArg_ParseTuple(pValue, "s(siis)", &pszMsg, &pszFile, &line, &offset, &pszText);
- //Q_UNUSED();
- PyObject *line_no = PyObject_GetAttrString(pValue, "lineno");
- PyObject *line_no_str = PyObject_Str(line_no);
- PyObject *line_no_unicode = PyUnicode_AsEncodedString(line_no_str, "utf-8", "Error");
- char *actual_line_no = PyBytes_AsString(line_no_unicode);
- printf("actual_line_no --%s\n", actual_line_no);
- }
- }
- #else
- CatchPythonException();
- #endif
- PyErr_Print();
- Py_Finalize();
- return -5;
- }
-
- Py_DECREF(pResult);
- Py_Finalize();
- return 0;
- }
- // lpScriptFile:脚本文件;
- // lpCommand:命令行参数;
- RUNPYTHON_API int CallPython(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);
- 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);
- // 启动子进程;
- if( !CreateProcess(
- NULL, // No module name (use command line)
- szCommandLine, // Command line
- NULL, // Process handle not inheritable
- NULL, // Thread handle not inheritable
- FALSE, // Set handle inheritance to 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;
- }
- // Wait until child process exits.
- WaitForSingleObject( pi.hProcess, INFINITE );
- // Close process and thread handles.
- CloseHandle( pi.hProcess );
- CloseHandle( pi.hThread );
- return 0;
- }
- // 读出stdout
- BOOL ReadFromPipe(HANDLE hStdOutRead)
- {
- char out_buffer[BUFSIZE] = {0};
- DWORD dwRead;
- BOOL bSuccess = FALSE;
- //用WriteFile,从hStdOutRead读出子进程stdout输出的数据,数据结果在out_buffer中,长度为dwRead
- bSuccess = ReadFile( hStdOutRead, out_buffer, BUFSIZE, &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);
- ReadFromPipe(hStdOutRead);
- 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;
- }
|