能使其它的.exe执行程序暂停吗?(60分)

  • 主题发起人 主题发起人 victor
  • 开始时间 开始时间
V

victor

Unregistered / Unconfirmed
GUEST, unregistred user!
我在程序中用winexec(..,..)调用运行了
一个.exe程序,若想让其暂停运行,
能做到吗?若能暂停,再如何重新接着
运行了?
 
应该可以做到.
想办法让被调用的程序在特定的时候运行WaitForSingleObject, 它所wait的这个object
由你的主程序控制是否满足条件不就成了?
 
但这个.exe程序是买来的,没有源码。
如何能让其运行:WaitForSingleObject
 
1.必须用CreateProcess()创建进程(为什么在32位系统下还有那么多人用
WinExec这个过时的函数?).
2.该进程只有一个线程(不是多线程程序).
3.CreateProcesd()返回的结果中,有一个线程句柄.这个句柄是那个进程
的主线程.记住这个句柄(设为ThreadHandle).
4.SuspendThread(ThreadHandle).
 
Hello,lhz:

我用CreateProcess(...)怎么老是不能正确创建
进程?
能否给个小例子.
我用createprocess(..)返回的Error号为87, 或167.
 
87的意思是“参数错误”,表示你传给CreateProcess的参数不正确。
把你关于这个函数调用的代码贴出来。
167的意思是“无法锁定文件区域”,可能这个.exe被别的进程打开了。
关闭打开了这个文件的进程再试。
 
如果这个程序是多现成的,是否会出问题呢?
 
A sample using CreateProcess to open "Notepad":

var lpProcessInformation: TProcessInformation;

TForm1.Button1Click(Sender: TObject);
var
sCommandLine: string;
bCreateProcess: boolean;
lpStartupInfo: TStartupInfo;
begin
sCommandLine := 'C:/Windows/Notepad.exe';
Button1.Enabled := false;
// 填入 StartupInfo
FillChar(lpStartupInfo, Sizeof(TStartupInfo), #0);
lpStartupInfo.cb := Sizeof(TStartupInfo);
lpStartupInfo.dwFlags := STARTF_USESHOWWINDOW;
lpStartupInfo.wShowWindow := SW_NORMAL;
bCreateProcess := CreateProcessA(pchar(sCommandLine), nil,
pchar(sCommandLine), nil, nil, True, NORMAL_PRIORITY_CLASS, nil,
nil, lpStartupInfo, lpProcessInformation);
if bCreateProcess then
begin
WaitForInputIdle(lpProcessInformation.hProcess, 60000);
//time-out interval in milliseconds
memo1.clear;
memo1.Lines.Add(format('hProcess: %d', [lpProcessInformation.hProcess]));
memo1.lines.add(format('hThread: %d', [lpProcessInformation.hThread]));
memo1.lines.add(format('dwProcessID: %u', [lpProcessInformation.dwProcessID]));
memo1.lines.add(format(' dwThreadID: %u', [lpProcessInformation.dwThreadId]));
end;
end;

With this ProcessInformation you can do:
1. Terminate it
TerminateProcess(lpProcessInformation.hProcess ,0);
2. Get thread windows
enumThreadWindows(lpProcessInformation.dwThreadID, @enumThreadWndProc, 0);
 
Here is a way to get all the windows associated with the Process:

First, you need a enumThreadWindow procedure(same as other enumwindow
procedure). After you get the ProcessInformation, you can call
enumThreadWindows function to enumerate all the window's handles of this thread:

var
WndCount: integer;
WndArray: array [0..255] of HWnd;
lpProcessInformation: TProcessInformation;

//the enumerate Thread Window procedure
function EnumThreadWndProc(AHWnd: HWnd; ALPARAM: lParam): boolean; stdcall;
var
WndCaption: array[0..254] of char;
WndClassName: array[0..254] of char;
begin
Form1.WndArray[Form1.WndCount] := AHWnd;
Inc(Form1.WndCount);
GetWindowText(AHWnd, @WndCaption, 254);
GetClassName(AHWnd, @WndClassName, 254);
with Form1.Memo1.Lines do
begin
Add(format('hWnd: %x, Caption: %s, Class: %s',[AHWnd, StrPas(WndCaption), StrPas(WndClassName)]));
end;
Result := true;
end;

//create process and find its windows
procedure TForm1.Button1Click(Sender: TObject);
var
sCommandLine: string;
bCreateProcess: boolean;
lpStartupInfo: TStartupInfo;
begin
sCommandLine := 'C:/Windows/Notepad.exe';
Button1.Enabled := false;
//填入 StartupInfo
FillChar(lpStartupInfo, Sizeof(TStartupInfo), #0);
lpStartupInfo.cb := Sizeof(TStartupInfo);
lpStartupInfo.dwFlags := STARTF_USESHOWWINDOW;
lpStartupInfo.wShowWindow := SW_NORMAL;
bCreateProcess := CreateProcessA(pchar(sCommandLine),nil,// PChar(sCommandLine),
nil, nil, True, NORMAL_PRIORITY_CLASS, nil, nil,
lpStartupInfo, lpProcessInformation);
if bCreateProcess then
begin
WaitForInputIdle(lpProcessInformation.hProcess,// handle to process
60000);// time-out interval in milliseconds
memo1.clear;
memo1.Lines.Add(format(' hProcess: %d',[lpProcessInformation.hProcess]));
memo1.lines.add(format(' hThread: %d',[lpProcessInformation.hThread]));
memo1.lines.add(format('dwProcessID: %u', [lpProcessInformation.dwProcessID]));
memo1.lines.add(format(' dwThreadID: %u', [lpProcessInformation.dwThreadId]));
WndCount:=0;
enumThreadWindows(lpProcessInformation.dwThreadID, @enumThreadWndProc, 0);
end;
end;

You should know the features of the main window so you can pick out
the main window. Once you got the main window, you can use the api
function enumChildWindows to find out all child windows. Surely you
need to write a enumChildWndProc.

enumChildWindows(MainWnd, @enumChildWndProc, 0);
In this example("notepad.exe"), WndArray[0] is the main window.
 
Sorry victor, the last message is for your other question.
 
谢谢各位,

请问在delphi中如何使用sendkey(..),
我试了, 在sendkey上按F1,没有反应,
这是不是说明sendkey不是windows的API.
 
SendKey是VB里面的东西, 模拟键盘输入某一个键盘命令到某一个Application.
Delphi中部没有, 但是Delphi4.0光盘下 /Info目录中有一个例子.

发送 WM_Command, 可以用下列两种方法, 有的时候Thread不能接受Message只能用
窗体的Handle:
PostThreadMessage(lpProcessInformation.dwThreadId,WM_Command,CmdID,0);
postMessage( WndArray[0], WM_Command, CmdID, 0);
 
>发送 WM_Command, 可以用下列两种方法, 有的时候Thread不能接受
>Message只能用窗体的Handle:
>PostThreadMessage(lpProcessInformation.dwThreadId,WM_Command,CmdID,0);
>postMessage( WndArray[0], WM_Command, CmdID, 0);

我试着用了PostThreadMessage and PostMessage,
但CmdID好象老是不对. (我这不是杀掉进程, 而是发送其他的命令)
我用BC的work shop 分析了一下, 菜单的ID为40002, 40003等,
都大于40000, CmdID是用这些吗?
 
当然CmdID要给具体值了, 40002, 40004...
 
Come on! Victor! Have you done the work?
 
victor看样子不会来了,给分了
 
多人接受答案了。
 
后退
顶部