这应该很简单:我正在创建一个使用win32 CreateProcess()函数生成进程的程序.加载此进程后,我会找到其窗口FindWindow并使用它发送消息SendMessage().问题是,我怎么知道该窗口何时准备接受消息?
考虑以下:
HWND wnd;
BOOL Start()
{
// Spawn the process
if (! CreateProcess(...))
return FALSE;
// Find the process's window (class and name already known)
wnd = FindWindow(MY_WINDOW_CLASS, MY_WINDOW_NAME);
// Always returns FALSE because window has not yet been created.
return (wnd != NULL);
}
Run Code Online (Sandbox Code Playgroud)
上面的代码(几乎?)总是失败; 窗口无法快速创建和发现.如果我把一个线程等待,比如Sleep(1000),在CreateProcess和FindWindow调用之间,它可以正常工作.但这感觉就像一个非常糟糕的黑客.
我怎样才能改善这个?
我有2个应用程序,program.exe和updater.exe,都是用Delphi5编写的.程序在没有admin-rights(并且没有manifest)的情况下运行,updater有一个带有"requireAdministrator"的清单,因为他必须能够在Program-Folder中写入以更新program.exe.
问题是启动更新程序,让他等到程序关闭.我在网上找到了不同的方式,但都没有用(大多数情况下,第一个应用程序启动第二个应用程序并等待第二个应用程序的结束,在我的情况下,第二个应用程序应该等待第一个应用程序的结束).
更新程序应该等待,这很容易
updater.exe
{$R manifest.res}
label.caption:='Wait for program.exe closing';
repeat
sleep(1000);
until File is not open
ProgramHandle := Read Handle from File
WaitForSingleObject(ProgramHandle,INFINITE);
label.caption:='program.exe CLOSED';
Do updates
Run Code Online (Sandbox Code Playgroud)
方法1
使用CreateProcess启动更新程序:
program.exe
FillChar(siInfo, SizeOf(siInfo), 0);
siInfo.cb := SizeOf(siInfo);
saProcessAttributes.nLength := SizeOf(saProcessAttributes);
saProcessAttributes.lpSecurityDescriptor := nil;
saProcessAttributes.bInheritHandle := TRUE;
saThreadAttributes.nLength := SizeOf(saThreadAttributes);
saThreadAttributes.lpSecurityDescriptor := nil;
saThreadAttributes.bInheritHandle := True;
if CreateProcess(nil,
PChar('updater.exe'),
@saProcessAttributes,
@saThreadAttributes,
TRUE, NORMAL_PRIORITY_CLASS, nil,
PChar(ExtractFilePath(Application.ExeName)),
siInfo, piInfo) then
begin
DuplicateHandle(GetCurrentProcess, GetCurrentProcess,
piInfo.hProcess, @MyHandle,
PROCESS_QUERY_INFORMATION, TRUE,
DUPLICATE_SAME_ACCESS) then
Write MyHandle in a …Run Code Online (Sandbox Code Playgroud) delphi createprocess handle waitforsingleobject shellexecuteex
我想创建一个与父进程分离的子进程,这样如果父进程退出,子进程将继续。我正在 Windows 上工作并执行了以下操作:
if(CreateProcess(program, arguments, NULL, NULL, FALSE, CREATE_DEFAULT_ERROR_MODE | CREATE_NO_WINDOW | DETACHED_PROCESS, NULL, NULL, &sinfo, &pinfo))
{
CloseHandle(pinfo.hProcess);
CloseHandle(pinfo.hThread);
}
Run Code Online (Sandbox Code Playgroud)
在我的例子中,父进程继续运行,而子进程在后台执行。如果我在终端中按 Ctrl-C 来终止父进程,则子进程将按预期继续执行。但是,如果我在 Window 的任务管理器中杀死父进程,则子进程也会被杀死。
为什么Ctrl-C和任务管理器中的查杀有区别?即使父级在任务管理器中被杀死,有什么方法可以确保子级继续运行?
当我在Windows中调用CreateProcess时,新进程似乎不会继承调用进程的控制台.我制作了一个运行"ruby xtest"的测试程序,xtest是一个将"hello"写入标准输出的脚本.我从Emacs运行了这个测试程序,没有输出.我还尝试了以下代码调用GetStdHandle,但同样没有输出.然后我尝试将dwCreationFlags中的CREATE_NEW_CONSOLE传递给CreateProcess,后者用Ruby输出创建了一个全新的窗口.最后,我做了一个简单的fork/exec测试程序,并使用Cygwin的GCC编译它.这个程序工作:Ruby输出出现在Emacs中如预期的那样.我试图在http://cygwin.com/cgi-bin/cvsweb.cgi/src/winsup/cygwin/spawn.cc?rev=1.268&content-type=text/x-cvsweb-markup&中破译Cygwin源代码.但失败了.那么,如何使新进程继承父进程的控制台,以便子进程的输出按预期显示?
STARTUPINFO si;
PROCESS_INFORMATION pi;
memset(&si, 0, sizeof(si));
memset(&pi, 0, sizeof(pi));
si.dwFlags |= STARTF_USESTDHANDLES;
si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
if(!CreateProcess(0, "ruby xtest", 0, 0, 1, 0, 0, 0, &si, &pi)) die("CreateProcess");
Run Code Online (Sandbox Code Playgroud) 我想执行任意命令行应用程序并在生成时读取其标准输出。我用来CreateNamedPipe创建一个管道,然后将另一端(打开使用的CreateFile)提供给CreateProcess。如果目标进程没有显式地使用标准输出缓冲进行操作,是否有一种方法可以确保有问题的管道没有缓冲,或者至少使用系统最小值作为缓冲区大小?
我有两个进程,A 和 B。在某个时刻 A 创建了 B。创建 B 后,如果 A 的进程树被终止,我希望 B 仍然存在。
我正在使用 CreateProcess() 创建 B,但我似乎找不到任何方法让它在不成为子进程的情况下创建进程。与 ShellExecuteEx() 相同,但我可能缺少一些标志。
有谁知道我可以用什么来做到这一点?
编辑:我忘了提到两个进程都需要另一个进程的句柄或进程 ID
对于Linux和WinXP,forking()和CreateProcess(带有所有必需的参数)分别是同一回事吗?
如果它们不同,那么有人可以用两种情况下的不同来解释这种差异吗?
谢谢
我们的应用程序需要安装HASP SRM设备驱动程序才能安装和运行我们的驱动程序.
目前,只有他们的5.50驱动程序在所有测试平台上一致地工作(他们的5.75(官方)和5.86(beta)驱动程序在测试的大约三分之一的计算机中崩溃).
因此,他们的5.50驱动程序是好的,当前可用的任何其他东西都被破坏,并且5.50驱动程序拒绝在Vista和Windows 7下加载.但是,如果我将exe的属性设置为"XP兼容模式",那么他们的5.50驱动程序安装并成功运行.
我在Windows 7下的注册表中挖了一下,我发现当我要求兼容模式时至少有一个条目:
HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers\
full-path REG_SZ WINXPSP3
Run Code Online (Sandbox Code Playgroud)
在尝试启动5.50驱动程序安装程序之前,我应该能够从安装程序添加该密钥.
问题:
如果您使用带有 CREATE_NEW_CONSOLE 标志的 CreateProcess,则新进程会将其标准输入、输出和错误句柄定向到新控制台窗口。如果要覆盖 I/O 流,可以通过设置 STARTUPINFO 字段 hStdOutput、hStdInput 和 hStdError 中的句柄并设置标志 STARTF_USESTDHANDLES 来实现。
但是如果您只想覆盖一个句柄怎么办?例如,我可能希望将 stderr 重定向到一个文件,同时将 stdout 和 stdin 连接到新的控制台窗口。
STARTF_USESTDHANDLES 标志告诉 CreateProcess 替换所有句柄,而不是将它们连接到新控制台窗口的句柄。所以看起来我们必须提供所有三个句柄。显然我可以将 hStdError 设置为日志文件的句柄,但是 hStdInput 和 hStdOutput 应该使用什么值?
我尝试使用 NULL,它似乎适用于 Windows 8.1,但不适用于 Windows 7。
我还考虑过首先创建一个控制台窗口,然后使用新控制台窗口缓冲区的句柄调用 CreateProcess(并省略 CREATE_NEW_CONSOLE 标志)。不幸的是,父进程也是一个控制台应用程序,似乎一个控制台应用程序无法创建第二个控制台窗口。
有没有办法以编程方式启动后台(即非窗口)可执行文件而不启动关联的 conhost.exe 进程?
我已经在生成工作进程的启动程序进程中尝试过这样的代码:
var process = new Process();
process.StartInfo.FileName = executable;
process.StartInfo.Arguments = args;
process.StartInfo.UseShellExecute = false;
process.StartInfo.CreateNoWindow = true;
Run Code Online (Sandbox Code Playgroud)
任何帮助,将不胜感激。
语境:
我们正在进行性能和负载测试。为了复制我们的大型客户环境,我们租用了服务器容量,以允许我们运行数千个虚拟服务器,但它们内存有限(每个虚拟机大约 300-500MB 内存)。
该场景是每个虚拟机运行 100 个进程。~1.3 MB 可执行进程和 4-5 MB conhost.exe 进程(在Windows Server Standard Edition 核心更新 1803上)的组合使得无法运行 100 个进程。如果我们能够消除相关的 conhost.exe,我们就有机会了。
注意:conhost 在 Windows 7 环境中要小得多 (< 800KB),但我们必须使用 Windows 服务器。
同样的场景也适用于 Linux。