вторник, 13 января 2015 г.

Что это за странные переменные окружения с =C:?

Это перевод What are these strange =C: environment variables? Автор: Реймонд Чен.

Вы не увидите их при выполнении команды SET, но вы увидите их, если получите список переменных окружения сами, программным путём. К примеру, если вы напишете программу, которая получает список всех переменных окружения и выводит их на консоль, и запустите её из командной строки, то увидите странные переменные с именами вроде =C: и значениями, соответствующими каталогам на этих дисках. Что это такое?

Эти переменные являются частью командного интерпретатора cmd.exe. Вот почему я добавил "и запустите её из командной строки" выше - потому что если запустить программу из Проводника или диалога "Выполнить", то вы не увидите эти переменные. Если cmd.exe не будет среди тех, кто изменял ваш блок переменных окружения, то вы не увидите переменные от cmd.exe.

Окей, командный процессор устанавливает эти переменные. Но зачем? Это остатки от попыток командного процессора имитировать старый способ, которым MS-DOS работала с дисками и каталогами. В Win32 существует только один текущий каталог, но в MS-DOS у каждого диска был свой текущий каталог. Посмотрите на такую последовательность команд:
A> CD \SUBDIR
// текущим каталогом для диска A: является A:\SUBDIR
A> B:
B> CD \TWO
// текущим каталогом для диска B: является B:\TWO
B> A:
A> DIR
// показывает содержимое каталога A:\SUBDIR
В этой последовательности команд мы начинаем с A: (текущего диска) и устанавливаем его текущий каталог в A:\SUBDIR. Далее, мы меняем текущий диск на B: и ставим B:\TWO его текущим каталогом. Наконец, мы возвращаемся на диск A: и когда мы просим показать текущий каталог, нам выводят содержимое A:\SUBDIR - потому что именно этот каталог является текущим на текущем диске.

В Win32 нет концепции отдельного текущего каталога для каждого диска, но командному процессору нужно сохранять старое поведение MS-DOS, потому что к нему все привыкли (и для этого поведения написаны базилионы командных файлов). Решение заключается в том, чтобы хранить "текущий каталог для диска" в переменных окружения, используя несколько странное имя переменной, чтобы избежать конфликта имён с другими переменными окружения.

Если вы повторите последовательность команд выше на современном cmd.exe, то результат будет одинаков, но достигаться он будет весьма иначе.
A> CD \SUBDIR
// Переменная окружения с именем =A: устанавливается равной A:\SUBDIR
// Текущий каталог Win32 устанавливается в A:\SUBDIR
A> B:
B> CD \TWO
// Переменная окружения с именем =B: устанавливается равной B:\TWO
// Текущий каталог Win32 устанавливается в B:\TWO
B> A:
// Текущий каталог Win32 устанавливается в A:\SUBDIR
A> DIR
// Показывает содержимое A:\SUBDIR
Когда мы переключаемся обратно на диск A:, командный процессор спрашивает: "Эй, каким был текущий каталог на диске A:, когда я последний раз был на нём?". Для этого он пытается прочитать переменную окружения с именем =A:, которая говорит ему: "Ах, да, это был A:\SUBDIR". И именно этот каталог он устанавливает в качестве текущего.

Но почему эти внутренние переменные выносятся в переменные окружения? Разве нельзя их сделать обычными переменными внутри процесса cmd.exe?

Эти переменные экспортируются в переменные окружения, поскольку вы хотели бы, чтобы эти "подложные текущие каталоги дисков" наследовались бы дочерними процессами. К примеру, представьте себе, что сидите вы в командной строке, запускаете emacs, а из emacs открываете ещё одну командную строку. Вы бы ожидали все те же текущие каталоги дисков в этой командной строке.
C:\SUBDIR> D:
D:\> emacs
M-x shell
D:\> C:
C:\SUBDIR>
// "Текущий каталог на диске C" был сохранён - как и ожидает пользователь

Что вам тогда нужно делать с этими переменными окружения?

Ничего. Просто оставьте их в покое и дайте им делать свою работу. Я так подробно описал эти переменные, только чтобы вы не пугались их.

2 комментария:

  1. Запустил cmd.exe на Win8.1, запустил Process Explorer - нет там таких.
    То ли он их ТОЖЕ прячет, то ли авторы CMD.exe наконец узнали про глобальные переменные и перестали фигачить в ограниченного размера окружения чисто внутреннее состояние программы....

    ОтветитьУдалить

Можно использовать некоторые HTML-теги, например:

<b>Жирный</b>
<i>Курсив</i>
<a href="http://www.example.com/">Ссылка</a>

Вам необязательно регистрироваться для комментирования - для этого просто выберите из списка "Анонимный" (для анонимного комментария) или "Имя/URL" (для указания вашего имени и ссылки на сайт). Все прочие варианты потребуют от вас входа в вашу учётку.

Пожалуйста, по возможности используйте "Имя/URL" вместо "Анонимный". URL можно просто не указывать.

Ваше сообщение может быть помечено как спам спам-фильтром - не волнуйтесь, оно появится после проверки администратором.

Примечание. Отправлять комментарии могут только участники этого блога.