为啥 CreateProcess 中的 cmd.exe 的行为与 DOS 提示符不同?

Posted

技术标签:

【中文标题】为啥 CreateProcess 中的 cmd.exe 的行为与 DOS 提示符不同?【英文标题】:why does cmd.exe in CreateProcess behaves different from DOS-prompt?为什么 CreateProcess 中的 cmd.exe 的行为与 DOS 提示符不同? 【发布时间】:2014-11-15 11:35:52 【问题描述】:

我使用Altar的GetDOSOutput()(变体1)到this question通过一个简单的delphi程序调用dos-commands。然而,现有的 DOS 程序,如 DiskPart,在被 CreateProcess 调用时找不到,而从 DOS 提示符(Windows server 2003 X64)调用时它们没有问题。这可能是什么原因?

命令行:`ListVolumes.bat'

ListVolumes.bat:

path
C:\WINDOWS\SYSTEM32\DiskPart.exe /s ListVolumes.scr
dir C:\WINDOWS\SYSTEM32\DiskPart.exe

通过程序调用输出:

I:\PartScan>path
PATH=C:\WINDOWS;C:\WINDOWS\System32;C:\WINDOWS\System32\wbem;C:\Program Files (x86)\Borland\Delphi7\Bin; C:\Program Files (x86)\Borland\Delphi7\Projects\Bpl\;

I:\PartScan>C:\WINDOWS\SYSTEM32\DiskPart.exe /s ListVolumes.scr
'C:\WINDOWS\SYSTEM32\DiskPart.exe' is not recognized as an internal or external command,
operable program or batch file.

I:\PartScan>dir C:\WINDOWS\SYSTEM32\DiskPart.exe
 Volume in drive C is system
 Volume Serial Number is 351F-0221

 Directory of C:\WINDOWS\SYSTEM32

File Not Found

从 DOS 提示符调用时的输出(注意最后的 dir 命令):

PATH=C:\WINDOWS;C:\WINDOWS\System32;C:\WINDOWS\System32\wbem;C:\Program Files (x86)\Borland\Delphi7\Bin; C:\Program Files (x86)\Borl
and\Delphi7\Projects\Bpl\;

I:\PartScan>C:\WINDOWS\SYSTEM32\DiskPart.exe /s ListVolumes.scr

Microsoft DiskPart version 5.2.3790.3959
Copyright (C) 1999-2001 Microsoft Corporation.
On computer: ISOETES

  Volume ###  Ltr  Label        Fs     Type        Size     Status     Info
  ----------  ---  -----------  -----  ----------  -------  ---------  --------
  Volume 0     F                       DVD-ROM         0 B  Healthy
  ...
  Volume 11    G                       DVD-ROM         0 B  Healthy

I:\PartScan>dir C:\WINDOWS\SYSTEM32\DiskPart.exe
 Volume in drive C is system
 Volume Serial Number is 351F-0221

 Directory of C:\WINDOWS\SYSTEM32

17-Feb-2007  08:17           263,680 diskpart.exe
               1 File(s)        263,680 bytes
               0 Dir(s)  33,111,334,912 bytes free

【问题讨论】:

如果我们可以停止调用控制台应用程序 DOS 程序,那就太好了。不再有 DOS。 或者更确切地说,DOS 确实存在,但大多数所谓的 DOS 确实不存在。 解决方法很简单,用Sysnative文件夹代替system32目录... 据我了解,在 Vista 之前没有引入 SysNative。目标机器运行服务器 2003x64。 是的,在您的坚持不懈的推动下,我进一步寻找。起初我只发现了更多的声明,在这个版本中是不可能的,到那时我到达了你在我不在时发布的同一个 kb 页面。荣誉是应得的:它是一种魅力。我似乎无法通过 CLI 进行测试,因为那时不涉及 WOW64。但是将 cmd.exe 称为“C:\windows\Sysnative\cmd.exe”就可以了。 【参考方案1】:

您没有显示代码,因此我们无法 100% 确定地诊断此问题。但是,可能的原因是您的进程是在 WOW64 模拟器下运行的 32 位进程。当您在模拟器下创建cmd 进程时,您将获得一个同样在模拟器下运行的 32 位 cmd 进程。您正在将其与 64 位进程进行比较。请注意,在模拟器下,system32 被文件系统重定向器重定向到 SysWOW64

您处理这个问题的方法是创建一个 64 位进程。从模拟器内部创建时,对于 cmd 来说,这非常棘手。最简单的方法是从 64 位进程调用 CreateProcess

由于您使用 Delphi 7,您可能需要使用现代编译器来制作一个小型 64 位可执行文件来为您完成工作。从您的 Delphi 7 程序中调用小型可执行文件。

另一种可能满足您需求的方法是使用 sysnative 别名从模拟器内部访问 64 位系统目录。这在file system redirector documentation 中有描述。

【讨论】:

代码从***.com/questions/1454501/…复制粘贴。 这似乎确实是问题所在。 XE2/64 编译的相同程序代码按预期工作。谢谢。 好的,但我们不知道你是怎么称呼它的。所以给出一个 MCVE 总是有用的。 结果 := GetDOSoutput('test.bat'); --- 如果你能从中学到什么,我想你可以教给我更多。

以上是关于为啥 CreateProcess 中的 cmd.exe 的行为与 DOS 提示符不同?的主要内容,如果未能解决你的问题,请参考以下文章

CreateProcess 适用于某些计算机,而不适用于其他计算机。为啥?

为啥 CreateProcess 给出错误 193(%1 不是有效的 Win32 应用程序)

createprocess中的Process.arguments?

CreateProcess : 应用程序路径中的转义空格

CreateProcess 和 WaitForSingleObject 在两个 PDF 文件中的第二个失败

CreateProcess 函数中的问题!