How to expand environment variables remotely with .NET?

佐手、 提交于 2019-12-29 01:35:56

问题


I need a way to expand environment variable on a remote machine.

Suppose I have a path to a folder %appdata%\MyApp\Plugins or %ProgramFiles%\MyCompany\MyApp\Plugins and I want to list files in that folder for audit purposes. The only problem is I want to do it on a remote machine, which however I have admin access to.

An extra question (but not essential) is how to do that for given user on remote machine?


回答1:


You would use GetFolderPath. There are a bunch of different SpecialFolder values that you could use including ProgramFiles and ApplicationData

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

Then you could just combine it with the rest of your path

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

On a remote machine, it looks like you can try something like 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"]);

Or for a list of all remote environment variables and their values, from here

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: Also %AppData% can be found from registry (can be done remotely) at HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders and Program Files at HKLM\Software\Microsoft\Windows\CurrentVersion, under ProgramfilesDir.




回答2:


The question doesn't make sense. Environment variables are not per-machine variables. For instance, you can expect %appdata% to point inside the C:\users\ directory, but precisely where obviously depends to the user. Logging in as admin still doesn't help you; that would merely tell you where the admin's %appdata% is.




回答3:


Environment variables are the amalgamation of 'puter-wide and per-user settings. A running process may modify its environment and when it spawns another process, that process inherits the environment of the process that created it.

Unless you have access to a process running on the remote machine (or can start one), there's no such thing as an 'environment': the context for it simply doesn't exist. The environment of a particular process is a function of all of the following:

  • the environment inherited from the parent process' environment (which may be running under a different user account than the child process.)
  • computer-wide environment settings.
  • any environment settings specified by the user.
  • any changes made by the process itself.

That being said, Windows keeps its environment variable settings in the registry:

  • User variables.
    HKEY_CURRENT_USER\Environment
  • System variables.
    HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment

If you have appropriate access to the remote machine's registry, you should be able to fish out what you need.

Note that environment variables may be defined in terms of other environment variables: I believe you'll likely to take care of the proper expansion yourself.




回答4:


As far as I can tell, the only way of resolving %ProgramFiles% is via the registry, since this is not exposed in Win32_Environment (despite the documentation suggesting otherwise). So this works fine:

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

However, I can't appear to use this approach to get back the Program Files (x86) folder - the key I can see in the registry doesn't 'show' using the registry API. Strange.

Of course if you were running Powershell Remoting on the remote machine, I imagine this would be fairly easy...



来源:https://stackoverflow.com/questions/5031111/how-to-expand-environment-variables-remotely-with-net

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!