Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
c#更改用户区域性,相当于powershell中的设置区域性_C#_.net - Fatal编程技术网

c#更改用户区域性,相当于powershell中的设置区域性

c#更改用户区域性,相当于powershell中的设置区域性,c#,.net,C#,.net,我需要运行一段代码(c#或powershell),它将在系统级别而不是线程级别设置用户区域性。即,所说的代码将运行,当我再次打开控制面板时,我将看到格式设置更改为该设置。我看过很多关于CultureInfo的对话,但它们都是针对该线程的,我需要用户级别的。使用.NET 4.6.1和windows 7。powershell中的cmdlet仅适用于Windows 8和10 我在CultureInfo中尝试了很多方法,比如在.net4.6和更高版本中,它是读/写的。但是,它似乎只适用于当前线程。但在执

我需要运行一段代码(c#或powershell),它将在系统级别而不是线程级别设置用户区域性。即,所说的代码将运行,当我再次打开控制面板时,我将看到格式设置更改为该设置。我看过很多关于CultureInfo的对话,但它们都是针对该线程的,我需要用户级别的。使用.NET 4.6.1和windows 7。powershell中的cmdlet仅适用于Windows 8和10

我在CultureInfo中尝试了很多方法,比如在.net4.6和更高版本中,它是读/写的。但是,它似乎只适用于当前线程。但在执行此操作(见下文)后,我转到控制面板,看不到我的更改。powershell cmdlet可为您执行此操作

CultureInfo.CurrentCulture = new CultureInfo("en-US");
CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("en-US");
CultureInfo.DefaultThreadCurrentUICulture = new CultureInfo("en-US");
CultureInfo.CurrentUICulture = new CultureInfo("en-US");
似乎没有一个能做到简单的powershell cmdlet所能做到的

# works for win8 and win10 only
set-culture en-US

我希望有一种方法来更改用户的当前区域性,然后通过以下自动化任务打开的任何应用程序都将使用该设置执行。提前谢谢

这是因为,正如文档中明确指出的,通过
CultureInfo
设置当前区域性是特定于线程的

Powershell的
set culture
命令通过调用非托管Win32函数执行完全不同的操作,从cmdlet的反汇编中可以看出:

[SuppressMessage("Microsoft.Usage", "CA1806:DoNotIgnoreMethodResults")]
    protected override void ProcessRecord()
    {
        if (LPAPIWrapper.NlsUpdateLocale(cultureinfo.Name, NLS_LOCALE_SELECT | NLS_LOCALE_CLEAR_USER_DATA) == 0)
        {
            NumberFormatInfo numberFormat = cultureinfo.NumberFormat;
            DateTimeFormatInfo dateTimeFormat = cultureinfo.DateTimeFormat;
            LPAPIWrapper.SetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_ICURRDIGITS, numberFormat.CurrencyDecimalDigits.ToString());
            LPAPIWrapper.SetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SMONDECIMALSEP, numberFormat.CurrencyDecimalSeparator.ToString());
            LPAPIWrapper.SetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SMONTHOUSANDSEP, numberFormat.CurrencyGroupSeparator.ToString());
            SetGroupSizes(LOCALE_SMONGROUPING, numberFormat.CurrencyGroupSizes);
            LPAPIWrapper.SetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_INEGCURR, numberFormat.CurrencyNegativePattern.ToString());
            LPAPIWrapper.SetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_ICURRENCY, numberFormat.CurrencyPositivePattern.ToString());
            LPAPIWrapper.SetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SCURRENCY, numberFormat.CurrencySymbol.ToString());
            LPAPIWrapper.SetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_IDIGITSUBSTITUTION, numberFormat.DigitSubstitution.ToString());
            string text = "";
            string[] nativeDigits = numberFormat.NativeDigits;
            foreach (string str in nativeDigits)
            {
                text += str;
            }
            LPAPIWrapper.SetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SNATIVEDIGITS, text);
            LPAPIWrapper.SetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SNEGATIVESIGN, numberFormat.NegativeSign.ToString());
            LPAPIWrapper.SetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_IDIGITS, numberFormat.NumberDecimalDigits.ToString());
            LPAPIWrapper.SetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SDECIMAL, numberFormat.NumberDecimalSeparator.ToString());
            LPAPIWrapper.SetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_STHOUSAND, numberFormat.NumberGroupSeparator.ToString());
            SetGroupSizes(LOCALE_SGROUPING, numberFormat.NumberGroupSizes);
            LPAPIWrapper.SetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_INEGNUMBER, numberFormat.NumberNegativePattern.ToString());
            LPAPIWrapper.SetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SPOSITIVESIGN, numberFormat.PositiveSign.ToString());
            LPAPIWrapper.SetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SDATE, dateTimeFormat.DateSeparator.ToString());
            LPAPIWrapper.SetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_STIME, dateTimeFormat.TimeSeparator.ToString());
            LPAPIWrapper.SetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SSHORTDATE, dateTimeFormat.ShortDatePattern.ToString());
            LPAPIWrapper.SetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SLONGDATE, dateTimeFormat.LongDatePattern.ToString());
            LPAPIWrapper.SetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_STIMEFORMAT, dateTimeFormat.LongTimePattern.ToString());
            LPAPIWrapper.SetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_S1159, dateTimeFormat.AMDesignator.ToString());
            LPAPIWrapper.SetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_S2359, dateTimeFormat.PMDesignator.ToString());
            LPAPIWrapper.SetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_IFIRSTDAYOFWEEK, ((int)(dateTimeFormat.FirstDayOfWeek + 6) % 7).ToString());
            LPAPIWrapper.SetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_IFIRSTWEEKOFYEAR, ((int)dateTimeFormat.CalendarWeekRule).ToString());
            LPAPIWrapper.SetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SYEARMONTH, dateTimeFormat.YearMonthPattern.ToString());
            LPAPIWrapper.SendNotifyMessage((IntPtr)65535, 26u, IntPtr.Zero, "intl");
        }
    }

如果您想进一步分析发生的情况,可以反汇编位于
C:\Windows\Microsoft.NET\assembly\GAC\u MSIL\Microsoft.InternationalSettings.Commands\v4.0\u 3.0.0.0\uu 31bf3856ad364e35\Microsoft.InternationalSettings.Commands.dll的dll,这是一个老版本,但万一有人偶然发现:
我反汇编了DLL,最后使用以下代码来设置区域设置。
请看我在代码库中的注释

[DllImport ("kernelbase.dll", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern int NlsUpdateLocale (string LocaleName, int Flags);

public static void SetLocale (string locale)
{
  // NOTE: this code was derived by disassembling the Set-Culture PowerShell command located at C:\Windows\Microsoft.NET\assembly\GAC_MSIL\Microsoft.InternationalSettings.Commands\v4.0_3.0.0.0__31bf3856ad364e35\Microsoft.InternationalSettings.Commands.dll
  //   However the PowerShell command has a branch that executes when the result of NlsUpdateLocale is not 0.
  //   This branch then sets all values that make up a locale separately. This is probably for cultures that are customized.
  //   Thus this branch is not implemented here and 0 simply leads to an error stating that Set-Culture should be called for that user manually in order to have the correct date, time, number and currency format for Excel rendering.
  var NLS_LOCALE_SELECT = 1;
  var NLS_LOCALE_CLEAR_USER_DATA = 2;

  var result = NlsUpdateLocale (locale, NLS_LOCALE_SELECT | NLS_LOCALE_CLEAR_USER_DATA);

  if (result != 0)
    throw new Exception ($"There ws an error setting the user locale to '{locale}'. Please set the locale for the service user of this service manually by executing the PowerShell command 'Set-Culture {locale}'. Result of NlsUpdateLocale was {result} instead of 0. ");
}
当使用Windows已知的区域设置(或区域性,无论您如何称呼它们)时,此方法应该可以使用。例如:en-US、de-AT、de-de等等

考虑到一些较旧的操作系统可能不支持较新操作系统所支持的所有区域性。例如,Windows Server 2012在.NET代码中没有可用的en CH,而Windows 10有可用的en CH。然而,我并没有测试这个DLL方法是否也适用,但我认为是这样的


通过发出以下PowerShell命令,您可以获得受支持的.NET区域性列表:
[System.Globalization.CultureInfo]::GetCultures([System.Globalization.CultureType]::AllCultures)

关于.NET代码的好处在于,使用一个像样的反汇编程序可以轻松地进行反编译。糟糕的是,你现在会发现做这件事需要什么。最好去。请注意,cmdlet似乎已停止使用,我看到一条关于它有bug的说明。可能与的重复