您的意图不太清楚。您是希望此进程在Perl程序结束后继续运行吗?还是您想与此进程进行通信?
在大多数情况下,只需使用普通的 fork
(在Windows上进行模拟,但大多数内容仍能正常运作)即可,除非您想以Windows特定的方式与 $proc
进行交互。另外请注意,通常 dir
是 cmd.exe
的内置命令,因此除非您在 %PATH%
上拥有 dir.exe
、dir.com
或 dir.bat
等文件,否则 Win32::Process
将无法在其中运行。
以下程序可以复制崩溃:
$| = 1;
use v5.24;
use strict;
use warnings;
use threads;
use feature 'signatures';
no warnings 'experimental::signatures';
use autouse Carp => qw( croak );
use Win32::GuiTest qw( FindWindowLike SendKeys SetForegroundWindow );
use Win32::Process;
use Win32;
run();
sub run {
Win32::Process::Create(
my $proc,
'C:\WINDOWS\system32\notepad.exe',
'notepad.exe',
0,
+NORMAL_PRIORITY_CLASS,
'.',
) or croak Win32::FormatMessage(Win32::GetLastError());
my @thr = map threads->create(\&task), 1 .. 2;
threads->yield;
my @windows;
do {
@windows = FindWindowLike(0, 'Notepad');
} until (@windows);
wait_for_thread($_, $windows[0]) for @thr;
say 'All done.';
SetForegroundWindow($windows[0]);
SendKeys('%fxn');
$proc->Wait(+INFINITE);
return;
}
sub task {
my $tid = threads->tid;
say "Thread $tid waiting ($_)" for 1 .. 5;
threads->yield;
return;
}
sub wait_for_thread($thr, $window) {
my $msg = sprintf "Waiting for thread %d\n", $thr->tid;
print $msg;
SetForegroundWindow($window);
SendKeys($msg);
$thr->join;
return;
}
我在调试器中看到了这个:
![Visual Studio Debugger](https://istack.dev59.com/FAazU.webp)
很可能是线程
和Win32::Process
之间的交互暴露出了一个错误*。
另一方面,下面的版本似乎运行良好:
$| = 1;
use v5.24;
use strict;
use warnings;
use threads;
use feature 'signatures';
no warnings 'experimental::signatures';
use autouse Carp => qw( croak );
use Win32::GuiTest qw( FindWindowLike SendKeys SetForegroundWindow );
run();
sub run {
defined(my $cpid = fork)
or croak "Failed to fork: $!";
if (!$cpid) {
system 'notepad';
exit;
}
my @thr = map threads->create(\&task), 1 .. 2;
threads->yield;
my @windows;
do {
@windows = FindWindowLike(0, 'Notepad');
} until (@windows);
wait_for_thread($_, $windows[0]) for @thr;
say 'All done.';
SetForegroundWindow($windows[0]);
SendKeys('%fxn');
1 while waitpid(-1, 0) > 0;
return;
}
sub task {
my $tid = threads->tid;
say "Thread $tid waiting ($_)" for 1 .. 5;
threads->yield;
return;
}
sub wait_for_thread($thr, $window) {
my $msg = sprintf "Waiting for thread %d\n", $thr->tid;
print $msg;
SetForegroundWindow($window);
SendKeys($msg);
$thr->join;
return;
}
正如我所提到的,除非有特定的原因需要使用 Win32::Process
,否则最好使用 fork
。
* 如有疑问,请随时与P5P联系。
Win32::Process::Create
?我以为你想在单独的进程中运行线程,但是如果你不想混合它们(更好!),那么你在问什么?请注意,在 Win32 上进行分叉是可行的,并且还有很好的模块可用。除非需要以复杂的方式交换数据,否则分叉要简单得多。(请标记您要寻址的人,以便他们收到通知) - zdim