OberonCore
https://forum.oberoncore.ru/

Извлечение имени пользователя из реестра
https://forum.oberoncore.ru/viewtopic.php?f=2&t=4323
Страница 1 из 1

Автор:  Иван Денисов [ Понедельник, 22 Апрель, 2013 05:30 ]
Заголовок сообщения:  Извлечение имени пользователя из реестра

Не могу понять как корректно в следующем случае получить данные от функции WinApi. Помогите, пожалуйста. Задача: взять из реестра данные об окружении пользователя.

Код:
MODULE DiaRegTest;

   IMPORT  SYSTEM, Log, WinApi, HostRegistry;
   
   TYPE
      StringPtr = POINTER TO ARRAY [untagged] OF CHAR;
   
   PROCEDURE Home*;
      VAR r, len, type, res: INTEGER;  adr: SHORTCHAR;  i: INTEGER;
      str2, data: StringPtr; hndl: WinApi.HANDLE;
   BEGIN
      res := WinApi.RegOpenKeyW(WinApi.HKEY_CURRENT_USER, "Volatile Environment", hndl);
      len := 1024;
      res := WinApi.RegQueryValueExW(hndl, "USERNAME", NIL, type, adr, len);
      
      Log.String("res: "); Log.Int(res);
      Log.String(" type: "); Log.Int(type);
      Log.String(" len: "); Log.Int(len);Гипотеза
      Log.Ln;
      
      Log.String("data adr: "); Log.Int(SYSTEM.ADR(adr));
      Log.Ln;
      
      str2 := SYSTEM.VAL(StringPtr, SYSTEM.ADR(adr));
      Log.String(str2$); Log.Ln;
      
   END Home;

END DiaRegTest.

Автор:  Александр Ильин [ Понедельник, 22 Апрель, 2013 07:13 ]
Заголовок сообщения:  Re: Извлечение имени пользователя из реестра

Встречный вопрос: не лучше ли будет GetUserName или GetEnvironmentVariable?

Автор:  maliya [ Понедельник, 22 Апрель, 2013 07:14 ]
Заголовок сообщения:  Re: Извлечение имени пользователя из реестра

test this:

Код:
MODULE DiaRegTest;
   
   IMPORT SYSTEM, Log, WinApi;

   PROCEDURE Home* ;
      VAR
         len, type, res: INTEGER;
         data: ARRAY 512 OF CHAR;
         hkey: WinApi.HANDLE;
   BEGIN
      res := WinApi.RegOpenKeyW(WinApi.HKEY_CURRENT_USER, "Volatile Environment", hkey);
      IF res = 0 THEN
         len := LEN(data) * 2;
         res := WinApi.RegQueryValueExW(hkey, "USERNAME", NIL, type, SYSTEM.VAL(SHORTCHAR, data[0]), len);
         Log.String("res: "); Log.Int(res); Log.Tab;
         Log.String(" type: "); Log.Int(type); Log.Tab; Log.String(" len: "); Log.Int(len DIV 2);Log.Ln;
         Log.String('data:'); Log.String(data); Log.Ln;
         res := WinApi.RegCloseKey(hkey);
      ELSE
         Log.String('open key error!'); Log.Tab; Log.Int(res); Log.Ln;
      END;
   END Home;

END DiaRegTest.



Автор:  Иван Денисов [ Понедельник, 22 Апрель, 2013 15:02 ]
Заголовок сообщения:  Re: Извлечение имени пользователя из реестра

Александр Ильин писал(а):
Встречный вопрос: не лучше ли будет GetUserName или GetEnvironmentVariable?
Не могу ответить, что лучше (не спец по WinApi). Этот проще в использовании. Хотя тот метод более общий. Теперь будет выбор :)

Автор:  Иван Денисов [ Понедельник, 22 Апрель, 2013 16:25 ]
Заголовок сообщения:  Re: Извлечение имени пользователя из реестра

maliya писал(а):
test this:
Thanks a lot! It works!

Автор:  Valery Solovey [ Вторник, 23 Апрель, 2013 22:50 ]
Заголовок сообщения:  Re: Извлечение имени пользователя из реестра

Иван Денисов писал(а):
Задача: взять из реестра данные об окружении пользователя.
Думаю, следует различать "Взять из реестра" и "Взять из окружения". Переменные среды могут меняться в пределах одной сессии не меняя значения реестра.

Автор:  Иван Денисов [ Среда, 24 Апрель, 2013 10:10 ]
Заголовок сообщения:  Re: Извлечение имени пользователя из реестра

Valery Solovey писал(а):
Иван Денисов писал(а):
Задача: взять из реестра данные об окружении пользователя.
Думаю, следует различать "Взять из реестра" и "Взять из окружения". Переменные среды могут меняться в пределах одной сессии не меняя значения реестра.

Учту на будущее. Опирался на название раздела «Volatile Environment» — «Переменное Окружение» поэтому и, подумал, что так будет корректно.

Автор:  Valery Solovey [ Среда, 24 Апрель, 2013 11:30 ]
Заголовок сообщения:  Re: Извлечение имени пользователя из реестра

Кстати, в этой ветке хранятся не все переменные окружения. Переменные, которые пользователь добавляет в своё окружение через "C:\Windows\System32\rundll32.exe sysdm.cpl,EditEnvironmentVariables", попадают в другое место. То есть, неудачный поиск по Вашему пути не гарантирует отсутствие переменной в окружении.

Автор:  Иван Денисов [ Среда, 24 Апрель, 2013 12:06 ]
Заголовок сообщения:  Re: Извлечение имени пользователя из реестра

Valery Solovey писал(а):
Кстати, в этой ветке хранятся не все переменные окружения. Переменные, которые пользователь добавляет в своё окружение через "C:\Windows\System32\rundll32.exe sysdm.cpl,EditEnvironmentVariables", попадают в другое место. То есть, неудачный поиск по Вашему пути не гарантирует отсутствие переменной в окружении.
Правильно ли понимаю, что вы хотите сказать, что лучше использовать GetUserName или GetEnvironmentVariable? Как рекомендовал Александр.

Автор:  Valery Solovey [ Среда, 24 Апрель, 2013 13:44 ]
Заголовок сообщения:  Re: Извлечение имени пользователя из реестра

Если цель - работа с переменными среды, а не работа с реестром, то - да. Потому что для вступления в силу значений из реестра программу придётся перезапустить.

Причём, не просто перезапустить, а перезапустить "с нуля". Дело вот в чём: если мы запускаем программу из уже запущенной консоли или какой-нибудь другой программы, то переменные среды будут скопированы из этой программы. И сверки с реестром не происходит. При запуске "с нуля" (или "из корня" не знаю, как правильно сказать применительно к windows), то есть, с рабочего стола или через "Run", переменные копировать неоткуда, потому они берутся из реестра. Всё это на основе наблюдений, и в мсдн-е, наверно, написано более аргументированно, однако, наблюдения эти меня не подводят, поэтому я им доверяю.

Автор:  Valery Solovey [ Среда, 24 Апрель, 2013 14:20 ]
Заголовок сообщения:  Re: Извлечение имени пользователя из реестра

Иван Денисов писал(а):
использовать GetUserName или GetEnvironmentVariable

Лично я бы использовал второе. Потому что модуль для этого у меня уже есть : ).

Код:
MODULE Env;

   TYPE
      String* = POINTER TO ARRAY OF CHAR;
      Hook* = POINTER TO ABSTRACT RECORD END;
   
   VAR hook : Hook;
   
   (* узнать значение переменной.   name - название переменной *)
   PROCEDURE (h: Hook) Get- (IN name : ARRAY OF CHAR) : String, NEW, ABSTRACT;
   (* задать значение переменной.   name - название переменной, val - значение *)
   PROCEDURE (h: Hook) Set- (IN name, val : ARRAY OF CHAR), NEW, ABSTRACT;
   
   PROCEDURE SetHook*(h : Hook);
   BEGIN
      hook := h
   END SetHook;
   
   PROCEDURE Get*(IN name : ARRAY OF CHAR) : String;
   BEGIN
      RETURN hook.Get(name)
   END Get;
   
   PROCEDURE Set*(IN name, val : ARRAY OF CHAR);
   BEGIN
      hook.Set(name, val)
   END Set;
   
END Env.
Код:
MODULE HostEnv;
   IMPORT Env, WinApi, SYSTEM;
   
   CONST MaxLen = 32767;
   
   TYPE
      Hook = POINTER TO RECORD(Env.Hook)
         ValueLen- : INTEGER
      END;
      SStr = POINTER TO ARRAY OF SHORTCHAR;
   
   VAR
      res : INTEGER;
      hook : Hook;
   
   PROCEDURE ToShort(IN str : ARRAY OF CHAR) : SStr;
      VAR  ret : SStr;
         i, len : INTEGER;
   BEGIN
      i := 0; len := LEN(str$); NEW( ret, len + 1 );
      WHILE i < len DO
         ret[i] := SHORT( str[i] );
         i := i + 1
      END;
      ret[i] := 0X;
      RETURN ret
   END ToShort;
   
   PROCEDURE ToLong(str : SStr) : Env.String;
      VAR  ret : Env.String;
         i, len : INTEGER;
   BEGIN
      i := 0; len := LEN(str$); NEW( ret, len + 1 );
      WHILE i < len DO
         ret[i] := LONG( str[i] );
         i := i + 1
      END;
      ret[i] := 0X;
      RETURN ret
   END ToLong;
   
   (* узнать значение переменной *)
   PROCEDURE (h: Hook) Get(IN name : ARRAY OF CHAR) : Env.String;
      VAR sname, sval : SStr;
         len : INTEGER;
         ret : Env.String;
   BEGIN
      sname := ToShort(name);
      len := 256;
      NEW( sval, len );
      res := WinApi.GetEnvironmentVariable(sname^, sval^, len);
      ret := ToLong(sval);
      RETURN ret
   END Get;
   
   (* задать значение переменной *)
   PROCEDURE (h: Hook) Set(IN name, val: ARRAY OF CHAR);
      VAR sname, sval : POINTER TO ARRAY OF SHORTCHAR;
   BEGIN
      sname := ToShort(name);
      sval := ToShort(val);
      res := WinApi.SetEnvironmentVariable(sname^, sval^)
   END Set;
   
   (* Задать размер значения переменной.
      Используется при получении значения из ОС.
      Если возвращено значение больше заданного размера, то хвост отсекается. *)
   PROCEDURE (h: Hook) SetValLen(i : INTEGER), NEW;
   BEGIN
      (* тихое игнорирование приказа. Нужно что-то придумать *)
      IF (i >= 0) & (i < MaxLen) THEN
         h.ValueLen := i + 1 (* учитываем нолик в конце строки *)
      END
   END SetValLen;
   
   PROCEDURE Init*(len : INTEGER);
   BEGIN
      NEW( hook );
      hook.ValueLen := len;
      Env.SetHook(hook)
   END Init;
   
BEGIN
   Init(256)
END HostEnv.

Автор:  Valery Solovey [ Среда, 24 Апрель, 2013 14:23 ]
Заголовок сообщения:  Re: Извлечение имени пользователя из реестра

Правда, инит желательно в конфиг запихнуть, а не по месту, как у меня.

Автор:  Valery Solovey [ Среда, 24 Апрель, 2013 14:26 ]
Заголовок сообщения:  Re: Извлечение имени пользователя из реестра

Ну и тип строк поменять, если в проекте есть один универсальный тип строки.

Страница 1 из 1 Часовой пояс: UTC + 3 часа
Powered by phpBB® Forum Software © phpBB Group
https://www.phpbb.com/