CreateProcess时不显示或者不创建窗口 (或用虚拟桌面实现后台调用外部程序)...

从网上搜了很多总结了三种方法,希望对大家有用:
网上常见的两种方法(详细说明参考:http://blog.163.com/zhucongdzkd@126/blog/static/1399971932010780309154/)。

【方法一:】
将 CreateProcess()的参数dwCreationFlags指定为CREATE_NO_WINDOW,即以不创建窗口方式创建DOS进程。
【参考代码:】
if (!CreateProcess(NULL, szCommand, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi))

【方法二:】
指定STARTUPINFO结构中WORD wShowWindow为SW_HIDE(但是一定要有这一句: si.dwFlags = STARTF_USESHOWWINDOW|STARTF_USESHOWWINDOW; ),即以不显示窗口方式创建DOS进程。
【参考代码:】
STARTUPINFO si;
PROCESS_INFORMATION pi;
::ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
si.dwFlags = STARTF_USESHOWWINDOW|STARTF_USESHOWWINDOW;
si.wShowWindow = SW_HIDE;
::ZeroMemory(&pi, sizeof(pi));
if (!CreateProcess(NULL, szCommand, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))

【方法三:】
将这个DOS窗口放到另外一个桌面上,实现隐藏。
【参考代码:】
si.lpDesktop="NewDesktop";
if (!CreateProcess(NULL, szCommand, NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi))
方法三的详细原理:
参考http://blog.163.com/madengyao_super/blog/static/2859822020093249493150/ 。



===============================================================================
【用虚拟桌面实现后台调用外部程序】
最近需要实现一个无线通信的功能,X他XX的,该死的硬件厂商竟然不提供接口函数,只提供一个EXE可执行文件-_-!
这样就需要我在程序里调用他的这个EXE可执行文件。
调用EXE文件,可以用WINEXEC()、SHELLEXECUTE()和CreateProcess()等函数来实现,我这里就用CreateProcess()来调用。
但是一个软件,两个EXE文件,这叫什么??实在没办法,我想在打开的时候不让用户看到这个执行文件:首先调用FINDWINDOW来查找窗口的句柄,之后再用SendMessage()来隐藏窗口,但是还是会有一瞬主窗口被显示出来的,或许你会说我BT吧,但是我实在是不忍心看到……
那么怎么解决这个问题呢,首先我当然在CreateProcess()上面寻找方法,可惜,它只有一个参数可以设置窗口的默认显示方式,但是一旦这个窗口自己重设了显示方式,它就没有任何作用了。
继续查找文档,这时我看到CreateProcess()的一个参数TStartupInfo中有 lpDesktop这么一个属性,按照MSDN的说法,如果该指针为NULL,那么新建的Process将在当前Desktop上启动,而如果对其赋了一个Desktop的名称后,Process将在指定的Desktop上启动,恩,看来不错,就从它入手了;
首先,建立一个虚拟的Desktop。
const
DesktopName: PChar = 'NewDesktop';
FDesktop:= CreateDesktop(DesktopName, nil, nil, 0, GENERIC_ALL, nil);
然后,在CreateProcess的时候,指定程序在我新生成的Desktop上运行:
var
SI: TStartupInfo;
begin
FillChar(SI, SizeOf(SI), 0);
SI.cb:= SizeOf(SI);
SI.lpDesktop:= DesktopName;
SI.wShowWindow:= SW_HIDE;
SI.dwFlags:= STARTF_USESHOWWINDOW;
SI.hStdError:= 0;
SI.hStdInput:= 0;
SI.hStdOutput:= 0;
  if not CreateProcess(PChar('……'), nil, nil, nil, True, CREATE_NEW_CONSOLE + HIGH_PRIORITY_CLASS, nil,
                       PChar('……'), SI, FProceInfo) then
    begin
      Application.MessageBox('Error', 'Error', $10);
      Exit;
    end;
end;

再用FindWindow去找程序的主窗口.
开始我直接写下了这样的代码:
WindowHandle:= FindWindow(nil, '……');

但是,这样是找不到不在当前Desktop中的Window的,那怎么办呢?
这个时候,我突然看到一位同事在上班时间偷偷打游戏,我问他:“你不怕被抓到??”
他说:“给你看一个工具!”
原来是一个叫“玩游戏一键隐藏”的小工具,仔细想想,他应该是利用各桌面之间的切换来达到这种效果的,于是又开始查看MSDN,终于看到可以用SetThreadDesktop()函数,这个函数可以设置当前Thread工作所在的Desktop,于是我在以上代码前又加了一句:
if not SetThreadDesktop(FDesktop) then
    begin
      Exit;
    end;
但是,程序运行后,该函数却返回了false,说明方法调用失败了,再仔细看MSDN,发现有这么一句话:
[color=red]The SetThreadDesktop function will fail if the calling thread has any windows or hooks on its current desktop (unless the hDesktop parameter is a handle to the current desktop).[/color]

对不起,我的E文水平实在有够呛-_-!!
具体是什么意思我就不太清楚了,PASSION帮我翻译的时候,我也没怎么记得,只记得是要切换Desktop的线程要“干净”。
不好意思,我对这个“干净”的理解就是一个新的线城,于是抱着试一试的心情,我写下了:
  TFindWindowThread = class(TThread)
  private
    FDesktop, FWindowHandle: THandle;
  protected
    procedure Execute(); override;
  public
    constructor Create(Suspended: Boolean; const ADesktop: THandle); reintroduce;
    property WindowHandle: THandle read FWindowHandle;
  end;

而主程序中的代码变成这样:
FindWindowThread:= TFindWindowThread.Create(False, FDesktop);
  try
    FindWindowThread.WaitFor;
    WindowHandle:= FindWindowThread.WindowHandle;
  finally
    FindWindowThread.Free;
  end;
  if WindowHandle = 0 then
    begin
      Application.MessageBox('Error', 'Error', $10);
      Exit;
    end;

呵呵,成功,这样果然可以顺利的找到窗口Handle了。
好了,这样就几乎完美的实现了一个后台调用程序的功能,它对最终客户来说将是完全透明的,客户根本感觉不到后台还有另一个程序在工作。
 

转载于:https://my.oschina.net/u/1777508/blog/1796694

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 您好!下面是使用Nim语言调用Windows下calc.exe程序的示例代码: ```nim import os let calcPath = "C:\\Windows\\System32\\calc.exe" # calc.exe的路径 if os.exists(calcPath): let process = execProcess(calcPath) # 执行calc.exe waitForProcess(process) # 等待calc.exe进程结束 else: echo "calc.exe不存在" ``` 这段代码首先定义了calc.exe程序的路径,然后判断该路径是否存在。如果存在,就使用`execProcess`函数执行calc.exe程序,并使用`waitForProcess`函数等待程序执行完毕;如果不存在,就输出一个提示信息。请注意,`calc.exe`的路径可能因系统版本或安装位置不同而有所不同,您需要根据自己的实际情况修改路径。 ### 回答2: 使用Nim语言可以通过调用Windows API来实现调用 calc.exe 程序。下面是实现此功能的代码示例: ```nim import os import winim proc main() = var cmd = "calc.exe" var si: STARTUPINFOW var pi: PROCESS_INFORMATION winim.ZeroMemory(addr(si), sizeof(si)) si.cb := sizeof(si) if CreateProcessW( nil, cmd.toWideCString(), nil, nil, false, 0, nil, nil, addr(si), addr(pi) ) == false: let errorCode = GetLastError() echo "无法启动 calc.exe, 错误码: ", errorCode else: echo "calc.exe 已启动" WaitForSingleObject(pi.hProcess, INFINITE) CloseHandle(pi.hThread) CloseHandle(pi.hProcess) main() ``` 此代码中,我们首先导入了 `os` 和 `winim` 模块,分别用于调用操作系统的命令和 Windows API。然后我们定义了一个 `main` 过程,在此过程中,我们创建了一个 `STARTUPINFOW` 结构体用来指定启动 calc.exe 的信息,并创建了一个 `PROCESS_INFORMATION` 结构体用来接收启动 calc.exe 后的相关信息。 在 `CreateProcessW` 函数中,我们传入了 `cmd` 参数指定要启动的程序(calc.exe),并传入了 `si` 和 `pi` 参数用来接收启动结果。若启动成功,则通过 `WaitForSingleObject` 函数等待 calc.exe 运行结束,并最后释放相关的资源。 请注意,在使用此代码之前,你需要确保已经安装了 Nim 编译器,并正确安装了 Winim 库。 同,如果该代码不能正常工作,可能是因为 calc.exe 的路径配置问题,你可以尝试使用 calc.exe 的绝对路径或正确配置环境变量后重新运行代码。 ### 回答3: 在Nim语言中,可以通过使用系统模块和`spawn`过程来调用Windows的calc.exe程序。下面是一个简单的示例代码: ```nim import os var processInfo: PROCESS_INFORMATION startupInfo: STARTUPINFO commandLine = "calc.exe" # 初始化startupInfo结构 ZeroMemory(addr(startupInfo), startupInfo.len) startupInfo.cb = sizeof(startupInfo) # 创建新进程 if CreateProcess(nil, cstring(commandLine), nil, nil, false, CREATE_DEFAULT_ERROR_MODE, nil, nil, addr(startupInfo), addr(processInfo)): echo "成功启动calc.exe程序" else: echo "启动calc.exe程序失败:", GetLastError() # 等待进程结束并关闭句柄 WaitForSingleObject(processInfo.hProcess, INFINITE) CloseHandle(processInfo.hProcess) CloseHandle(processInfo.hThread) ``` 这段代码中,首先使用`CreateProcess`函数来启动calc.exe程序。如果成功,将会输出"成功启动calc.exe程序";如果失败,将会输出"启动calc.exe程序失败"并显示错误信息。然后,使用`WaitForSingleObject`函数等待calc.exe程序运行结束,并使用`CloseHandle`函数关闭进程和线程的句柄。 请注意,在运行这段代码之前,确保已经安装了Nim编译器以及相应的Windows SDK,并将calc.exe程序添加到系统PATH环境变量中。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值