当IDE与启动器启动应用程序时,为什么命令行参数的数量会发生变化?

Fab*_*ujo 2 delphi command-line-arguments delphi-xe2 delphi-ide

考虑以下命令行参数

"alfa" "beta" "4"
Run Code Online (Sandbox Code Playgroud)

当我为我正在工作的项目指定Run> Parameters ...时,应用程序在Process Explorer上显示为命令行:

"c:\myapp\myapp.exe" "alfa" "beta" "4"
Run Code Online (Sandbox Code Playgroud)

ParamCount显示4个参数.但是当我从启动器应用程序(执行访问控制)启动相同的可执行文件时,Process Explorer显示:

"alfa" "beta" "4"
Run Code Online (Sandbox Code Playgroud)

ParamCount显示3个参数.命令行是从启动器应用程序中提取的.理论上它可以工作,因为从启动器启动应用程序工作完美无缺.从IDE启动时,它尝试在"4"上面执行StrToInt ,但只检索"beta"参数.

来自启动器应用程序的示例代码:

var
  StartupInfo: TSTARTUPINFO;
  ProcessInfo: PROCESS_INFORMATION;
  CurrentDirPath: String;
begin
  Result := 0;
  ZeroMemory(@StartupInfo, SizeOf(StartupInfo));
  StartupInfo.cb := SizeOf(StartupInfo);
  DirCorrente := ExtractFilePath(sExe);

  if CreateProcess(PChar(sExe), PChar(sParam), nil, nil, true,
    NORMAL_PRIORITY_CLASS, nil, PChar(CurrentDirPath),
    StartupInfo, ProcessInfo) then
Run Code Online (Sandbox Code Playgroud)

sParam的内容是上面的命令行参数,sExe是可执行路径.为什么会这样?

注意:我已经设计了如何将命令行参数解释更改为此边缘情况的健壮 - 这里的重点是为什么会发生这种情况.

Rob*_*edy 5

您的启动程序未CreateProcess正确调用.请考虑文档中的摘录(强调添加):

如果lpApplicationName和lpCommandLine都是非NULL,则lpApplicationName指向的以null结尾的字符串指定要执行的模块,lpCommandLine指向的以null结尾的字符串指定命令行.新进程可以使用GetCommandLine来检索整个命令行.用C编写的控制台进程可以使用argc和argv参数来解析命令行.因为argv [0]是模块名称,所以C程序员通常会重复模块名称作为命令行中的第一个标记.

忽略"C程序员"; 它适用于为Windows编写程序的每个人,无论语言如何.

您的启动程序为lpApplicationName和lpCommandLine参数提供了值,但它没有遵循重复程序文件名作为命令行中第一个参数的约定.Delphi ParamStrParamCount函数知道遵循约定,因此它们跳过命令行上的第一个标记.如果调用者没有遵循惯例,那么接收者最终认为预期的第二个参数实际上是第一个,第三个实际上是第二个,依此类推.

  • 如果您的程序将*仅*由您的启动器启动,并且您的启动器将*仅启动您控制的程序,那么您可以将所有内容保留为今天的状态.即,您可以选择忽略提供程序名称作为第一个参数的约定.只有在控制整个系统时它才是安全的.它不支持以其他方式启动程序(如Windows资源管理器,cmd.exe或Delphi的调试程序).如果您的系统一直错误地解释命令行参数,它只会"崩溃整个系统".我认为*那是你应该解决的问题. (2认同)