Как удаленно изменять переменные среды с помощью .NET?

Мне нужен способ расширения переменной среды на удаленной машине.

Предположим, что у меня есть путь к папке %appdata%\MyApp\Plugins или %ProgramFiles%\MyCompany\MyApp\Plugins, и я хочу перечислить файлы в этой папке для целей аудита. Единственная проблема заключается в том, что я хочу сделать это на удаленной машине, но, тем не менее, у меня есть доступ администратора.

Дополнительный вопрос (но не обязательно) - как это сделать для данного пользователя на удаленной машине?

Ответ 1

Вы бы использовали GetFolderPath. Есть несколько различных значений SpecialFolder, которые вы могли бы использовать, включая ProgramFiles и ApplicationData

string path = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles);

Затем вы можете просто объединить его с остальной частью вашего пути.

string full_path = Path.Combine(path, "\MyApp\Plugins");

На удаленной машине похоже, что вы можете попробовать что-то вроде this

ConnectionOptions co = new ConnectionOptions();
// user with sufficient privileges to connect to the cimv2 namespace
co.Username = "administrator"; 
// his password
co.Password = "adminPwd";
ManagementScope scope = new ManagementScope(@"\\BOBSMachine\root\cimv2", co);
SelectQuery query = new SelectQuery("Select windowsdirectory from Win32_OperatingSystem");
ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query);
foreach (ManagementObject windir in searcher.Get())
   Console.WriteLine("Value = {0}", windir["windowsdirectory"]);

Или для списка всех переменных удаленной среды и их значений, от здесь

public static void GetSysInfo(string domain, string machine, string username, string password)
{
    ManagementObjectSearcher query = null;
    ManagementObjectCollection queryCollection = null;

    ConnectionOptions opt = new ConnectionOptions(); 

    opt.Impersonation = ImpersonationLevel.Impersonate; 
    opt.EnablePrivileges = true; 
    opt.Username = username; 
    opt.Password = password; 
    try 
    { 
        ManagementPath p = new ManagementPath("\\\\" +machine+ "\\root\\cimv2");   

        ManagementScope msc = new ManagementScope(p, opt); 

        SelectQuery q= new SelectQuery("Win32_Environment");

        query = new ManagementObjectSearcher(msc, q, null); 
        queryCollection = query.Get(); 

        Console.WriteLine(queryCollection.Count);

        foreach (ManagementBaseObject envVar in queryCollection) 
        {
            Console.WriteLine("System environment variable {0} = {1}", 
            envVar["Name"], envVar["VariableValue"]);
        }
    } 
    catch(ManagementException e) 
    { 
        Console.WriteLine(e.Message); 
        Environment.Exit(1); 
    } 
    catch(System.UnauthorizedAccessException e) 
    { 
        Console.WriteLine(e.Message); 
        Environment.Exit(1); 
    } 
}

OP Edit: Также %AppData% можно найти из реестра (можно сделать удаленно) в HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders и Program Files в HKLM\Software\Microsoft\Windows\CurrentVersion, под ProgramfilesDir.

Ответ 2

Вопрос не имеет смысла. Переменные среды не относятся к машинным переменным. Например, вы можете ожидать, что %appdata% укажет внутри каталога C:\users\, но точно там, где явно зависит от пользователя. Вход в систему по-прежнему не помогает вам; это просто сообщит вам, где находится admin %appdata%.

Ответ 3

Переменные среды - это объединение параметров "puter-wide" и "per-user". Выполненный процесс может изменять свою среду, а когда он порождает другой процесс, этот процесс наследует среду процесса, который его создал.

Если у вас нет доступа к процессу, запущенному на удаленном компьютере (или его можно запустить), нет такой вещи, как "среда": контекст для этого просто не существует. Окружение конкретного процесса является функцией следующего:

  • среда, унаследованная от среды родительского процесса (которая может работать под другой учетной записью пользователя, чем дочерний процесс.)
  • настройки среды компьютера.
  • любые настройки среды, заданные пользователем.
  • любые изменения, сделанные самим процессом.

При этом Windows сохраняет свои параметры переменной среды в реестре:

  • Пользовательские переменные.
    HKEY_CURRENT_USER\Environment
  • Системные переменные.
    HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment

Если у вас есть подходящий доступ к реестру удаленных компьютеров, вы должны уловить, что вам нужно.

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

Ответ 4

Насколько я могу судить, единственный способ разрешить% ProgramFiles% - через реестр, так как это не отображается в Win32_Environment (несмотря на документацию, указывающую на другое). Так что это прекрасно работает:

$key = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey([Microsoft.Win32.RegistryHive]::LocalMachine,$serverName);
$versionKey = $key.OpenSubKey('SOFTWARE\Microsoft\Windows\CurrentVersion');
$versionKey.GetValue('ProgramFilesDir')

Однако я не могу использовать этот подход, чтобы вернуть папку Program Files (x86) - ключ, который я вижу в реестре, не отображается "с помощью API реестра". Странно.

Конечно, если бы вы запускали Powershell Remoting на удаленной машине, я предполагаю, что это будет довольно легко...