我们想要D7中的一个程序知道它是从我们的某个应用程序通过ShellExecute命令运行,还是由用户直接启动.
有没有可靠的方法让Delphi 7程序确定运行它的程序的名称?
我们当然可以让我们的父程序使用命令行参数或其他标志,但我们更喜欢上述方法.
TIA
我害怕,没办法做你想做的事.不通过命令行,快捷方式或在资源管理器中双击来通知应用程序是通过ShellExecute(或CreateProcess)以编程方式运行应用程序.
如果我没记错的话,Raymond Chen在这个话题上做了一篇文章.我会看看我是否能找到它并在这里更新我的答案.
基于另一个答案和Torry.net上的一些代码,我来到了此函数来获取父进程ID。它似乎在Windows 7上返回了一个相关的数字,并且它使用的Windows函数至少应该在Win 2000以后才可用。
uses Tlhelp32;
function GetProcessInfo(ProcessId: Cardinal; out ParentProcessId: Cardinal; out ExeFileName: string): Boolean;
var
hSnapShot: THandle;
ProcInfo: TProcessEntry32;
begin
hSnapShot := CreateToolHelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnapShot <> THandle(-1)) then
try
ProcInfo.dwSize := SizeOf(ProcInfo);
if (Process32First(hSnapshot, ProcInfo)) then
repeat
if ProcInfo.th32ProcessID = ProcessId then
begin
ExeFileName := string(ProcInfo.szExeFile);
ParentProcessId := ProcInfo.th32ParentProcessID;
Result := True;
Exit;
end;
until not Process32Next(hSnapShot, ProcInfo);
finally
CloseHandle(hSnapShot);
end;
Result := False;
end;
procedure Test;
var
ProcessId, ParentProcessId, Dummy: Cardinal;
FileName: string;
begin
ProcessId := GetCurrentProcessId();
// Get info for current process
if GetProcessInfo(ProcessId, ParentProcessId, FileName) then
// Get info for parent process
if GetProcessInfo(ParentProcessId, Dummy, FileName) then
// Show it.
ShowMessage(IntToStr(ParentProcessId) + FileName);
end;
Run Code Online (Sandbox Code Playgroud)
请注意!父进程可能不再存在。更糟糕的是,它的ID可能已被回收,导致此功能给您的进程不同于您要求的进程。
简单回答是不”。
更复杂的答案是“不像简单地传递命令行参数那么容易”。
:)
您需要做的是识别您的进程的父进程。获得这一点是可能的,但并不简单。有关如何进行操作的详细信息,请参阅这篇 CodeProject 文章。
最大的问题是Windows中的进程之间没有严格的层次关系,PID(进程ID)可能会被重复使用。您标识为“父级”的 PID 可能根本不是您的父级。如果父进程随后终止,那么它的 PID 可能会被重新使用,这可能会导致一些看似令人困惑的结果(“我的进程是由 calc.exe 启动的?这怎么可能?”)。
尝试找到防弹、防水和防白痴的机制来防止此类过程可能失败,这比简单地在启动器应用程序和启动程序之间设计和实现基于命令行的约定要花费更多的精力,后者可以通过该约定来识别启动程序。以前的。
命令行参数就是这样的选项之一,但可能会被“欺骗”(如果有人弄清楚您在命令行上传递的内容,并且由于某种原因可以通过模仿它自己来获得一些价值或好处)。
然而,根据您需要该机制的可靠性和防篡改程度,这仍然足够了。