Как установить системную переменную среды в C #?

я пытаюсь установить системную переменную среды в моем приложении, но получитьSecurityException, Я проверил все, что я нашел в Google - без успеха. Вот мой код (обратите внимание, что ям администратора моего ПК и запускаю VS2012 от имени администратора):

Попытка 1

new EnvironmentPermission(EnvironmentPermissionAccess.Write, "TEST1").Demand();
Environment.SetEnvironmentVariable("TEST1", "MyTest", EnvironmentVariableTarget.Machine);

Попытка 2

new EnvironmentPermission(EnvironmentPermissionAccess.Write, "TEST1").Demand();

using (var envKey = Registry.LocalMachine.OpenSubKey(@"SYSTEM\CurrentControlSet\Control\Session Manager\Environment", true))
{

  Contract.Assert(envKey != null, @"HKLM\System\CurrentControlSet\Control\Session Manager\Environment is missing!");
  envKey.SetValue("TEST1", "TestValue");
}

Попытка 3 Также я попытался достать свойприложение с правами администратора.

Есть ли у вас другие предложения?

 David Heffernan31 окт. 2013 г., 13:04
Вы можете'просто пойти и получить разрешение. Вы должны быть повышены. И это нужно сделать во время запуска процесса.

Ответы на вопрос(1)

Решение Вопроса

документация говорит вам, как это сделать.

призваниеSetEnvironmentVariable не влияет на системные переменные окружения. Чтобы программно добавить или изменить системные переменные среды, добавьте их вHKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment ключ реестра, затем транслироватьWM_SETTINGCHANGE сообщение сlParam установить на строку"Environment", Это позволяет приложениям, таким как оболочка, забирать ваши обновления.

Итак, вам нужно записать в параметр реестра, в который вы уже пытаетесь записать. А потом транслироватьWM_SETTINGCHANGE сообщение, как описано выше. Вам нужно будет работать с повышенными правами, чтобы это удалось.

Пример кода:

using Microsoft.Win32;
using System;
using System.Diagnostics.Contracts;
using System.Runtime.InteropServices;

namespace ConsoleApplication1
{
    class Program
    {
        const int HWND_BROADCAST = 0xffff;
        const uint WM_SETTINGCHANGE = 0x001a;

        [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        static extern bool SendNotifyMessage(IntPtr hWnd, uint Msg, 
            UIntPtr wParam, string lParam);

        static void Main(string[] args)
        {
            using (var envKey = Registry.LocalMachine.OpenSubKey(
                @"SYSTEM\CurrentControlSet\Control\Session Manager\Environment",
                true))
            {
                Contract.Assert(envKey != null, @"registry key is missing!");
                envKey.SetValue("TEST1", "TestValue");
                SendNotifyMessage((IntPtr)HWND_BROADCAST, WM_SETTINGCHANGE,
                    (UIntPtr)0, "Environment");
            }
        }
    }
}

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

Environment.SetEnvironmentVariable("TEST1", "TestValue", 
    EnvironmentVariableTarget.Machine);

документация за три аргументаEnvironment.SetEnvironmentVariable перегрузка говорит:

Если целью является EnvironmentVariableTarget.Machine, переменная среды сохраняется в HKEY_LOCAL_MACHINE \ SYSTEM \ ControlSet001 \ Control \ Session Manager \ Ключ среды локального компьютера.реестр. Он также копируется во все экземпляры проводника. Затем переменная среды наследуется любыми новыми процессами, которые запускаются из проводника.

Если целью является Пользователь или Машина, другие приложения уведомляются о заданной операции с помощью сообщения Windows WM_SETTINGCHANGE.

 David Heffernan31 окт. 2013 г., 13:44
Я не понимаю этот вопрос.
 alex55531 окт. 2013 г., 13:14
Как я уже говорил, звонюOpenSubKey функция также заканчивается исключением, хотя ключ доступен
 Learner02 нояб. 2015 г., 12:01
Нет, не ошибся, но немного вводит в заблуждение, поскольку кто-то может подумать, что выдержка о C # SetEnvironmentVariable (операционная система попросила C #). Я бы добавилWinAPI» в первой строке ответа.
 David Heffernan02 нояб. 2015 г., 11:12
@Learner Ничто из того, что я написал, не так, и документация WinAPI является важной информацией. Среда выполнения .net, конечно же, построена поверх WinAPI. Но вы совершенно правы, что я упустил возможность прохожденияEnvironmentVariableTarget.Machine, Спасибо за указание на это. Я'Мы добавили эту информацию в ответ.
 David Heffernan31 окт. 2013 г., 13:21
Как я уже сказал, вам нужно запустить это повышенное. Когда вы это сделаете, вы обнаружите, что это работает. Я тестировал этот код, вы знаете!
 Igor Levicki16 февр. 2017 г., 21:45
Стоит отметить, что функция SetEnvironmentVariabl () в .Net Framework даже в последней версии 4.6.2 имеет ошибку, не проверяющую, устанавливаете ли вы переменную PATH - она все равно обрабатывает их и молча меняет тип ключа реестра для PATH от REG_EXPAND_SZ до REG_SZ и, таким образом, убить возможность использовать расширение переменной в PATH. Излишне говорить, что многие программы (и пользователи компьютеров) полагаются на расширение PATH.
 Learner02 нояб. 2015 г., 11:06
Док. выдержка из C ++ WinAPI, а не C #! Метод SetEnvironmentVariable в C # отличается от C ++. Он может получить третий параметр, который является EnvironmentVariableTarget! ... Если целью является User или Machine, другие приложения уведомляются об операции set сообщением Windows WM_SETTINGCHANGE.
 David Heffernan02 нояб. 2015 г., 12:02
@Learner Я не вижу в ответе ничего, кроме C #
 alex55531 окт. 2013 г., 13:59
когда вы запускаете программу от имени администратора, появляется предупреждение UAC, где вы должны ввести admin 'пароль и продолжить. Я хочу знать, есть ли параметры, чтобы пропустить этот шаг
 alex55531 окт. 2013 г., 13:41
Ах, это работает! Большое спасибо. Есть ли команда или параметр для подтверждения этого предупреждения UAC?
 David Heffernan02 нояб. 2015 г., 11:54
@ Ученик, которого я не знаюне думаю, чтоправильное различие. Оба приведенных выше примера кода написаны на C #, оба делают одно и то же, оба используют WinAPI для выполнения реальной работы. Я нене думаю, что этоРеально игнорировать существование WinAPI при кодировании такого рода задач в Windows. В конечном итоге любое решение проблемы приводит к записи в этот раздел реестра и отправке широковещательного сообщения.
 David Heffernan31 окт. 2013 г., 14:07
Если бы была такая вещь, это сделало бы UAC бессмысленным.т это. Если вы хотите выполнять задачи администратора, вам нужно стать администратором. Там'от этого не уйти

Ваш ответ на вопрос