以下代码利用CreateProcess
运行带有环境variables的命令。 在这里,它试图运行notepad %APPDATA%\test.txt
。
如果我在notepad %APPDATA%\test.txt
直接运行notepad %APPDATA%\test.txt
,%APPDATA%将被展开。 但是,由CreateProcess
执行时,环境variables不能被扩展。 你能帮忙评论一下原因和解决办法吗? 任何评论将不胜感激!
program TestConsole2; {$APPTYPE CONSOLE} uses Windows, SysUtils; var I: Integer; ProgramName: String; StartInfo : TStartupInfo; ProcInfo : TProcessInformation; CreateOK : Boolean; begin try FillChar(StartInfo, SizeOf(StartInfo), #0); FillChar(ProcInfo, SizeOf(ProcInfo), #0); StartInfo.cb := SizeOf(StartInfo); ProgramName := 'NOTEPAD %APPDATA%\test.txt'; CreateOK := CreateProcess( nil, PChar(ProgramName), nil, nil, True, 0, nil, nil, StartInfo, ProcInfo); if CreateOK then WaitForSingleObject(ProcInfo.hProcess, INFINITE); Readln(ProgramName); except on E: Exception do Writeln(E.ClassName, ': ', E.Message); end; end.
调用ExpandEnvironmentStrings来扩展环境变量。
当您使用cmd.exe时,它会为您执行扩展。 CreateProcess不会,所以你需要在调用CreateProcess之前做。 或者,你可以使用ShellExecute来扩展环境字符串。
您当前的代码不符合CreateProcess的合同。 第二个参数必须是可修改内存的指针。 如果你使用的是ANSI API,那么你可以避开这个问题,但是当你使用Unicode时,你的代码很可能会失败。 将指针传递给可修改的内存,而不是指向文字的指针。 如果你添加了一个调用来扩展环境变量,那么你最终会得到一个可修改的字符串。
最后,看起来你只是想打开一个文本文件。 为什么强迫用户在记事本中查看它? 我的文本文件的默认编辑器不记事本。 我不喜欢任何强迫记事本的程序。 而是让shell在用户首选的编辑器中打开文件。 调用ShellExecute,使用“打开”作为动词并传递文本文件名作为文件名参数。 另一方面,也许你知道这一切,这只是示例代码。 如果是这样,请忽略这个建议。