Поведение, которое вы видите - это документ MSDN для функции CreateProcessWithLogon
Win32, которая работает в фоновом режиме при запуске процесса для другого пользователя (используя System.Diagnostics.Process
):
Указатель на блок среды для нового процесса.Если этот параметр имеет значение NULL, новый процесс использует среду, созданную из профиля пользователя, указанного в lpUsername.
Так что, как только вы укажете одну переменную среды дляновый процесс, вам нужно указать их все.
Проблема теперь заключается в свойстве ProcessStartInfo.EnvironmentVariables
.Как только вы обращаетесь к нему в первый раз (для данного экземпляра ProcessStartInfo), он будет автоматически заполнен полной средой для текущего пользователя ( ref ).
Взять эту строку, который запускается в контексте пользователя "podosta":
p.EnvironmentVariables.Add("MY_NEW_VARIABLE", "SOME_TEXT");
Он делает две вещи:
- заполняет
p.EnvironmentVariables
средой "podosta" (включая "USERPROFILE = ... podosta "). - Добавьте к этому новую переменную" MY_NEW_VARIABLE = SOME_TEXT ".
Этот объединенный набор затем передается процессу, запущенному как" myuser "и, таким образом, он получает «неправильное» (лучше: неожиданное) значение для «USERPROFILE».
Если вы хотите убедиться, что передали блок окружения NULL
базовой функции Win32, чтобы получить поведениеописанный в приведенной выше цитате, вы никогда не сможете «дотронуться» до свойства EnvironmentVariables
- даже не повторять и не выгружать его для целей ведения журнала.
Этого также недостаточно для EnvironmentVariables.Clear()
.Это не установит для внутреннего поля значение null
, и функции CreateProcessWithLogon
будет просто передан пустой блок окружения, но не нулевой.
Если вам не удастся сделать это, вы получите все виды смешныхповедения, например, тогда выполняющийся процесс будет иметь значение для USERPROFILE
, то есть для пользователя, который запустил процесс, и т. д.
Вы можете обойти это, вызвав CreateEnvironmentBlock
через p /invoke, добавьте переменные окружения по мере необходимости, затем вызовите CreateProcessAsUser
(также через p / invoke), передав эту измененную среду.Это нелегкое дело, особенно если вам нужны все функции Process
-класса, такие как перенаправление вывода и т. Д.
К сожалению, свойство ProcessStartInfo.EnvironmentVariables
работает так же, как и оно.