【问题标题】:Determine if a process is active确定进程是否处于活动状态
【发布时间】:2013-06-01 18:19:03
【问题描述】:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs,Tlhelp32, StdCtrls;

  function processExists(exeFileName: string): Boolean; 
var
  ContinueLoop: BOOL; 
  FSnapshotHandle: THandle; 
  FProcessEntry32: TProcessEntry32;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
FSnapshotHandle := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  FProcessEntry32.dwSize := SizeOf(FProcessEntry32); 
  ContinueLoop := Process32First(FSnapshotHandle, FProcessEntry32); 
  Result := False;
  while Integer(ContinueLoop) <> 0 do 
  begin 
    if ((UpperCase(ExtractFileName(FProcessEntry32.szExeFile)) = 
      UpperCase(ExeFileName)) or (UpperCase(FProcessEntry32.szExeFile) = 
      UpperCase(ExeFileName))) then
    begin 
      Result := True; 
    end; 
    ContinueLoop := Process32Next(FSnapshotHandle, FProcessEntry32); 
  end;
  CloseHandle(FSnapshotHandle); 
end; 

procedure TForm1.Button1Click(Sender: TObject); 
begin 
  if processExists('notepad.exe') then 
    ShowMessage('process is running')
  else 
    ShowMessage('process not running');
end;

enprocedure TForm1.Button1Click(Sender: TObject);
begin

end;

这是我遇到错误的确切代码,它是 delphi 技巧的示例。现在我只是想填满我的编辑,以便stackoverflow让我发布我的编辑,我显然有大部分代码,所以我需要礼貌地添加更多细节

【问题讨论】:

  • “我不断收到错误” 什么错误?在代码的哪一行。也许编辑您的问题并将您的确切代码粘贴到其中。
  • 你试过打电话给EnumProcesses吗?
  • 调用枚举进程?让我再读一遍,我也会发布错误
  • 您似乎偶然发现了常见的代码完成问题 - 当您通过双击对象检查器中的事件创建新过程作为事件处理程序时,有时它会将新过程注入到稍微偏离位置,导致代码混淆。这就是为什么你有一行以enprocedure 开头的原因,因为en 部分应该是end. 无论哪种方式,在此之后你应该有一个d.。
  • @JerryDodge 这是症状,不是疾病。问题是由混合行尾字符的源引起的(有些行以 LF 结尾,其他行以 CRLF 结尾,而其他行可能只有 CR)并且 delphi IDE 错误地解析它。看到这个问题:stackoverflow.com/q/14243629/10300

标签: delphi


【解决方案1】:

您问题中的代码失败了,因为您已设法将函数 processExists 的内容复制到 FormCreate 方法中,而不是复制到实际函数本身中。

从FormCreate中删除代码并在实现部分实现函数processExists:

function processExists(exeFileName : string) : Boolean;
begin
  FSnapshotHandle := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  FProcessEntry32.dwSize := SizeOf(FProcessEntry32);
  ContinueLoop := Process32First(FSnapshotHandle, FProcessEntry32);
  Result := False;
  while Integer(ContinueLoop) <> 0 do
  begin
    if ((UpperCase(ExtractFileName(FProcessEntry32.szExeFile)) =
      UpperCase(ExeFileName)) or (UpperCase(FProcessEntry32.szExeFile) =
      UpperCase(ExeFileName))) then
    begin
      Result := True;
    end;
    ContinueLoop := Process32Next(FSnapshotHandle, FProcessEntry32);
  end;
  CloseHandle(FSnapshotHandle);  
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  if processExists('notepad.exe') then
    ShowMessage('process is running')
  else
    ShowMessage('process not running');
end;

【讨论】:

  • 非常感谢,效果很好!哇,现在我要通读一遍并弄清楚,我没有考虑实现部分...我需要在部分上学习更多
  • @Sheep,是的,你可以这样做。选择您在 Button1Click 方法中的代码并将其移动或复制粘贴到与 OnCreate 事件关联的方法(FormCreate),然后在创建表单时将触发相同的代码。我还建议您查看 David 的回答,虽然他对这个问题不满意,但他提出了一些关于代码的有效观点。
  • @PeterVonča 我不太确定我的回答是“不正确”。我实际上看不到直接的问题。问题中的代码甚至无法编译。我刚刚提供了一个不错的 ProcessExists 实现,它解决了无数问题。
  • @DavidHeffernan,问题不在于代码的有效性,而在于“为什么不能编译”或“为什么这会给我错误”。我同意,代码很糟糕,但不会导致他问这个问题的原因的错误。
  • 我的意思是,实际上没有问题。上面这段文字的哪一部分是问题?而且发布的代码也无法编译,因为没有实现 processExists 并且单元没有结束。我不想重复您对 FormCreate 所说的话,因为您说得很好并且您的回答被接受了。我想确保至少有人用健全的代码给出了答案。虽然可能没有人会认真对待我的回答。
【解决方案2】:

代码似乎放错了地方。我们看不到您对ProcessExists 的实现,但那是代码应该存在的地方。

但我想专注于包含多个错误的问题中的代码。下面是我的写法:

function ProcessExists(const ExeFileName: string): Boolean;
var
  SnapshotHandle: THandle;
  ProcessEntry32: TProcessEntry32;
  Continue: BOOL;
begin
  Result := False;
  SnapshotHandle := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  Win32Check(SnapshotHandle<>INVALID_HANDLE_VALUE);
  try
    ProcessEntry32.dwSize := SizeOf(ProcessEntry32);
    Continue := Process32First(SnapshotHandle, ProcessEntry32);
    while Continue do
    begin
      if SameText(ProcessEntry32.szExeFile, ExeFileName) then
      begin
        Result := True;
        exit;
      end;
      Continue := Process32Next(SnapshotHandle, ProcessEntry32);
    end;
  finally
    CloseHandle(SnapshotHandle);
  end;
end;

我已经解决的问题:

  1. 这里不要使用全局变量。这里的变量都可以并且应该是局部变量。将局部变量优先于所有其他变量,并尽可能使用它们。
  2. 不要将BOOL 转换为整数并与0 进行比较。BOOL 是逻辑的,因此可以直接在逻辑上下文中使用。
  3. 使用SameText 而不是UpperCase 混乱。
  4. 不要两次执行相同的文本比较。一次就够了。
  5. 找到匹配项时跳出循环。
  6. 使用 try/finally 来防御导致资源泄漏的异常。

【讨论】:

    【解决方案3】:

    链接页面中显示的代码使用的是 Windows 中的ToolHelp API。您应该查看链接页面。

    当您使用该 API 时,您会创建操作系统当前进程列表的快照,并使用 Process32First 和 Process32Next 遍历该列表以检测该进程。

    建议:MadCollection 的 MadKernel 部分(MadExcept 和 MadCodeHook 是付费部分)围绕这些功能做了一个非常好的和有用的包装器。这些调用使我的 50 行函数将消息发送到父应用程序到 10 行。

    PS:除了使用他们的库之外,我与 madshi.net 没有任何关系;-)

    【讨论】:

    • 另外,这对我来说运行得很好..但它只会在 delphi 中获取应用程序,我希望它对外部应用程序执行此操作
    猜你喜欢
    • 2015-04-13
    • 1970-01-01
    • 2011-01-17
    • 2016-08-29
    • 2019-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多