Вот код для анализа полного набора переменных среды в словаре C #.Он использует CreateEnvironmentBlock
, как предлагается в комментариях.CreateEnvironmentBlock
нужен токен пользователя, для которого вы хотите получить переменные.Мы можем получить маркер для пользователя, который запускает наш процесс через OpenProcessToken(GetCurrentProcess(), TOKEN_READ, out primaryToken);
Получить блок среды очень просто.Больше кода тратится на анализ блока среды в словаре C #, и я уверен, что он может быть намного короче.
Важные биты без проверки ошибок:
IntPtr primaryToken = IntPtr.Zero;
OpenProcessToken(GetCurrentProcess(), TOKEN_READ, out primaryToken);
IntPtr lpEnvironment = IntPtr.Zero;
bool resultEnv = CreateEnvironmentBlock(out lpEnvironment, primaryToken, false);
// Do stuff with lpEnvironment here
DestroyEnvironmentBlock(lpEnvironment);
CloseHandle(primaryToken);
Полный пример, готов ккомпилировать:
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
public class EnvVarGetter
{
public static Dictionary<String, String> GetEnvironmentVariables()
{
IntPtr primaryToken = IntPtr.Zero;
OpenProcessToken(GetCurrentProcess(), TOKEN_READ, out primaryToken);
if (primaryToken == IntPtr.Zero)
{
return null;
}
IntPtr lpEnvironment = IntPtr.Zero;
bool resultEnv = CreateEnvironmentBlock(out lpEnvironment, primaryToken, false);
if (resultEnv != true)
{
int nError = GetLastError();
}
var envVars = new Dictionary<string, string> { };
IntPtr next = lpEnvironment;
while (Marshal.ReadByte(next) != 0)
{
var str = Marshal.PtrToStringUni(next);
// skip first character because windows allows env vars to begin with equal sign
var splitPoint = str.IndexOf('=', 1);
var envVarName = str.Substring(0, splitPoint);
var envVarVal = str.Substring(splitPoint + 1);
envVars.Add(envVarName, envVarVal);
next = (IntPtr)((Int64)next + (str.Length * 2) + 2);
}
DestroyEnvironmentBlock(lpEnvironment);
CloseHandle(primaryToken);
return envVars;
}
private static uint STANDARD_RIGHTS_REQUIRED = 0x000F0000;
private static uint STANDARD_RIGHTS_READ = 0x00020000;
private static uint TOKEN_ASSIGN_PRIMARY = 0x0001;
private static uint TOKEN_DUPLICATE = 0x0002;
private static uint TOKEN_IMPERSONATE = 0x0004;
private static uint TOKEN_QUERY = 0x0008;
private static uint TOKEN_QUERY_SOURCE = 0x0010;
private static uint TOKEN_ADJUST_PRIVILEGES = 0x0020;
private static uint TOKEN_ADJUST_GROUPS = 0x0040;
private static uint TOKEN_ADJUST_DEFAULT = 0x0080;
private static uint TOKEN_ADJUST_SESSIONID = 0x0100;
private static uint TOKEN_READ = (STANDARD_RIGHTS_READ | TOKEN_QUERY);
private static uint TOKEN_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED | TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE | TOKEN_IMPERSONATE | TOKEN_QUERY | TOKEN_QUERY_SOURCE | TOKEN_ADJUST_PRIVILEGES | TOKEN_ADJUST_GROUPS | TOKEN_ADJUST_DEFAULT | TOKEN_ADJUST_SESSIONID);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern bool CloseHandle(IntPtr handle);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern int GetLastError();
[DllImport("userenv.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern bool CreateEnvironmentBlock(out IntPtr lpEnvironment, IntPtr hToken, bool bInherit);
[DllImport("userenv.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool DestroyEnvironmentBlock(IntPtr lpEnvironment);
[DllImport("advapi32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool OpenProcessToken(IntPtr ProcessHandle,
UInt32 DesiredAccess, out IntPtr TokenHandle);
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr GetCurrentProcess();
public static int Main()
{
// Loop indefinitely till user hits escape
do
{
// Get environment variables
var vars = EnvVarGetter.GetEnvironmentVariables();
// Log them
foreach(var pair in vars)
{
Console.WriteLine(pair);
}
while (!Console.KeyAvailable)
{
}
} while (Console.ReadKey(true).Key != ConsoleKey.Escape);
return 0;
}
}