求Delphi中createprocess、pipe、winexec、shellexecute的详细用法

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了求Delphi中createprocess、pipe、winexec、shellexecute的详细用法相关的知识,希望对你有一定的参考价值。

三个SDK函数: WinExec,ShellExecute ,CreateProcess可以实现调用其他程序的要求,其中以WinExec最为简单,ShellExecute比WinExec灵活一些,CreateProcess最为复杂。

WinExec 两个参数,前一个指定路径,后一个指定显示方式。
ShellExecute 可以指定工作目录,并且还可以寻找文件的关联直接打开不用加载与文件关联的应用程序,ShellExecute还可以打开网页,启动相应的邮件关联发送邮件等等。
CreateProcess 一共有十个参数,不过大部分都可以用NULL代替,它可以指定进程的安全属性,继承信息,类的优先级等等。如果我们要得到足够多的关于新的进程的信息,控制新的进程的细节属性,若要达到这些目的,我们就需要使用CreateProcess函数了。

三个SDK函数( WinExec、ShellExec、CrateProcess )的语法:
WinExec
这个函数最简单,只有两个参数,原型如下:
UINT WinExec(
LPCSTR lpCmdLine, // 命令路径
UINT uCmdShow // 显示方式
);
使用方法如下:
WinExec("Notepad.exe", SW_SHOW); // 打开记事本
WinExec("D:\\Program Files\\Test\\Test.exe",SW_SHOWMAXIMIZED); // 以最大化的方式打开Test.exe
需要注意的是若用 SW_SHOWMAXMIZED 方式去加载一个无最大化按钮的程序,譬如Neterm,Calc 等等,就不会出现正常的 窗体,但是已经被加到任务列表里了。

ShellExecute
原型如下:
HINSTANCE ShellExecute(
HWND hwnd, //父窗口句柄
LPCTSTR lpOperation, //操作, 打开方式 "edit","explore","open","find","print","NULL"
LPCTSTR lpFile, //文件名,前面可加路径
LPCTSTR lpParameters, //参数
LPCTSTR lpDirectory, //默认文件夹
INT nShowCmd //显示方式
);
使用方法如下:
ShellExecute(NULL,"open","C:\\Test.txt",NULL,NULL,SW_SHOWNORMAL); // 打开C:\Test.txt 文件
ShellExecute(NULL, "open", "http://www.google.com",/ NULL, NULL, SW_SHOWNORMAL); // 打开网页www.google.com
ShellExecute(NULL,"explore", "D:\\C++",NULL,NULL,SW_SHOWNORMAL); // 打开目录D:\C++
ShellExecute(NULL,"print","C:\\Test.txt",NULL,NULL, SW_HIDE); // 打印文件C:\Test.txt
ShellExecute不支持定向输出。

CreateProcess
原型如下:
BOOL CreateProcess(
LPCTSTR lpApplicationName, //执行程序名
LPTSTR lpCommandLine, // 参数行
//下面两个参数描述了所创建的进程和线程的安全属性,如果为NULL则使用默认的安全属性
LPSECURITY_ATTRIBUTES lpProcessAttributes, // process security attributes
LPSECURITY_ATTRIBUTES lpThreadAttributes, // thread security attributes
BOOL bInheritHandles, // 继承标志
DWORD dwCreationFlags, // 创建标志
LPVOID lpEnvironment, // 环境变量
LPCTSTR lpCurrentDirectory, // 运行该进程的初始目录
LPSTARTUPINFO lpStartupInfo, // 用于在创建子进程时设置各种属性
LPPROCESS_INFORMATION lpProcessInformation //用于在进程创建后接受相关信息
);
使用方法如下:
PROCESS_INFORMATION pi;
STARTUPINFO si;
memset(&si,0,sizeof(si));
si.cb=sizeof(si);
si.wShowWindow=SW_SHOW;
si.dwFlags=STARTF_USESHOWWINDOW;
bool fRet=CreateProcess("D:\\putty.exe",NULL,NULL,FALSE,NULL,NULL,NULL,NULL,&si,&pi);
可以看出,通过上面的几个不同的方法,都可以实现在应用程序中打开其他应用程序的目的,其中有些方法可能会麻烦一点,所以就需要我们根据不同的目的去选择最适合自己的方法去实现自己的目的!

关于三个SDK函数: WinExec, ShellExecute,CreateProcess 的其他注意事项:
1、定义头文件
在头文件stdafx.h中必须定义以下两个头文件:
#include <shlobj.h> // 可替换为 windows.h
#include <shellapi.h>
如果定义了头文件 #include <windows.h>的话就不必定义 #include <shlobj.h>了,"windows.h" 不光是包含了"shellapi.h",它还定义了许多数据类型,如果没有这些数据类型,shellapi.h本身会出错。
2、定义路径
C++中所表示的路径要用 " \\ "而不是平常所用的" \ ",所以以上三个函数表示路径都为:
Disk:\\Directory\\...\\File name
WinExec("D:\\Program Files\\Test\\Test.exe",SW_SHOWMAXIMIZED);
ShellExecute(NULL,"open","C:\\Test.txt",NULL,NULL,SW_SHOWNORMAL);
bool fRet=CreateProcess("D:\\putty.exe",NULL,NULL,FALSE,NULL,NULL,NULL,NULL,&si,&pi);

///////////////////////////////////////////////////////////////
WinAPI: WinExec - 运行外部程序
//声明
WinExec(
lpCmdLine: LPCSTR; 文件名和参数; 如没指定路径会按以下顺序查找: 程序目录/当前目录/System32/Windows/PATH环境变量
uCmdShow: UINT 启动选项
): UINT;
//返回值:
大于 31 调用成功
等于 0 内存不足
ERROR_FILE_NOT_FOUND = 2; 文件名错误
ERROR_PATH_NOT_FOUND = 3; 路径名错误
ERROR_BAD_FORMAT = 11; EXE 文件无效
//uCmdShow 参数可选值:
SW_HIDE = 0; 隐藏, 并且任务栏也没有最小化图标
SW_SHOWNORMAL = 1; 用最近的大小和位置显示, 激活
SW_NORMAL = 1; 同 SW_SHOWNORMAL
SW_SHOWMINIMIZED = 2; 最小化, 激活
SW_SHOWMAXIMIZED = 3; 最大化, 激活
SW_MAXIMIZE = 3; 同 SW_SHOWMAXIMIZED
SW_SHOWNOACTIVATE = 4; 用最近的大小和位置显示, 不激活
SW_SHOW = 5; 同 SW_SHOWNORMAL
SW_MINIMIZE = 6; 最小化, 不激活
SW_SHOWMINNOACTIVE = 7; 同 SW_MINIMIZE
SW_SHOWNA = 8; 同 SW_SHOWNOACTIVATE
SW_RESTORE = 9; 同 SW_SHOWNORMAL
SW_SHOWDEFAULT = 10; 同 SW_SHOWNORMAL
SW_MAX = 10; 同 SW_SHOWNORMAL
--------------------------------------------------------------------------------
//举例, 启动记事本:
procedure TForm1.Button1Click(Sender: TObject);
begin
WinExec('notepad.exe', SW_SHOWNORMAL);
end;
参考技术A
ShellExecute(
HWND hwnd, //父窗口句柄
LPCSTR lpOperation, //操作类型
LPCSTR lpFile, //要进行操作的文件或路径
LPCSTR lpParameters, //当lpOperation为“explore”时指定要传递的参数,通常设为NULL
LPCSTR lpDirectory, //指定默认目录,通常设为NULL
INT nShowCmd //文件打开的方式,以通常方式还是最大化或最小化显示
)
例子如下:

//调用计算器
ShellExecute(NULL,"open","calc.exe",NULL,NULL,SW_SHOWNORMAL);

//调用记事本
ShellExecute(NULL,"open","NOTEPAD.EXE",NULL,NULL,SW_SHOWNORMAL);

如何在 Delphi Prism 中调用函数 CreateProcess?

【中文标题】如何在 Delphi Prism 中调用函数 CreateProcess?【英文标题】:How to call function CreateProcess in Delphi Prism? 【发布时间】:2010-04-25 14:22:45 【问题描述】:

我写的

function CreateProcess(
            lpApplicationName:String;
            lpCommandLine:String;
            lpProcessAttributes:IntPtr;
            lpThreadAttributes:IntPtr;
            bInheritHandles:Boolean;
            dwCreationFlags:Int32;
            lpEnvironment:IntPtr;
            lpCurrentDirectory:IntPtr;
            lpStartupInfo:STARTUPINFO;
            lpProcessInformation:ProcessInfo):Boolean;
         external 'kernel32.dll';

但 VStudio 说“分号”预期 - 在外部和“预期结束”在 'kernel32.dll' 之后; 你能帮我加载和调用一个函数吗?

【问题讨论】:

【参考方案1】:

为什么不使用 .NET Process Class .. 在这种情况下使用互操作没有多大意义,因为您已经在使用 Delphi Prism..

http://msdn.microsoft.com/en-us/library/system.diagnostics.process.aspx

【讨论】:

+1; .NET 的重点不是学习一门编程语言,而是学习.NET Framework 中的内容并加以利用。 .NET 框架非常庞大:en.wikipedia.org/wiki/.NET_Framework【参考方案2】:

@Ilya,您在调用外部函数时使用了错误的语法。您需要使用 DllImport 关键字才能使 Windows 互操作正常工作。

你必须将你的函数重写为

[DllImport("kernel32.dll")]
class function CreateProcess(
            lpApplicationName:String;
            lpCommandLine:String;
            lpProcessAttributes:IntPtr;
            lpThreadAttributes:IntPtr;
            bInheritHandles:Boolean;
            dwCreationFlags:Int32;
            lpEnvironment:IntPtr;
            lpCurrentDirectory:IntPtr;
            lpStartupInfo:STARTUPINFO;
            lpProcessInformation:ProcessInfo):Boolean; external;

检查这个工作示例

namespace ConsoleApplication20;

interface
uses
    System.Diagnostics,
    System.Runtime.InteropServices;


type
PROCESS_INFORMATION =record
    hProcess    : IntPtr;
    hThread     : IntPtr;
    dwProcessId : UInt32;
    dwThreadId  : UInt32;
end;



STARTUPINFO =record
     cb       : UInt32;
    lpReserved: String;
    lpDesktop : String;
    lpTitle   : String;
    dwX       : UInt32;
    dwY       : UInt32;
    dwXSize   : UInt32;
    dYSize    : UInt32;
    dwXCountChars   : UInt32;
    dwYCountChars   : UInt32;
    dwFillAttribute : UInt32;
    dwFlags         : UInt32;
    wShowWindow : ShortInt;
    cbReserved2 : ShortInt;
    lpReserved2 : IntPtr;
    hStdInput   : IntPtr;
    hStdOutput  : IntPtr;
    hStdError   : IntPtr;
end;

  ConsoleApp = class
  private
    [DllImport("kernel32.dll")]
    class method CreateProcess( lpApplicationName: string;  lpCommandLine:string;  lpProcessAttributes:IntPtr; lpThreadAttributes:IntPtr;
                        bInheritHandles:Boolean;dwCreationFlags: UInt32;  lpEnvironment:IntPtr;
                        lpCurrentDirectory:string;var lpStartupInfo:STARTUPINFO;out lpProcessInformation:PROCESS_INFORMATION) : boolean; external;
  public
    class method Main;
  end;

implementation

class method ConsoleApp.Main;
var
lpStartupInfo        : STARTUPINFO;
lpProcessInformation : PROCESS_INFORMATION;
begin
        lpStartupInfo := new STARTUPINFO();
        lpProcessInformation := new PROCESS_INFORMATION();
        Console.WriteLine('Creating Process');
        CreateProcess('C:\WINDOWS\SYSTEM32\notepad.exe', nil, IntPtr.Zero, IntPtr.Zero, false, 0, IntPtr.Zero, nil, var lpStartupInfo, out lpProcessInformation);
        Console.ReadLine();
end;

end.

查看论文链接了解更多信息

Platform Invoke Tutorial A Closer Look at Platform Invoke

【讨论】:

以上是关于求Delphi中createprocess、pipe、winexec、shellexecute的详细用法的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Delphi Prism 中调用函数 CreateProcess?

如何将字符串或信息发送到我在 Delphi 7 中使用 Createprocess 打开的进程

Delphi:如何使用进度条显示 CreateProcess 的进度?

Delphi - 优雅地关闭服务中创建的进程。 (使用 tprocess / createProcess)

我可以访问从 Delphi CreateProcess 命令返回的字符串吗?

Delphi 使用CreateProcess创建进程并弹出进程PID值