SetEnvironmentVariable не работает?
От: Аноним  
Дата: 14.10.09 12:39
Оценка:
есть some.bat
set RRR=0
myConsoleApplication.exe
echo %RRR%


в myConsoleApplication написанном на шарп
есть System.Environment.SetEnvironmentVariable("RRR", "333");

почему после выполнения some.bat %RRR% равно 0? как вернуть в бат нужные environment?
Re: SetEnvironmentVariable не работает?
От: Nuseraro Россия  
Дата: 14.10.09 13:33
Оценка:
Здравствуйте, Аноним, Вы писали:

А>есть some.bat

А>set RRR=0
А>myConsoleApplication.exe
А>echo %RRR%


А>в myConsoleApplication написанном на шарп

А>есть System.Environment.SetEnvironmentVariable("RRR", "333");

А>почему после выполнения some.bat %RRR% равно 0? как вернуть в бат нужные environment?


Почти так как вы думали:
Environment.SetEnvironmentVariable("RRR", "333", EnvironmentVariableTarget.Machine);
Homo Guglens
Re[2]: SetEnvironmentVariable не работает?
От: Аноним  
Дата: 14.10.09 14:03
Оценка:
Здравствуйте, Nuseraro, Вы писали:

N>Здравствуйте, Аноним, Вы писали:


А>>есть some.bat

А>>set RRR=0
А>>myConsoleApplication.exe
А>>echo %RRR%


А>>в myConsoleApplication написанном на шарп

А>>есть System.Environment.SetEnvironmentVariable("RRR", "333");

А>>почему после выполнения some.bat %RRR% равно 0? как вернуть в бат нужные environment?


N>Почти так как вы думали:

N>
N>Environment.SetEnvironmentVariable("RRR", "333", EnvironmentVariableTarget.Machine);
N>


я, тогда, перепробывал все EnvironmentVariableTarget, и это не помогло.
Думаю, проблема в другом
Re[3]: SetEnvironmentVariable не работает?
От: Nuseraro Россия  
Дата: 14.10.09 14:13
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, Nuseraro, Вы писали:


N>>Здравствуйте, Аноним, Вы писали:


А>>>есть some.bat

А>>>set RRR=0
А>>>myConsoleApplication.exe
А>>>echo %RRR%


А>>>в myConsoleApplication написанном на шарп

А>>>есть System.Environment.SetEnvironmentVariable("RRR", "333");

А>>>почему после выполнения some.bat %RRR% равно 0? как вернуть в бат нужные environment?


N>>Почти так как вы думали:

N>>
N>>Environment.SetEnvironmentVariable("RRR", "333", EnvironmentVariableTarget.Machine);
N>>


А>я, тогда, перепробывал все EnvironmentVariableTarget, и это не помогло.

А>Думаю, проблема в другом

У Вас не работает с EnvironmentVariableTarget.Machine? У меня вроде работает. И set, и Environment.GetEnvironmentVariable. Хотя всех тонкостей не знаю. А в общем списке (set без параметров) что показывает?
Можно еще Process.Start просто применить на худой конец наверное...
Homo Guglens
Re[2]: SetEnvironmentVariable не работает?
От: Lloyd Россия  
Дата: 14.10.09 16:49
Оценка:
Здравствуйте, Nuseraro, Вы писали:

А>>почему после выполнения some.bat %RRR% равно 0? как вернуть в бат нужные environment?


N>Почти так как вы думали:

N>
N>Environment.SetEnvironmentVariable("RRR", "333", EnvironmentVariableTarget.Machine);
N>


Для уже работающего процесса вроде как не будет применяться.
Re[2]: SetEnvironmentVariable не работает?
От: Pavel Dvorkin Россия  
Дата: 15.10.09 03:12
Оценка: 3 (1) +2
Здравствуйте, Nuseraro, Вы писали:

N>Почти так как вы думали:

N>
N>Environment.SetEnvironmentVariable("RRR", "333", EnvironmentVariableTarget.Machine);
N>


Вообще-то верно, но в применении к задаче топикстартера ничего не выйдет.

Дело в том, что окружение создается при запуске процесса. Если его изменить для машины, то это повлияет на новые процессы, но не на уже запущенные.

bat — это тоже процесс (реально ntvdm.exe). И запуск myConsoleApplication.exe ничего не изменит в окружении этого процесса на основе bat-файла.

В данном случае надо повлиять на окружение родительского процесса. Легальных средств для этого нет.
With best regards
Pavel Dvorkin
Re[3]: SetEnvironmentVariable не работает?
От: Мизантроп  
Дата: 15.10.09 03:47
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Дело в том, что окружение создается при запуске процесса. Если его изменить для машины, то это повлияет на новые процессы, но не на уже запущенные.


PD>bat — это тоже процесс (реально ntvdm.exe). И запуск myConsoleApplication.exe ничего не изменит в окружении этого процесса на основе bat-файла.


PD>В данном случае надо повлиять на окружение родительского процесса. Легальных средств для этого нет.


Дополню немного, с Вашего разрешения.

Переменные окружения хранятся между сеансами работы в ключах Environment соответствующих веток реестра, отдельно для каждого из пользователей и общие для системы. Блок окружения процесса создаётся при входе пользователя их объединением и далее наследуется от процесса к процессу, если специально не указано иного. Функция WinApi SetEnvironmentVariable изменяет значение только в окружении текущего процесса. Для внесения персистентных изменений, необходимо новое знвчение занести в реестр, что видимо и делает перегруженная версия Environment.SetEnvironmentVariable. Но эти изменения не будут видны другим процессам, в том числе и новым, в существующих сессиях. Чтобы они стали видны, нужно пересоздать блок окружения, то есть в общем случае перелогиниться или перезагрузиться. В принципе, при изменениии настроек принято рассылать WM_SETTINGCHANGE. Но отправить её мало, нужно ещё чтобы получатели отреагировали должным образом, что имеет место далеко не всегда.

Исходя из изложенного, можно из батника передать через окружение новое значение запускаемому им процессу, но не в обратную сторону. Этим, кстати, пользуются CGI приложения. Входные параметры они получают через переменные окружения, а результат пишут в стандартный вывод.
"Нормальные герои всегда идут в обход!"
Re[4]: SetEnvironmentVariable не работает?
От: Pavel Dvorkin Россия  
Дата: 15.10.09 04:39
Оценка:
Здравствуйте, Мизантроп, Вы писали:

М>Дополню немного, с Вашего разрешения.


Поправлю немного, с Вашего разрешения

М>Но эти изменения не будут видны другим процессам, в том числе и новым, в существующих сессиях. Чтобы они стали видны, нужно пересоздать блок окружения, то есть в общем случае перелогиниться или перезагрузиться.


Нет. Проверяем.

Запускаем FAR

C:\>set RRR

Environment variable not defined

Запускаем myConsoleApplication.exe из под админа с таким кодом

Environment.SetEnvironmentVariable("RRR", "333", EnvironmentVariableTarget.Machine);

В Висте и Windows 7 запускать его надо с elevated privileges!

Теперь запускаем новый FAR

C:\>set RRR
RRR=333

Чистим окружение в компьютере. Проверяем еще раз в обоих FAR'ах. Ничего не изменилось.

Запускаем третий FAR

C:\>set RRR

Environment variable not defined
With best regards
Pavel Dvorkin
Re[5]: SetEnvironmentVariable не работает?
От: Мизантроп  
Дата: 15.10.09 05:13
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Поправлю немного, с Вашего разрешения




Это не противоречит сказанному мной, просто это частный случай, а я специально указал, что перелогин требуется в общем случае.
Другой частный случай. В консольном приложении пишем
unsafe static void Main(string[] args)
{
    Environment.SetEnvironmentVariable("evv", "33", EnvironmentVariableTarget.User);
    string s = Environment.GetEnvironmentVariable("evv");
    Console.WriteLine("evv = {0}", s);
    Console.ReadKey();
{

Запускаем раз, выводит "evv =". Запускаем ещё раз, выводит то-же самое. Перелогиниваемся, запускаем — выводит "evv = 33". Просто кто-то реагирует на WM_SETTINGCHANGE с "Environment", а кто-то нет. Потому я бы не посоветовал закладываться на такое поведение, если-бы моего совета кто-нибудь спросил
"Нормальные герои всегда идут в обход!"
Re[5]: SetEnvironmentVariable не работает?
От: Ziaw Россия  
Дата: 15.10.09 05:15
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Нет. Проверяем.


PD>Запускаем FAR


Видимо какой-то плагин для фара который рефрешит. Или версия более поздняя чем у меня.
У меня фар сам не ловит изменения глобальных переменных. Мало того, cmd запускаемый из процесса наследует его переменные.

>set RRR
Переменная среды RRR не определена

>type ..\..\Program.cs
я¬¬using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication3
{
    class Program
    {
        static void Main(string[] args)
        {
            var t = args.Length > 0 ? args[0] : "worked";
            Environment.SetEnvironmentVariable("RRR", t, EnvironmentVariableTarg
et.Machine);
        }
    }
}

>cmd
Microsoft Windows XP [Версия 5.1.2600]
(С) Корпорация Майкрософт, 1985-2001.

>set RRR
Переменная среды RRR не определена


Вот если запустить cmd из эксплорера (Win+R например), то он уже получит новые переменные из реестра.
Microsoft Windows XP [Версия 5.1.2600]
(С) Корпорация Майкрософт, 1985-2001.

C:\Documents and Settings\ziaw>set RRR
RRR=test

C:\Documents and Settings\ziaw>


З.Ы. Хочу такой же плагин к фару, или достаточно обновить сам фар?
... << RSDN@Home 1.2.0 alpha 4 rev. 1237>>
Re[6]: SetEnvironmentVariable не работает?
От: Ziaw Россия  
Дата: 15.10.09 05:19
Оценка:
Здравствуйте, Ziaw, Вы писали:

Прошу прощения, недокопировал лог работы, пропал самый важный кусок
Z>

>set ERR
Переменная среды ERR не определена
>ConsoleApplication3.exe test
>>set RRR
Z>Переменная среды RRR не определена

>>type ..\..\Program.cs
Z>я¬¬using System;
Z>using System.Collections.Generic;
Z>using System.Linq;
...
Z>
... << RSDN@Home 1.2.0 alpha 4 rev. 1237>>
Re[5]: SetEnvironmentVariable не работает?
От: Мизантроп  
Дата: 15.10.09 05:20
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Запускаем FAR


Кроме того, возможно, что FAR вообще не читает своё окружение, а обращается напрямую к реестру, либо комбинирует то и то.
"Нормальные герои всегда идут в обход!"
Re[6]: SetEnvironmentVariable не работает?
От: Pavel Dvorkin Россия  
Дата: 15.10.09 05:26
Оценка:
Здравствуйте, Ziaw, Вы писали:

Z>Здравствуйте, Pavel Dvorkin, Вы писали:


PD>>Нет. Проверяем.


PD>>Запускаем FAR


Z>Видимо какой-то плагин для фара который рефрешит. Или версия более поздняя чем у меня.


Такое поведение у FAR сколько я его помню. И FAR тут ни при чем.

Сделал совершенно те же действия, но запускал CMD вмето FAR. Эффекты 1:1
With best regards
Pavel Dvorkin
Re[7]: SetEnvironmentVariable не работает?
От: Pavel Dvorkin Россия  
Дата: 15.10.09 05:28
Оценка:
Здравствуйте, Ziaw, Вы писали:


Z>Прошу прощения, недокопировал лог работы, пропал самый важный кусок


Все правильно. Я же сказал — запускаем новый FAR, тогда и проявятся
With best regards
Pavel Dvorkin
Re[7]: SetEnvironmentVariable не работает?
От: Ziaw Россия  
Дата: 15.10.09 05:37
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

Z>>Видимо какой-то плагин для фара который рефрешит. Или версия более поздняя чем у меня.


PD>Такое поведение у FAR сколько я его помню. И FAR тут ни при чем.


Значит влияет что-то другое, оффициальная дока ничего не говорит о авторефреше машинных переменных.

In the command shell, each instance of Cmd.exe inherits the environment of its parent application. Therefore, you can change the variables in the new Cmd.exe environment without affecting the environment of the parent application.


PD>Сделал совершенно те же действия, но запускал CMD вмето FAR. Эффекты 1:1


У меня тоже 1:1 только эффект противоположный
Сколько помню, столько и наблюдал такое поведение, после иземенения переменных в свойствах компьютера всегда рестартил фар или шелл
... << RSDN@Home 1.2.0 alpha 4 rev. 1237>>
Re[8]: SetEnvironmentVariable не работает?
От: Ziaw Россия  
Дата: 15.10.09 05:38
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Здравствуйте, Ziaw, Вы писали:



Z>>Прошу прощения, недокопировал лог работы, пропал самый важный кусок


PD>Все правильно. Я же сказал — запускаем новый FAR, тогда и проявятся


О мой бог Я пропустил эту строчку
... << RSDN@Home 1.2.0 alpha 4 rev. 1237>>
Re[8]: SetEnvironmentVariable не работает?
От: Pavel Dvorkin Россия  
Дата: 15.10.09 05:49
Оценка:
Здравствуйте, Ziaw, Вы писали:

Z>Здравствуйте, Pavel Dvorkin, Вы писали:


Z>>>Видимо какой-то плагин для фара который рефрешит. Или версия более поздняя чем у меня.


PD>>Такое поведение у FAR сколько я его помню. И FAR тут ни при чем.


Z>Значит влияет что-то другое, оффициальная дока ничего не говорит о авторефреше машинных переменных.


А я разве говорю об авторефреше ? прочти внимательно, что я написал.

Z>

Z>In the command shell, each instance of Cmd.exe inherits the environment of its parent application. Therefore, you can change the variables in the new Cmd.exe environment without affecting the environment of the parent application.


Совершенно верно.

PD>>Сделал совершенно те же действия, но запускал CMD вмето FAR. Эффекты 1:1


Z>У меня тоже 1:1 только эффект противоположный

Z>Сколько помню, столько и наблюдал такое поведение, после иземенения переменных в свойствах компьютера всегда рестартил фар или шелл

Так я о том же и говорю — новая копия FAR получит эту переменную Уже запущенные остаются при своем.
With best regards
Pavel Dvorkin
Re[8]: SetEnvironmentVariable не работает?
От: Мизантроп  
Дата: 15.10.09 05:58
Оценка: +2
Здравствуйте, Ziaw, Вы писали:

Z>

Z>In the command shell, each instance of Cmd.exe inherits the environment of its parent application. Therefore, you can change the variables in the new Cmd.exe environment without affecting the environment of the parent application.


Стоит, вероятно, добавить, что все процессы, не только CMD, по умолчанию наследуют своё окружение от родительского процесса, и об этом сказано в описании CreateProcess, если правильно помню. А для всех пользовательских процессов в родителях (прямо или опосредованно) числится shell, от него и наследуется окружение. (Отдельная история с RunAs) То есть если мы в своём процессе добавим в своё окружение какую-то переменную или наоборот, удалим, а потом запустим какой-нибудь процесс, то в этом новом процессе будут видны сделанные нами изменения.

Другое дело, что в частных случаях в CreateProcess можно передать собственноручно созданный блок окружения, в том числе и считав его из реестра. Но это частный случай. Другой частный случай, что у нового процесса может вообще оказаться пустой блок, если передать в CreateProcess соответствующим параметром указатель на ноль
"Нормальные герои всегда идут в обход!"
Re[5]: подводя итог или с другой точки зрения
От: Pavel Dvorkin Россия  
Дата: 15.10.09 06:10
Оценка:
Еще один эксперимент.

1. Запускаем CMD (назову его CMD1)
C:\>set 333
Environment variable not defined

2. Запускаем .cs программу
3. Запускаем новый CMD -2
C:\>set RRR
RRR=333

4. Из CMD1 запускаем CMD3. Он запустится в той же консоли, но это не важно — по Task Manager видно, что запустился новый cmd

C:\>set 333
Environment variable not defined

4. Из CMD2 запускаем CMD4. Он запустится в той же консоли, но это не важно — по Task Manager видно, что запустился новый cmd

C:\>set RRR
RRR=333

5. Удаляем RRR для компьютера

6. Из CMD4 запускаем CMD5

C:\>set RRR
RRR=333

хотя в системе этой переменной уже нет

Подводим итоги.

При запуске CMD из shell shell берет новую информацию из реестра. Видимо, shell это умеет. Например, он мог подписаться на RegNotifyChangeKeyValue. Или просто перечитать значение из реестра. После этого shell запускает новый процесс с измененным окружением.
Сам CMD этого не умеет. Поэтому он просто запускает новый процесс, передавая NULL в соответствующем параметре CreateProcess, что приводит к копированию его окружения в новый процесс. Поэтому CMD5 получил эту переменную, хотя ее уже нет в машине.
Аналогично CMD будут вести себя и другие программы-стартеры, если они не позаботятся о том, чтобы прочитать значения из реестра
With best regards
Pavel Dvorkin
Re[9]: SetEnvironmentVariable не работает?
От: Мизантроп  
Дата: 15.10.09 06:10
Оценка:
Здравствуйте, Мизантроп, Вы писали:

На всякий случай утоню

М>То есть если мы в своём процессе добавим в своё окружение какую-то переменную или наоборот, удалим, а потом запустим какой-нибудь процесс


Имелось в виду — запустим новый процесс из того, в котором вносили изменения в его окружение. То есть изменяем вызовом
System.SetEnvironmentVariable(Name, Value)

а запускаем вызовом CreateProcess.
"Нормальные герои всегда идут в обход!"
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.