RegistryKey.SetValue нарушая PATH - PullRequest
       32

RegistryKey.SetValue нарушая PATH

0 голосов
/ 28 октября 2019

Я пытаюсь добавить путь к своему приложению к пути к системной среде, и хотя следующий код добавляет его соответствующим образом:

    using (RegistryKey regKey = Registry.LocalMachine.OpenSubKey(@"SYSTEM\CurrentControlSet\Control\Session Manager\Environment\", true)) {
      String pathString = regKey.GetValue("PATH", "", RegistryValueOptions.DoNotExpandEnvironmentNames).ToString();
      if (pathString[pathString.Length - 1] != ';') {
        pathString = pathString + ";";
      }
      regKey.SetValue("PATH", pathString + Directory.GetCurrentDirectory() + ";");
    }

, он не вступит в силу, пока я не посмотрю на переменные среды черезПанель управления, а затем, когда я это сделаю, она прервет все другие ссылки на переменные окружения в этом пути, например,% SystemRoot% \ System32, пока ... Я скопирую всю строку пути из и обратно в переменную PATH и повторно сохраню ее.

Так что, по-видимому, есть часть, которую мне не хватает, потому что путь на 100% правильный, просто кажется, что он не был обновлен в системе.

Редактировать: Я нашелэто изменение:

regKey.SetValue("PATH", pathString + Directory.GetCurrentDirectory() + ";");

Кому:

regKey.SetValue("PATH", pathString + Directory.GetCurrentDirectory() + ";", RegistryValueKind.ExpandString);

Устранит проблему с разрывом ссылочных переменных (не знаю, зачем мне это нужно, они имеют ключ REG_EXPAND_SZ иЯ не изменяю его), но у меня все еще есть проблема с тем, что путь не обновляется, пока я не отредактирую его через панель управления.

До сих пор я не нашел программный путьсделать это.

1 Ответ

0 голосов
/ 28 октября 2019

Хорошо, так что с небольшими НИОКР, похоже, мне нужно передать сообщение WM_SETTINGCHANGE в Windows. Я смог добиться этого, импортировав функцию user32.dll SendMessageTimeout следующим образом:

class NativeMsg {

  public static readonly IntPtr HWND_BROADCAST = new IntPtr(0xffff);
  public static readonly IntPtr HWND_TOP = new IntPtr(0);
  public static readonly IntPtr HWND_BOTTOM = new IntPtr(1);
  public static readonly IntPtr HWND_TOPMOST = new IntPtr(-1);
  public static readonly IntPtr HWND_NOTOPMOST = new IntPtr(-2);
  public static readonly IntPtr HWND_MESSAGE = new IntPtr(-3);

  public enum WindowsMessages : UInt32 {
  //For full list of WM_ constants reference: http://www.pinvoke.net/default.aspx/Constants.WM
    WM_SETTINGCHANGE = 0x001A
  }

  [Flags]
  public enum SendMessageTimeoutFlags : UInt32 {
    SMTO_NORMAL = 0x0,
    SMTO_BLOCK = 0x1,
    SMTO_ABORTIFHUNG = 0x2,
    SMTO_NOTIMEOUTIFNOTHUNG = 0x8,
    SMTO_ERRORONEXIT = 0x20
  }

  [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
  public static extern IntPtr SendMessageTimeout(
    IntPtr hWnd,
    WindowsMessages Msg,
    UIntPtr wParam,
    String lParam,
    SendMessageTimeoutFlags fuFlags,
    UInt32 uTimeout,
    out UIntPtr lpdwResult
  );

}

и затем вызвав ее после изменения среды с помощью:

UIntPtr lRes;
NativeMsg.SendMessageTimeout(NativeMsg.HWND_BROADCAST, NativeMsg.WindowsMessages.WM_SETTINGCHANGE, UIntPtr.Zero, "Environment", NativeMsg.SendMessageTimeoutFlags.SMTO_ABORTIFHUNG, 1000, out lRes);

, которая, кажется, работает, здесь могут быть некоторые недостатки кода, так как большую часть я получил от pinvoke.net, чьи примеры на C # не работают дословно, но это действительно делает свою работу.

...