Как использовать или расширять переменные среды в команде, созданной CreateProcess?

Следующий код использует CreateProcess для запуска команд с переменными окружения. Здесь он пытается запустить notepad %APPDATA%\test.txt.

Если я запущу notepad %APPDATA%\test.txt непосредственно в Windows' CMD, %APPDATA% будет расширен. Однако переменная среды не может быть расширена при выполнении CreateProcess. Не могли бы вы помочь прокомментировать причину и обходной путь? Любой комментарий будет оценен!

непосредственно в cmdиспользовать CreateProcess

    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.

person SOUser    schedule 27.03.2012    source источник


Ответы (1)


Вызовите ExpandEnvironmentStrings, чтобы расширить переменные окружения.

Когда вы используете cmd.exe, он выполняет расширение за вас. CreateProcess этого не делает, поэтому вам нужно будет сделать это перед вызовом CreateProcess. В качестве альтернативы вы можете использовать ShellExecute, который расширит строки среды.

Ваш текущий код не соответствует контракту CreateProcess. Второй параметр должен быть указателем на модифицируемую память. Вы можете избежать этого, если вы используете ANSI API, но при нацеливании на Unicode ваш код может дать сбой. Передайте указатель на изменяемую память, а не указатель на литерал. Если вы добавили вызов для расширения переменных среды, вы получите изменяемую строку.

Наконец, похоже, что вы просто пытаетесь открыть текстовый файл. Зачем заставлять пользователя просматривать его в Блокноте? Мой редактор по умолчанию для текстовых файлов не Блокнот. Я ненавижу любую программу, которая навязывает мне Блокнот. Вместо этого позвольте оболочке открыть файл в предпочитаемом пользователем редакторе. Вызовите ShellExecute, используйте «открыть» в качестве глагола и передайте имя текстового файла в качестве параметра имени файла. С другой стороны, возможно, вы все это знаете, и это просто пример кода. Если да, то просто игнорируйте этот совет.

person David Heffernan    schedule 27.03.2012
comment
Большое спасибо за грамотные комментарии!! :) - person SOUser; 29.03.2012