Windows下如何让非NT程序像NT程序一样毫无踪迹在后台运行?

Windows版本:Windows 10

Delphi版本:Delphi 10.3

需求说明:让正常的图形界面程序或DOS程序,能够彻底隐藏踪迹,像NT程序一样在后台悄悄运行!!正常的程序,如果在运行时候,会有程序窗口,如果加入了在任务栏显示代码,最小化会在任务栏有图标!!这些我都不想要,我就想让这些正常程序运行时候,根本任何运行痕迹都看不到!!!

解决过程:

通常这样的程序,把运行的参数设置为SW_HIDE就可以了,但是,对于有些程序,这样设置是不可以的,当最小化时候,会在任务栏留有图标!!怎么办?创建虚拟桌面,让这个运行的程序在这个虚拟桌面中,这样,在当前运行程序的桌面中就看不到任何踪迹了!!

Delphi实现代码:

uses TLHelp32; // 判断进程是否运行用的单元

const
  DesktopName: PChar = 'NewDesktop'; //虚拟桌面名称

var
  desktopHandle: THandle; // 桌面handle

{
  像NT程序一样在后台运行程序,前台看不到被运行程序
  说明:无论要运行的程序是正常的图形界面程序,还是DOS程序,在运行程序的桌面中看不到它的任何运行的踪迹,
  被运行的程序像NT程序一样悄悄在后台运行,即使这个程序正常运行时候最小化会在任务栏有图标!!
  在任务管理器中会查看到被运行程序的进程!!
  参数:
  fullExe:要运行程序的全路径名称
  exeParam:要运行程序的参数
  tempDesktopName:创建的虚拟桌面名称
  tempDesktopHandle:创建的虚拟桌面Handle
  返回值:是否运行成功
}
function RunInbackGround(fullExe: string; exeParam: string;
  tempDesktopName: string; var tempDesktopHandle: THandle): boolean;
var
  isSuccess: boolean; // 是否运行成功的返回值

  CmdLine: string; // 要执行的命令(要执行程序的全路径名称+参数)
  WorkingDirP: PChar; // 工作目录
  StartupInfo: TStartupInfo; // 进程启动参数
  ProcessInfo: TProcessInformation; // 进程信息
  ErrorCode: integer; // 进程启动的错误代码
  exeName: string; // 要执行程序名称

  // 是否程序正在运行
  function isExeRunning(exeName: string): boolean;
  var
    lppe: TProcessEntry32;
    isFound: boolean;
    Hand: THandle;
    tempName: string; // 程序名称
    temp: boolean; // 返回值变量
    judgePos: integer; // 扩展名判断位置
  begin
    Hand := CreateToolhelp32Snapshot(TH32CS_SNAPALL, 0);
    lppe.dwSize := SizeOf(lppe); // 必须设置此值
    isFound := Process32First(Hand, lppe);

    temp := false; // 返回的布尔值

    // 程序名称变量
    tempName := trim(exeName);

    // 扩展名分隔符位置
    judgePos := Pos('.', tempName);

    // 判断是否有扩展名
    if judgePos = 0 then
    begin
      tempName := tempName + '.exe'; // 添加".exe"扩展名
    end
    else
    begin
      if Length(copy(tempName, judgePos, 4)) < 4 then
      begin
        // 删除不符合添加的扩展名
        Delete(tempName, judgePos, (Length(tempName) - judgePos + 1));
        // 添加".exe"扩展名
        tempName := tempName + '.exe';
      end;
    end;

    // 循环判断是否有相同名称程序
    while isFound do
    begin

      // 判断当前程序名称和指定程序名称相同
      if lppe.szExeFile = tempName then
      begin
        temp := true;
        Break;
      end;

      // Memo1.Lines.Add(IntToStr(i) + ' : ' +IntToStr(lppe.th32ProcessID)+' '+ StrPas(lppe.szExeFile));
      isFound := Process32Next(Hand, lppe);
    end;

    result := temp;
  end;

// 杀死进程
  procedure KillProc(procName: string);
  const
    PROCESS_TERMINATE = $0001;
  var
    ExeFileName: String;
    ContinueLoop: Bool;
    FSnapshotHandle: THandle;
    FProcessEntry32: TProcessEntry32;
  begin
    ExeFileName := procName;
    FSnapshotHandle := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    FProcessEntry32.dwSize := SizeOf(FProcessEntry32);
    ContinueLoop := Process32First(FSnapshotHandle, FProcessEntry32);
    while integer(ContinueLoop) <> 0 do
    begin
      if ((UpperCase(ExtractFileName(FProcessEntry32.szExeFile))
        = UpperCase(ExeFileName)) or (UpperCase(FProcessEntry32.szExeFile)
        = UpperCase(ExeFileName))) then
        TerminateProcess(OpenProcess(PROCESS_TERMINATE, Bool(0),
          FProcessEntry32.th32ProcessID), 0);
      ContinueLoop := Process32Next(FSnapshotHandle, FProcessEntry32);
    end;
  end;

begin

  isSuccess := true; // 是否运行成功的返回值的默认值

  {
    一,创建用于存放要运行程序的虚拟桌面
  }
  // 如果虚拟桌面没有创建,则创建
  if tempDesktopHandle = 0 then
  begin
    tempDesktopHandle := CreateDesktop(PChar(tempDesktopName), nil, nil, 0,
      GENERIC_ALL, nil);
  end;

  {
    二,运行指定的程序
  }
  try

    // 要执行的命令(要执行程序的全路径名称+参数)
    CmdLine := '"' + trim(fullExe) + '" ' + trim(exeParam);
    WorkingDirP := nil; // 工作目录

    exeName := ExtractFileName(fullExe); // 得到要运行的程序名称
    // 如果要运行程序运行中,则先杀死它
    if isExeRunning(exeName) = true then
    begin
      KillProc(exeName); // 杀死正在运行的程序
    end;

    ZeroMemory(@StartupInfo, SizeOf(StartupInfo));
    StartupInfo.cb := SizeOf(StartupInfo);

    StartupInfo.lpDesktop := DesktopName; // 设置启动程序的虚拟桌面(注意:这个参数才真正让运行的程序隐藏起来)
    StartupInfo.dwFlags := STARTF_USESHOWWINDOW;
    StartupInfo.wShowWindow := SW_HIDE; // 常规的隐藏运行程序窗口参数

    // 创建要运行程序的进程(CREATE_NO_WINDOW是创建无窗口程序的参数)
    if not CreateProcess(nil, PChar(CmdLine), nil, nil, false, CREATE_NO_WINDOW,
      nil, WorkingDirP, StartupInfo, ProcessInfo) then
    begin
      isSuccess := false;
      ErrorCode := GetLastError;
    end;

    with ProcessInfo do
    begin
      CloseHandle(hThread);
      CloseHandle(hProcess);
    end;

  except
    on e: exception do
    begin
      isSuccess := false;
    end;
  end;

  result := isSuccess;
end;

Delphi示例代码:

procedure TForm2.Button3Click(Sender: TObject);
var
  FileName, Parameters: string;
begin

  FileName := '要运行的程序,可以是图形界面也可以是DOS程序';

  Parameters :='要运行程序的参数,没有就空';

  if RunInbackGround(FileName, Parameters, DesktopName, desktopHandle) = true
  then
  begin
    showMessage('虚拟创建桌面完毕:' + IntToStr(desktopHandle));
    showMessage('指定程序已经运行:' + FileName);
  end
  else
  begin
    showMessage('虚拟创建失败,指定程序没能运行!');
  end;

end;

未完待续,后面会加入FreePascal实现的代码。。。

posted on 2020-09-09 10:36  sunylat  阅读(578)  评论(0编辑  收藏  举报