怎样用createprocess调用一个外部exe文件,并且能处理发给它的消息并使主程序流程等待它执行的结束?

dave75 2001-08-03 03:21:04
如题
...全文
901 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
skt985 2002-01-11
  • 打赏
  • 举报
回复
33820关注!
gameboy999 2001-12-27
  • 打赏
  • 举报
回复
follow me
use this fuction to run your application

if you wanna send some messages to the child process,
use this function in a thread.

int RunExe(const char * ProcessName,char * CommandLine)
{
STARTUPINFO si;
PROCESS_INFORMATION pi;

ZeroMemory( &si, sizeof(si) );
si.cb = sizeof(si);
ZeroMemory( &pi, sizeof(pi) );

// Start the child process.
if( !CreateProcess( ProcessName, // No module name (use command line).
CommandLine, // Command line.
NULL, // Process handle not inheritable.
NULL, // Thread handle not inheritable.
FALSE, // Set handle inheritance to FALSE.
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.
)
{
return 0;
}

// Wait until child process exits.
WaitForSingleObject( pi.hProcess, INFINITE );

// Close process and thread handles.
CloseHandle( pi.hProcess );
CloseHandle( pi.hThread );
return 1;

}
xiaoxiaohan 2001-12-27
  • 打赏
  • 举报
回复
5. 如何正确使用CreateProcess函数?
(1) LPCTSTR lpApplicationName
想运行的可执行文件的名字的字符串(应含扩展名)。如果找不到该文件,CreateProcess运行失败。应该设为NULL。
(2) LPTSTR lpCommandLine
传递给新进程的命令行字符串,应当为非常量字符串的地址。可以设定一个完整的命令行,如果第一个标记没有扩展名,CreateProcess将其假设为.exe。如果找不到该文件,CreateProcess按环境设置目录搜索运行。
(3) LPSECURITY_ATTRIBUTES
设定进程对象的安全性。可以为这些参数传递NULL,在这种情况下,系统为这些对象赋予默认安全性描述符。 (不明白)
(4) LPSECURITY_ATTRIBUTES lpThreadAttributes
设定线程对象的安全性。可以为这些参数传递NULL,在这种情况下,系统为这些对象赋予默认安全性描述符。 (不明白)
(5) BOOL bInheritHandles
决定子进程对父进程继承性,一般设为FALSE。
(6) DWORD dwCreationFlags
用于标识标志,以便用于规定如何来创建新进程。
标志 说明
EBUG_PROCESS 父进程想要调试子进程和子进程将来生成的任何进程。当任何子进程(被调试进程)中发生某些事件时,将情况通知父进程。 (不明白)
DEBUG_ONLY_THIS_PROCESS 与DEBUG_PROCESS标志相类似,调试程序只被告知紧靠父进程的子进程中发生的特定事件。 (不明白)
CREATE_SUSPENDED 新进程被创建,但是,它的主线程则被挂起。
DETACHED_PROCESS 阻止基于CUI的进程对它的父进程的控制台窗口的访问,并告诉系统将它的输出发送到新的控制台窗口。
CREATE_NEW_CONSOLE 为新进程创建一个新控制台窗口。如果同时设定CREATE_NEW_CONSOLE和DETACHED_PROCESS标志,就会产生一个错误。
CREATE_NO_WINDOW 不为应用程序创建任何控制台窗口。
CREATE_NEW_PROCESS_GROUP 修改用户在按下Ctrl+C或Ctrl+Break键时得到通知的进程列表。
CREATE_DEFAULT_ERROR_MODE 不继承父进程使用的错误模式。
CREATE_SEPARATE_WOW_VDM 只能当你在Windows2000上运行16位Windows应用程序时使用。告诉系统创建一个单独的DOS虚拟机(VDM),并且在该VDM中运行16位Windows应用程序。 (不明白)
CREATE_SHARED_WOW_VDM 只能当你在Windows2000上运行16位Windows应用程序时使用。在系统的共享VDM中运行16位Windows应用程序。 (不明白)
CREATE_UNICODE_ENVIRONMENT 告诉系统,子进程的环境块应该包含Unicode字符。按照默认设置,进程的环境块包含的是ANSI字符串。
CREATE_FORCEDOS 强制系统运行嵌入16位OS/2应用程序的MOS-DOS应用程序。
CREATE_BREAKAWAY_FROM_JOB 使作业中的进程生成一个与作业相关联的新进程 (不明白)。
IDLE_PRIORITY_CLASSBELOW_NORMAL_PRIORITY_CLASSNORMAL_PRIORITY_CLASSABOVE_NORMAL_PRIORITY_CLASSHIGH_PRIORITY_CLASSREALTIME_PRIORITY_CLASS 空闲低于正常(Windows2000)正常高于正常(Windows2000)高实时
对于大多数应用程序来说不应该设定优先级类。
(7) LPVOID lpEnvironment
指向包含新进程将要使用的环境字符串的内存块。在大多数情况下,为该参数传递NULL,使子进程能够继承它的父进程正在使用的一组环境字符串。也可以使用GetEnvironmentStrings函数当不再需要该内存块时,应该调用FreeEnvironmentStrings函数将内存块释放。
(8) LPCTSTR lpCurrentDirectory
设置子进程的当前驱动器和目录。如果本参数是NULL,则新进程的工作目录将与生成新进程的应用程序的目录相同。如果本参数不是NULL,那么必须指向包含需要的工作驱动器和工作目录的以0 结尾的字符串。注意,必须设定路径中的驱动器名。
(9) LPSTARTUPINFO lpStartupInfo
使用时应首先进行初始化。
成员 窗口/控制台 作用
cb 两者兼有 用作版本控制手段。必须初始化为sizeof(STARTUPINFO)
lpReserved 两者兼有 保留。必须初始化为NULL (不为NULL也可以)
lpDesktop 两者兼有 标识启动应用程序所在桌面的名字。如果桌面不存在,便创建一个带有默认属性的桌面,并使用为新进程指定的名字。其值为NULL时,与当前桌面相关联。 (不明白)
lpTitle 控制台 设定控制台窗口的名称。其值为NULL,则把可执行文件的名字用作窗口名。
dwXdwY 两者兼有 设定应用程序窗口在屏幕上的位置(以像素为单位)。只有当子进程用CW_USEDEFAULT作为CreateWindow的x参数来创建它的第一个重叠窗口时,才使用这两个坐标。
dwXSizedwYsize 两者兼有 设定应用程序窗口的宽度和长度(以像素为单位)只有当子进程将CW_USEDEFAULT用作CreateWindow的nWidth参数来创建它的第一个重叠窗口时,才使用这些值。
dwXCountCharsdwYCountChars 控制台 设定子应用程序的控制台窗口的宽度和高度(以字符为单位)
dwFillAttribute 控制台 设定控制台窗口的文本和背景颜色
dwFlags 两者兼有 后面以表格说明。
wShowWindow 窗口 设定如果子应用程序初次调用的ShowWindow将SW_SHOWDEFAULT作为nCmdShow参数传递时,该应用程序的第一个重叠窗口应该如何出现。
cbReserved2 两者兼有 保留。必须被初始化为0 (非0也可以)
lpReserved2 两者兼有 保留。必须被初始化为NULL (为什么)
hStdInputhStdOutputhStdError 控制台 设定控制台输入输出缓存的句柄。照默hStdInput标识键盘缓存,hStdOutput和hStdError标识控制台窗口缓存。
dwFlags使用方法:
标志 含义
STARTF_USESIZE 使用dwXSize和dwYSize成员
STARTF_USESHOWWINDOW 使用wShowWindow成员
STARTF_USEPOSITION 使用dwX和dwY成员
STARTF_USECOUNTCHARS 使用dwXCountChars和dwYCountChars成员
STARTF_USEFILLATTRIBUTE 使用dwFillAttribute成员
STARTF_USESTDHANDLES 使用hStdInput、hStdOutput和hStdError成员
STARTF_RUN_FULLSCREEN 强制在x86计算机上运行的控制台应用程序以全屏幕方式运行
STARTF_FORCEONFEEDBACK 启动进程时,临时将系统的箭头光标改为沙漏箭头光标。
STARTF_FORCEOFFFEEDBACK 启动进程时,不将光标改为沙漏。
(10) LPPROCESS_INFORMATION lpProcessInformation
新进程的返回信息。hProcess为新进程内核对象的句柄;hThread为新线程内核对象的句柄。在使用后应当用CloseHandle释放,使该内核的使用计数减一。dwProcessId新进程ID号;dwThreadId新线程ID号。0不能为ID号。虽然系统不会同时有相同的ID号,但是当一个进程的内核句柄被释放后其ID号又可能被新的进程使用。若要确保进程ID或线程ID不被重复使用,唯一的方法是保证进程或线程的内核对象不会被撤消。如果刚刚创建了一个新进程或线程,只要不关闭这些对象的句柄,就能够保证进程对象不被撤消。一旦应用程序结束使用该ID,那么调用CloseHandle就可以释放内核对象,要记住,这时使用或依赖进程ID,对来说将不再安全。如果使用的是子进程,将无法保证父进程或父线程的有效性,除非父进程复制了它自己的进程对象或线程对象的句柄,并让子进程继承这些句柄。
waterpig 2001-08-06
  • 打赏
  • 举报
回复
CreateProcess + WaitForSingleObject
dave75 2001-08-06
  • 打赏
  • 举报
回复
up
xlfrd 2001-08-06
  • 打赏
  • 举报
回复
既然你现在已经能得到所有窗口的鼠标消息,剩下的就是得到窗口句柄了,
…………
HWND hwnd;
::WaitForInputIdle(ProcessInfo.hProcess, INFINITE);
EnumThreadWindow(ProcessInfo.dwThreadId,EnumProc,(LPARAM)&hwnd);
//OK,hwnd is main window handle now

BOOL EnumProc(HWND hwnd,LPARAM param)
{
HWND* phwnd=(HWND*)param,hwndtemp;
while(hwndtemp=GetParent(hwnd))
{
hwnd=hwndtemp;
}
*phwnd=hwnd;
return FALSE;
}
Drate 2001-08-06
  • 打赏
  • 举报
回复
如果要改的话,可能要用到api的拦截技术了,可以看看这个例程,它讲了如何拦截api函数
http://www.vckbase.com/sourcecode/中的“消息截获程序代码”
土豆 2001-08-06
  • 打赏
  • 举报
回复
唉,不好办,我也不知道。
dave75 2001-08-06
  • 打赏
  • 举报
回复
还请众高手赐教啊。暂时先加100分。不知系统允不允许加分超过300?
hhb 2001-08-06
  • 打赏
  • 举报
回复
WH_CALLWNDPROC 类型的钩子不能修改消息
bzshow 2001-08-06
  • 打赏
  • 举报
回复
这样行否



DWORD Wait(HANDLE hProcess)
{
return WaitForSingleObject(hProcess, INFINITE);
}


DWORD Execute(const CString & strCmd, const CString & strArgs, const CString & strDir, BOOL bWait)
{
TRACE3("ProcessMgr::Execute(%s,%s,%s)\n",LPCTSTR(strCmd),LPCTSTR(strArgs),LPCTSTR(strDir));

CString strPath = strCmd;

// first check, which program to use to start <strCmd>
TCHAR szExe[1024];
if( int(FindExecutable(
strPath, // pointer to filename
strDir.IsEmpty() ? 0 : LPCTSTR(strDir), // pointer to default directory
szExe // result-buffer
)) <= 32 ) {
return DWORD(-1);
}

CString strCmdLine;

if( strPath.FindOneOf(TEXT(" \t")) >= 0 )
strCmdLine = "\"" + strPath + "\"" ;
else
strCmdLine = strPath;

if( !strArgs.IsEmpty() )
strCmdLine += " " + strArgs;

STARTUPINFO StartupInfo;
ZeroMemory(&StartupInfo, sizeof(STARTUPINFO));
StartupInfo.cb = sizeof(STARTUPINFO);

PROCESS_INFORMATION ProcessInfo;
DWORD dwRetVal = DWORD(-1);

BOOL bStat = CreateProcess(
szExe, // pointer to name of executable module
LPTSTR(LPCTSTR(strCmdLine)),// pointer to command line string
0, // pointer to process security attributes
0, // pointer to thread security attributes
TRUE, // handle inheritance flag
0, // creation flags
0, // pointer to new environment block
strDir.IsEmpty() ? 0 : LPCTSTR(strDir),
&StartupInfo, // pointer to STARTUPINFO
&ProcessInfo // pointer to PROCESS_INFORMATION
);
if( bStat ) {
if( bWait ) {
::WaitForInputIdle(ProcessInfo.hProcess, INFINITE);
dwRetVal = Wait(ProcessInfo.hProcess);
} else {
// before we return to the caller, we wait for the currently
// started application until it is ready to work.
::WaitForInputIdle(ProcessInfo.hProcess, INFINITE);
dwRetVal = ProcessInfo.dwProcessId;
}

::CloseHandle(ProcessInfo.hThread);
}

return dwRetVal;
}
dave75 2001-08-06
  • 打赏
  • 举报
回复
up
dave75 2001-08-06
  • 打赏
  • 举报
回复
to : FireAngel(堕落天使):你的回答和我的要求比较接近。我已经做了一个全局鼠标钩子,希望拦截发给这个外部的exe的所有的鼠标右键消息,这个exe不是我写的。我现在已经能够读到所有的鼠标消息,但怎样修改(或抛弃)呢?WM_MOUSE挂钩过程允许修改消息吗?如不能,如何才能修改?
NowCan 2001-08-03
  • 打赏
  • 举报
回复
还要用SetWindowLong改变窗口处理函数。
lownr 2001-08-03
  • 打赏
  • 举报
回复
首先 CreateProcess 建立进程
然后用 WH_CALLWNDPROC 类型的钩子钩住这个进程
土豆 2001-08-03
  • 打赏
  • 举报
回复
如果外部EXE不是你自己写的,那么你可以考虑做一个钩子去拦截它的消息,至于等待它结束倒是比较简单的,用waitforsingleobject(创建时得到的进程句柄...)就可以了。因为进程执行结束后它的句柄会转变成为信号量。
五行擒拿术 2001-08-03
  • 打赏
  • 举报
回复
没看明白
土豆 2001-08-03
  • 打赏
  • 举报
回复
外部的exe文件也是你自己写的吗?
dave75 2001-08-03
  • 打赏
  • 举报
回复
如果不用createprocess当然也可以。回答请写明各个参数的设置。急等答案,有效立刻给分。我随时在网上。

16,472

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧