Интерфейс для изменения переменных среды Windows из Python

Вы можете использовать malloc для динамического распределения памяти (т. е. размер неизвестен до времени исполнения).

C - язык низкого уровня: вы должны вручную освободить память после ее использования; Если вы этого не сделаете, ваша программа будет страдать от утечек памяти.

UPDATE

Просто прочитайте свой комментарий к другому ответу.

Вы просите массив с динамически меняющимся размером.

Ну, C не имеет языковых / синтаксических возможностей для этого; вам нужно либо реализовать это самостоятельно, либо использовать библиотеку, которая уже реализовала его.

См. этот вопрос: Существует ли реализация автоматического масштабирования массива / динамического массива для C, которая поставляется с glibc?

17
задан Paul Stephenson 6 July 2009 в 09:02
поделиться

5 ответов

Использование setx имеет несколько недостатков, особенно если вы пытаетесь добавить переменные среды (например, setx PATH% Path%; C: \ mypath) Это будет постоянно добавляться к пути каждый раз, когда вы запускаете его, что может быть проблемой. Хуже того, он не различает путь к машине (хранится в HKEY_LOCAL_MACHINE) и путь пользователя (хранится в HKEY_CURRENT_USER). Переменная среды, которую вы видите в командной строке, состоит из конкатенации этих двух значений. Следовательно, перед вызовом setx:

user PATH == u
machine PATH == m
%PATH% == m;u

> setx PATH %PATH%;new

Calling setx sets the USER path by default, hence now:
user PATH == m;u;new
machine PATH == m
%PATH% == m;m;u;new

Системный путь неизбежно дублируется в переменной среды% PATH% каждый раз, когда вы вызываете setx для добавления в PATH. Эти изменения являются постоянными, никогда не сбрасываются перезагрузками и накапливаются в течение всего срока службы машины.

Попытка компенсировать это в DOS - вне моих возможностей. Поэтому я обратился к Python. Решение, которое я придумал сегодня, для установки переменных среды путем настройки реестра, включая добавление в PATH без введения дубликатов, выглядит следующим образом:

from os import system, environ
import win32con
from win32gui import SendMessage
from _winreg import (
    CloseKey, OpenKey, QueryValueEx, SetValueEx,
    HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE,
    KEY_ALL_ACCESS, KEY_READ, REG_EXPAND_SZ, REG_SZ
)

def env_keys(user=True):
    if user:
        root = HKEY_CURRENT_USER
        subkey = 'Environment'
    else:
        root = HKEY_LOCAL_MACHINE
        subkey = r'SYSTEM\CurrentControlSet\Control\Session Manager\Environment'
    return root, subkey


def get_env(name, user=True):
    root, subkey = env_keys(user)
    key = OpenKey(root, subkey, 0, KEY_READ)
    try:
        value, _ = QueryValueEx(key, name)
    except WindowsError:
        return ''
    return value


def set_env(name, value):
    key = OpenKey(HKEY_CURRENT_USER, 'Environment', 0, KEY_ALL_ACCESS)
    SetValueEx(key, name, 0, REG_EXPAND_SZ, value)
    CloseKey(key)
    SendMessage(
        win32con.HWND_BROADCAST, win32con.WM_SETTINGCHANGE, 0, 'Environment')


def remove(paths, value):
    while value in paths:
        paths.remove(value)


def unique(paths):
    unique = []
    for value in paths:
        if value not in unique:
            unique.append(value)
    return unique


def prepend_env(name, values):
    for value in values:
        paths = get_env(name).split(';')
        remove(paths, '')
        paths = unique(paths)
        remove(paths, value)
        paths.insert(0, value)
        set_env(name, ';'.join(paths))


def prepend_env_pathext(values):
    prepend_env('PathExt_User', values)
    pathext = ';'.join([
        get_env('PathExt_User'),
        get_env('PathExt', user=False)
    ])
    set_env('PathExt', pathext)



set_env('Home', '%HomeDrive%%HomePath%')
set_env('Docs', '%HomeDrive%%HomePath%\docs')
set_env('Prompt', '$P$_$G$S')

prepend_env('Path', [
    r'%SystemDrive%\cygwin\bin', # Add cygwin binaries to path
    r'%HomeDrive%%HomePath%\bin', # shortcuts and 'pass-through' bat files
    r'%HomeDrive%%HomePath%\docs\bin\mswin', # copies of standalone executables
])

# allow running of these filetypes without having to type the extension
prepend_env_pathext(['.lnk', '.exe.lnk', '.py'])

Это не влияет на текущий процесс или родительскую оболочку, но повлияет на все Окна cmd открываются после его запуска без перезагрузки, и их можно безопасно редактировать и повторно запускать много раз, не создавая дубликатов.

user PATH == u
machine PATH == m
%PATH% == m;u

> setx PATH %PATH%;new

Calling setx sets the USER path by default, hence now:
user PATH == m;u;new
machine PATH == m
%PATH% == m;m;u;new

Системный путь неизбежно дублируется в переменной среды% PATH% каждый раз, когда вы вызываете setx для добавления в PATH. Эти изменения являются постоянными, никогда не сбрасываются перезагрузками и накапливаются в течение всего срока службы машины.

Попытка компенсировать это в DOS - вне моих возможностей. Поэтому я обратился к Python. Решение, которое я придумал сегодня, установить переменные среды путем настройки реестра, включая добавление в PATH без добавления дубликатов, выглядит следующим образом:

from os import system, environ
import win32con
from win32gui import SendMessage
from _winreg import (
    CloseKey, OpenKey, QueryValueEx, SetValueEx,
    HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE,
    KEY_ALL_ACCESS, KEY_READ, REG_EXPAND_SZ, REG_SZ
)

def env_keys(user=True):
    if user:
        root = HKEY_CURRENT_USER
        subkey = 'Environment'
    else:
        root = HKEY_LOCAL_MACHINE
        subkey = r'SYSTEM\CurrentControlSet\Control\Session Manager\Environment'
    return root, subkey


def get_env(name, user=True):
    root, subkey = env_keys(user)
    key = OpenKey(root, subkey, 0, KEY_READ)
    try:
        value, _ = QueryValueEx(key, name)
    except WindowsError:
        return ''
    return value


def set_env(name, value):
    key = OpenKey(HKEY_CURRENT_USER, 'Environment', 0, KEY_ALL_ACCESS)
    SetValueEx(key, name, 0, REG_EXPAND_SZ, value)
    CloseKey(key)
    SendMessage(
        win32con.HWND_BROADCAST, win32con.WM_SETTINGCHANGE, 0, 'Environment')


def remove(paths, value):
    while value in paths:
        paths.remove(value)


def unique(paths):
    unique = []
    for value in paths:
        if value not in unique:
            unique.append(value)
    return unique


def prepend_env(name, values):
    for value in values:
        paths = get_env(name).split(';')
        remove(paths, '')
        paths = unique(paths)
        remove(paths, value)
        paths.insert(0, value)
        set_env(name, ';'.join(paths))


def prepend_env_pathext(values):
    prepend_env('PathExt_User', values)
    pathext = ';'.join([
        get_env('PathExt_User'),
        get_env('PathExt', user=False)
    ])
    set_env('PathExt', pathext)



set_env('Home', '%HomeDrive%%HomePath%')
set_env('Docs', '%HomeDrive%%HomePath%\docs')
set_env('Prompt', '$P$_$G$S')

prepend_env('Path', [
    r'%SystemDrive%\cygwin\bin', # Add cygwin binaries to path
    r'%HomeDrive%%HomePath%\bin', # shortcuts and 'pass-through' bat files
    r'%HomeDrive%%HomePath%\docs\bin\mswin', # copies of standalone executables
])

# allow running of these filetypes without having to type the extension
prepend_env_pathext(['.lnk', '.exe.lnk', '.py'])

Это не влияет на текущий процесс или родительскую оболочку, но повлияет на все Окна cmd открываются после его запуска без необходимости перезагрузки, и их можно безопасно редактировать и запускать повторно много раз без создания каких-либо дубликатов.

user PATH == u
machine PATH == m
%PATH% == m;u

> setx PATH %PATH%;new

Calling setx sets the USER path by default, hence now:
user PATH == m;u;new
machine PATH == m
%PATH% == m;m;u;new

Системный путь неизбежно дублируется в переменной среды% PATH% каждый раз, когда вы вызываете setx для добавления в PATH. Эти изменения являются постоянными, никогда не сбрасываются перезагрузкой и накапливаются в течение всего срока службы машины.

Попытка компенсировать это в DOS не в моих силах. Поэтому я обратился к Python. Решение, которое я придумал сегодня, установить переменные среды путем настройки реестра, включая добавление в PATH без добавления дубликатов, выглядит следующим образом:

from os import system, environ
import win32con
from win32gui import SendMessage
from _winreg import (
    CloseKey, OpenKey, QueryValueEx, SetValueEx,
    HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE,
    KEY_ALL_ACCESS, KEY_READ, REG_EXPAND_SZ, REG_SZ
)

def env_keys(user=True):
    if user:
        root = HKEY_CURRENT_USER
        subkey = 'Environment'
    else:
        root = HKEY_LOCAL_MACHINE
        subkey = r'SYSTEM\CurrentControlSet\Control\Session Manager\Environment'
    return root, subkey


def get_env(name, user=True):
    root, subkey = env_keys(user)
    key = OpenKey(root, subkey, 0, KEY_READ)
    try:
        value, _ = QueryValueEx(key, name)
    except WindowsError:
        return ''
    return value


def set_env(name, value):
    key = OpenKey(HKEY_CURRENT_USER, 'Environment', 0, KEY_ALL_ACCESS)
    SetValueEx(key, name, 0, REG_EXPAND_SZ, value)
    CloseKey(key)
    SendMessage(
        win32con.HWND_BROADCAST, win32con.WM_SETTINGCHANGE, 0, 'Environment')


def remove(paths, value):
    while value in paths:
        paths.remove(value)


def unique(paths):
    unique = []
    for value in paths:
        if value not in unique:
            unique.append(value)
    return unique


def prepend_env(name, values):
    for value in values:
        paths = get_env(name).split(';')
        remove(paths, '')
        paths = unique(paths)
        remove(paths, value)
        paths.insert(0, value)
        set_env(name, ';'.join(paths))


def prepend_env_pathext(values):
    prepend_env('PathExt_User', values)
    pathext = ';'.join([
        get_env('PathExt_User'),
        get_env('PathExt', user=False)
    ])
    set_env('PathExt', pathext)



set_env('Home', '%HomeDrive%%HomePath%')
set_env('Docs', '%HomeDrive%%HomePath%\docs')
set_env('Prompt', '$P$_$G$S')

prepend_env('Path', [
    r'%SystemDrive%\cygwin\bin', # Add cygwin binaries to path
    r'%HomeDrive%%HomePath%\bin', # shortcuts and 'pass-through' bat files
    r'%HomeDrive%%HomePath%\docs\bin\mswin', # copies of standalone executables
])

# allow running of these filetypes without having to type the extension
prepend_env_pathext(['.lnk', '.exe.lnk', '.py'])

Это не влияет на текущий процесс или родительскую оболочку, но повлияет на все Окна cmd открываются после его запуска без необходимости перезагрузки, и их можно безопасно редактировать и запускать повторно много раз без создания каких-либо дубликатов.

Попытка компенсировать это в DOS не в моих силах. Поэтому я обратился к Python. Решение, которое я придумал сегодня, для установки переменных среды путем настройки реестра, включая добавление в PATH без введения дубликатов, выглядит следующим образом:

from os import system, environ
import win32con
from win32gui import SendMessage
from _winreg import (
    CloseKey, OpenKey, QueryValueEx, SetValueEx,
    HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE,
    KEY_ALL_ACCESS, KEY_READ, REG_EXPAND_SZ, REG_SZ
)

def env_keys(user=True):
    if user:
        root = HKEY_CURRENT_USER
        subkey = 'Environment'
    else:
        root = HKEY_LOCAL_MACHINE
        subkey = r'SYSTEM\CurrentControlSet\Control\Session Manager\Environment'
    return root, subkey


def get_env(name, user=True):
    root, subkey = env_keys(user)
    key = OpenKey(root, subkey, 0, KEY_READ)
    try:
        value, _ = QueryValueEx(key, name)
    except WindowsError:
        return ''
    return value


def set_env(name, value):
    key = OpenKey(HKEY_CURRENT_USER, 'Environment', 0, KEY_ALL_ACCESS)
    SetValueEx(key, name, 0, REG_EXPAND_SZ, value)
    CloseKey(key)
    SendMessage(
        win32con.HWND_BROADCAST, win32con.WM_SETTINGCHANGE, 0, 'Environment')


def remove(paths, value):
    while value in paths:
        paths.remove(value)


def unique(paths):
    unique = []
    for value in paths:
        if value not in unique:
            unique.append(value)
    return unique


def prepend_env(name, values):
    for value in values:
        paths = get_env(name).split(';')
        remove(paths, '')
        paths = unique(paths)
        remove(paths, value)
        paths.insert(0, value)
        set_env(name, ';'.join(paths))


def prepend_env_pathext(values):
    prepend_env('PathExt_User', values)
    pathext = ';'.join([
        get_env('PathExt_User'),
        get_env('PathExt', user=False)
    ])
    set_env('PathExt', pathext)



set_env('Home', '%HomeDrive%%HomePath%')
set_env('Docs', '%HomeDrive%%HomePath%\docs')
set_env('Prompt', '$P$_$G$S')

prepend_env('Path', [
    r'%SystemDrive%\cygwin\bin', # Add cygwin binaries to path
    r'%HomeDrive%%HomePath%\bin', # shortcuts and 'pass-through' bat files
    r'%HomeDrive%%HomePath%\docs\bin\mswin', # copies of standalone executables
])

# allow running of these filetypes without having to type the extension
prepend_env_pathext(['.lnk', '.exe.lnk', '.py'])

Это не влияет на текущий процесс или родительскую оболочку, но повлияет на все Окна cmd открываются после его запуска без перезагрузки, и их можно безопасно редактировать и повторно запускать много раз, не создавая дубликатов.

Попытка компенсировать это в DOS не в моих силах. Поэтому я обратился к Python. Решение, которое я придумал сегодня, для установки переменных среды путем настройки реестра, включая добавление в PATH без введения дубликатов, выглядит следующим образом:

from os import system, environ
import win32con
from win32gui import SendMessage
from _winreg import (
    CloseKey, OpenKey, QueryValueEx, SetValueEx,
    HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE,
    KEY_ALL_ACCESS, KEY_READ, REG_EXPAND_SZ, REG_SZ
)

def env_keys(user=True):
    if user:
        root = HKEY_CURRENT_USER
        subkey = 'Environment'
    else:
        root = HKEY_LOCAL_MACHINE
        subkey = r'SYSTEM\CurrentControlSet\Control\Session Manager\Environment'
    return root, subkey


def get_env(name, user=True):
    root, subkey = env_keys(user)
    key = OpenKey(root, subkey, 0, KEY_READ)
    try:
        value, _ = QueryValueEx(key, name)
    except WindowsError:
        return ''
    return value


def set_env(name, value):
    key = OpenKey(HKEY_CURRENT_USER, 'Environment', 0, KEY_ALL_ACCESS)
    SetValueEx(key, name, 0, REG_EXPAND_SZ, value)
    CloseKey(key)
    SendMessage(
        win32con.HWND_BROADCAST, win32con.WM_SETTINGCHANGE, 0, 'Environment')


def remove(paths, value):
    while value in paths:
        paths.remove(value)


def unique(paths):
    unique = []
    for value in paths:
        if value not in unique:
            unique.append(value)
    return unique


def prepend_env(name, values):
    for value in values:
        paths = get_env(name).split(';')
        remove(paths, '')
        paths = unique(paths)
        remove(paths, value)
        paths.insert(0, value)
        set_env(name, ';'.join(paths))


def prepend_env_pathext(values):
    prepend_env('PathExt_User', values)
    pathext = ';'.join([
        get_env('PathExt_User'),
        get_env('PathExt', user=False)
    ])
    set_env('PathExt', pathext)



set_env('Home', '%HomeDrive%%HomePath%')
set_env('Docs', '%HomeDrive%%HomePath%\docs')
set_env('Prompt', '$P$_$G$S')

prepend_env('Path', [
    r'%SystemDrive%\cygwin\bin', # Add cygwin binaries to path
    r'%HomeDrive%%HomePath%\bin', # shortcuts and 'pass-through' bat files
    r'%HomeDrive%%HomePath%\docs\bin\mswin', # copies of standalone executables
])

# allow running of these filetypes without having to type the extension
prepend_env_pathext(['.lnk', '.exe.lnk', '.py'])

Это не влияет на текущий процесс или родительскую оболочку, но повлияет на все Окна cmd открываются после его запуска без перезагрузки, и их можно безопасно редактировать и повторно запускать много раз без создания каких-либо дубликатов.

22
ответ дан 30 November 2019 в 12:20
поделиться

Способ реестра - это если вы хотите изменить его навсегда для всего, что, я думаю, именно то, что вам нужно здесь, так как он находится в setup.py.

Временно только для вашего процесса, затем os .environ - это уловка.

1
ответ дан 30 November 2019 в 12:20
поделиться

В модуле os есть функции getenv и putenv. Однако кажется, что putenv работает некорректно, и вместо этого вы должны использовать реестр Windows

Посмотрите это обсуждение

1
ответ дан 30 November 2019 в 12:20
поделиться

It может быть так же просто использовать внешнюю команду Windows setx :

C:\>set NEWVAR
Environment variable NEWVAR not defined

C:\>python
Python 2.5.4 (r254:67916, Dec 23 2008, 15:10:54) [MSC v.1310 32 bit (Intel)] on
win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> os.system('setx NEWVAR newvalue')
0
>>> os.getenv('NEWVAR')
>>> ^Z


C:\>set NEWVAR
Environment variable NEWVAR not defined

Теперь откройте новую командную строку:

C:\>set NEWVAR
NEWVAR=newvalue

Как видите, setx не устанавливает переменную для текущий сеанс, ни для родительского процесса (первая командная строка).Но он постоянно устанавливает переменную в реестре для будущих процессов.

Я не думаю, что существует вообще способ изменить среду родительского процесса (и если есть, я бы хотел услышать это!).

4
ответ дан 30 November 2019 в 12:20
поделиться

Должно быть, тысячелетие назад я пытался изменить среду текущего сеанса DOS с помощью программы. Проблема в том, что эта программа работает в своей собственной оболочке DOS, поэтому она должна работать в своей родительской среде. Требуется пройтись, начиная с информационного блока DOS, по всей цепочке блоков управления памятью, чтобы найти расположение этой родительской среды. Как только я узнал, как это сделать, моя потребность в манипулировании переменными среды отпала. Я дам вам код Turbo Pascal ниже, но я полагаю, что есть по крайней мере три лучших способа сделать это:

  1. Создайте командный файл, который: (a) вызывает скрипт Python (или независимо), который генерирует временный командный файл, содержащий соответствующие команды SET; (b) вызывает временный пакетный файл (команды SET выполняются в текущей оболочке); и (c) удаляет временный пакетный файл.

  2. Создайте сценарий Python, который записывает что-то вроде «VAR1 = val1 \ nVAR2 = val2 \ nVAR3 = val3 \ n» в STDOUT. Используйте это в своем командном файле следующим образом:

    для / f "delims = |" %% X в (' callYourPythonScript ') установить %% X

    et voilà: переменным VAR1, VAR2 и VAR3 присвоено значение.

  3. Измените реестр Windows и передайте изменение настройки как описано здесь Александра Прокофьева.

А вот и код на Паскале (вам может понадобиться голландский словарь и книга по программированию на Паскале) программы, которая просто сообщает о ячейках памяти. Кажется, что он все еще работает под Windows XP, даже если он сообщает, что мы работаем с DOS 5.00. Это только первое начало, нужно выполнить много низкоуровневого программирования, чтобы управлять выбранной средой. И поскольку структура указателя может показаться правильной, я не уверен, что модель среды 1994 года все еще актуальна в наши дни ...

program MCBKETEN;
uses dos, HexConv;

{----------------------------------------------------------------------------}
{  Programma: MCBKETEN.EXE                                                   }
{  Broncode : MCBKETEN.PAS                                                   }
{  Doel     : Tocht langs de MCB's met rapportage                            }
{  Datum    : 11 januari 1994                                                }
{  Auteur   : Meindert Meindertsma                                           }
{  Versie   : 1.00                                                           }
{----------------------------------------------------------------------------}

type
   MCB_Ptr     = ^MCB;
{  MCB_PtrPtr  = ^MCB_Ptr;  vervallen wegens DOS 2.11 -- zie verderop }
   MCB         = record
                    Signatuur    : char;
                    Eigenaar     : word;
                    Paragrafen   : word;
                    Gereserveerd : array[1..3] of byte;
                    Naam         : array[1..8] of char;
                 end;
   BlokPtr     = ^BlokRec;
   BlokRec     = record
                    Vorige       : BlokPtr;
                    DitSegment,
                    Paragrafen   : word;
                    Signatuur    : string[6];
                    Eigenaar,
                    Omgeving     : word;
                    Functie      : String4;
                    Oorsprong,
                    Pijl         : char;
                    KorteNaam    : string[8];
                    LangeNaam    : string;
                    Volgende     : BlokPtr;
                 end;
   PSP_Ptr     = ^PSP;
   PSP         = record
                    Vulsel1      : array[1..44] of byte;
                    Omgeving     : word;
                    Vulsel2      : array[47..256] of byte;
                 end;

var
   Zone                  : string[5];
   ProgGevonden,
   EindeKeten,
   Dos3punt2             : boolean;
   Regs                  : registers;
   ActMCB                : MCB_Ptr;
   EersteSchakel, Schakel,
   LaatsteSchakel        : BlokPtr;
   ActPSP                : PSP_Ptr;
   EersteProg,
   Meester, Ouder,
   TerugkeerSegment,
   TerugkeerOffset,
   TerugkeerSegment2,
   OuderSegment          : word;
   Specificatie          : string[8];
   ReleaseNummer         : string[2];
   i                     : byte;


{----------------------------------------------------------------------------}
{  PROCEDURES EN FUNCTIES                                                    }
{----------------------------------------------------------------------------}

function Coda (Omgeving : word; Paragrafen : word) : string;

var
   i            : longint;
   Vorige, Deze : char;
   Streng       : string;

begin
   i    := 0;
   Deze := #0;
   repeat
      Vorige := Deze;
      Deze   := char (ptr (Omgeving, i)^);
      inc (i);
   until ((Vorige = #0) and (Deze = #0)) or (i div $10 >= Paragrafen);
   if (i + 3) div $10 < Paragrafen then begin
      Vorige := char (ptr (Omgeving, i)^);
      inc (i);
      Deze   := char (ptr (Omgeving, i)^);
      inc (i);
      if (Vorige = #01) and (Deze = #0) then begin
         Streng := '';
         Deze   := char (ptr (Omgeving, i)^);
         inc (i);
         while (Deze <> #0) and (i div $10 < Paragrafen) do begin
            Streng := Streng + Deze;
            Deze   := char (ptr (Omgeving, i)^);
            inc (i);
         end;
         Coda := Streng;
      end
      else Coda := '';
   end
   else Coda := '';
end {Coda};


{----------------------------------------------------------------------------}
{  HOOFDPROGRAMMA                                                            }
{----------------------------------------------------------------------------}

BEGIN
  {----- Initiatie -----}
   Zone            := 'Lower';
   ProgGevonden    := FALSE;
   EindeKeten      := FALSE;
   Dos3punt2       := (dosversion >= $1403) and (dosversion <= $1D03);
   Meester         := $0000;
   Ouder           := $0000;
   Specificatie[0] := #8;
   str (hi (dosversion) : 2, ReleaseNummer);
   if ReleaseNummer[1] = ' ' then ReleaseNummer[1] := '0';

  {----- Pointer naar eerste MCB ophalen ------}
   Regs.AH := $52;  { functie $52 geeft adres van DOS Info Block in ES:BX }
   msdos (Regs);
{  ActMCB := MCB_PtrPtr (ptr (Regs.ES, Regs.BX - 4))^;  NIET onder DOS 2.11  }
   ActMCB := ptr (word (ptr (Regs.ES, Regs.BX - 2)^), $0000);

  {----- MCB-keten doorlopen -----}
   new (EersteSchakel);
   EersteSchakel^.Vorige := nil;
   Schakel               := EersteSchakel;
   repeat
      with Schakel^ do begin
         DitSegment := seg (ActMCB^);
         Paragrafen := ActMCB^.Paragrafen;
         if DitSegment + Paragrafen >= $A000 then
            Zone    := 'Upper';
         Signatuur  := Zone + ActMCB^.Signatuur;
         Eigenaar   := ActMCB^.Eigenaar;
         ActPSP     := ptr (Eigenaar, 0);
         if not ProgGevonden then EersteProg := DitSegment + 1;
         if Eigenaar >= EersteProg
            then Omgeving := ActPSP^.Omgeving
            else Omgeving := 0;
         if DitSegment + 1 = Eigenaar then begin
            ProgGevonden  := TRUE;
            Functie       := 'Prog';
            KorteNaam[0]  := #0;
            while (ActMCB^.Naam[ ord (KorteNaam[0]) + 1 ] <> #0) and
                  (KorteNaam[0] < #8) do
            begin
               inc (KorteNaam[0]);
               KorteNaam[ ord (KorteNaam[0]) ] :=
                  ActMCB^.Naam[ ord (KorteNaam[0]) ];
            end;
            if Eigenaar = prefixseg then begin
               TerugkeerSegment := word (ptr (prefixseg, $000C)^);
               TerugkeerOffset  := word (ptr (prefixseg, $000A)^);
               LangeNaam        := '-----> Terminate Vector = '     +
                                   WordHex (TerugkeerSegment) + ':' +
                                   WordHex (TerugkeerOffset )        ;
            end
            else
               LangeNaam := '';
         end {if ÆProgØ}
         else begin
            if Eigenaar = $0008 then begin
               if ActMCB^.Naam[1] = 'S' then
                  case ActMCB^.Naam[2] of
                     'D' : Functie := 'SysD';
                     'C' : Functie := 'SysP';
                     else  Functie := 'Data';
                  end {case}
               else        Functie := 'Data';
               KorteNaam := '';
               LangeNaam := '';
            end {if Eigenaar = $0008}
            else begin
               if DitSegment + 1 = Omgeving then begin
                  Functie   := 'Env ';
                  LangeNaam := Coda (Omgeving, Paragrafen);
                  if EersteProg = Eigenaar then Meester := Omgeving;
               end {if ÆEnvØ}
               else begin
                  move (ptr (DitSegment + 1, 0)^, Specificatie[1], 8);
                  if (Specificatie = 'PATH=' + #0 + 'CO') or
                     (Specificatie = 'COMSPEC='         ) or
                     (Specificatie = 'OS=DRDOS'         ) then
                  begin
                     Functie   := 'Env' + chr (39);
                     LangeNaam := Coda (DitSegment + 1, Paragrafen);
                     if (EersteProg = Eigenaar) and
                        (Meester    = $0000   )
                     then
                        Meester := DitSegment + 1;
                  end
                  else begin
                     if Eigenaar = 0
                        then Functie := 'Free'
                        else Functie := 'Data';
                     LangeNaam := '';
                     if (EersteProg = Eigenaar) and
                        (Meester    = $0000   )
                     then
                        Meester := DitSegment + 1;
                  end;
               end {else: not ÆEnvØ};
               KorteNaam := '';
            end {else: Eigenaar <> $0008};
         end {else: not ÆProgØ};

        {----- KorteNaam redigeren -----}
         for i := 1 to length (KorteNaam) do
            if KorteNaam[i] < #32 then KorteNaam[i] := '.';
         KorteNaam := KorteNaam + '        ';

        {----- Oorsprong vaststellen -----}
         if EersteProg = Eigenaar
            then Oorsprong := '*'
            else Oorsprong := ' ';

        {----- Actueel proces (uitgaande Pijl) vaststellen -----}
         if Eigenaar = prefixseg
            then Pijl := '>'
            else Pijl := ' ';
      end {with Schakel^};

     {----- MCB-opeenvolging onderzoeken / schakelverloop vaststellen -----}
      if (Zone = 'Upper') and (ActMCB^.Signatuur = 'Z') then begin
         Schakel^.Volgende := nil;
         EindeKeten        := TRUE;
      end
      else begin
         ActMCB := ptr (seg (ActMCB^) + ActMCB^.Paragrafen + 1, 0);
         if ((ActMCB^.Signatuur <> 'M') and (ActMCB^.Signatuur <> 'Z')) or
            ($FFFF - ActMCB^.Paragrafen < seg (ActMCB^)               )
         then begin
            Schakel^.Volgende := nil;
            EindeKeten        := TRUE;
         end
         else begin
            new (LaatsteSchakel);
            Schakel^.Volgende      := LaatsteSchakel;
            LaatsteSchakel^.Vorige := Schakel;
            Schakel                := LaatsteSchakel;
         end {else: (ÆMØ or ÆZØ) and Æteveel_ParagrafenØ};
      end {else: ÆLowerØ or not ÆZØ};
   until EindeKeten;

  {----- Terugtocht -----}
   while Schakel <> nil do with Schakel^ do begin

     {----- Ouder-proces vaststellen -----}
      TerugkeerSegment2 := TerugkeerSegment + (TerugkeerOffset div $10);
      if (DitSegment              <= TerugkeerSegment2) and
         (DitSegment + Paragrafen >= TerugkeerSegment2)
      then
         OuderSegment := Eigenaar;

     {----- Meester-omgeving markeren -----}
      if DitSegment + 1 = Meester then Oorsprong := 'M';

     {----- Schakel-verloop -----}
      Schakel := Schakel^.Vorige;
   end {while Schakel <> nil};

  {----- Rapportage -----}
   writeln ('Chain of Memory Control Blocks in DOS version ',
            lo (dosversion), '.', ReleaseNummer, ':');
   writeln;
   writeln ('MCB@ #Par Signat PSP@ Env@ Type !! Name     File');
   writeln ('---- ---- ------ ---- ---- ---- -- -------- ',
            '-----------------------------------');
   Schakel := EersteSchakel;
   while Schakel <> nil do with Schakel^ do begin

     {----- Ouder-omgeving vaststellen -----}
      if Eigenaar = OuderSegment then begin
         if not Dos3punt2 then begin
            if (Functie = 'Env ') then begin
               Ouder := DitSegment + 1;
               Pijl  := 'Û';
            end
            else
               Pijl := '<';
         end {if not Dos3punt2}
         else begin
            if ((Functie = 'Env' + chr (39)) or (Functie = 'Data')) and
               (Ouder    = $0000)
            then begin
               Ouder := DitSegment + 1;
               Pijl  := 'Û';
            end
            else
               Pijl := '<';
         end {else: Dos3punt2};
      end {with Schakel^};

     {----- Keten-weergave -----}
      writeln (WordHex (DitSegment)        , ' ',
               WordHex (Paragrafen)        , ' ',
               Signatuur                   , ' ',
               WordHex (Eigenaar)          , ' ',
               WordHex (Omgeving)          , ' ',
               Functie                     , ' ',
               Oorsprong, Pijl             , ' ',
               KorteNaam                   , ' ',
               LangeNaam                        );

     {----- Schakel-verloop -----}
      Schakel := Schakel^.Volgende;
   end {while Schakel <> nil};

  {----- Afsluiting rapportage -----}
   writeln;

   write ('* = First command interpreter at ');
   if ProgGevonden
      then writeln (WordHex (EersteProg), ':0000')
      else writeln ('?');

   write ('M = Master environment        at ');
   if Meester > $0000
      then writeln (WordHex (Meester), ':0000')
      else writeln ('?');

   write ('< = Parent proces             at ');
   writeln (WordHex (OuderSegment), ':0000');

   write ('Û = Parent environment        at ');
   if Ouder > $0000
      then writeln (WordHex (Ouder), ':0000')
      else writeln ('?');

   writeln ('> = Current proces            at ',
            WordHex (prefixseg), ':0000');

   writeln ('    returns                   to ',
            WordHex (TerugkeerSegment), ':', WordHex (TerugkeerOffset));
END.

(Выше ASCII 127, в этой презентации могут быть некоторые проблемы с преобразованием ASCII / ANSI.)

3
ответ дан 30 November 2019 в 12:20
поделиться
Другие вопросы по тегам:

Похожие вопросы: