Issue with English non-US Culture - powershell

I am able to use Set-Culture (Powershell as Admin) to set the Current Culture to "en-DE" which is English (Germany). However, when I run the different PS commands to view the Current Culture, I am still getting en-US. I checked my Region (Format) and Location as well.
Do I have to change the system locale as well to Germany (German) ?
This is causing an error in an application, because the datetime format is different from en-DE to en-US and causing the date to be read incorrectly.
When I Set-Culture to de-DE, everything appears to be in working order.
I make sure to run Powershell Console as Administrator, Set-Culture, close console. Open Powershell and run Get-Culture, [CultureInfo]::CurrentCulture, [CultureInfo]::CurrentUICulture and a few more to check and and still getting en-US

Note: Use of en-DE as a culture identifier - i.e., mixing language en (English) with normally unrelated region/country DE (Germany) - requires Windows 10 with release channel 1607 or later or Windows Server 2016, according to Microsoft.
However, there's a bug that prevents use of such mixed cultures, observed on Windows 10 Pro (64-bit; Version 1709, OS Build: 16299.371)
While you can successfully set such mixed-culture values with Set-Culture, subsequent sessions do not recognize it and fall back to en-US (as reflected in $PSCulture, Get-Culture and [cultureinfo]::currentCulture)
This problem has been reported on UserVoice.
Note that PowerShell Core is not affected (but it doesn't support Set-Culture).
The rest of this answer discusses persistently setting the current user's culture in general, irrespective of the bug.
Set-Culture - via the registry - sets the culture for future PowerShell sessions (only), not (also) for the current session.
Get-Culture, by contrast, only ever reports the current session's culture at session-startup time. That is, if you change the culture during a session (see below), it will not be reflected in Get-Culture.
In order to also apply the newly set culture to the current session, run the following in addition to the Set-Culture call:
[cultureinfo]::CurrentCulture = 'de-DE'
Caveat re interactive (command-line) use:
In Windows PowerShell (still as of v5.1), the active culture is reset after every command submitted; e.g.,
[cultureinfo]::CurrentCulture = 'de-DE'; Get-Date works as expected, because it is part of the same command line, but when executing just Get-Date as the next command, the current culture has reverted to the one that was current at session-startup time.
This problem has been fixed in PowerShell Core.
This perhaps surprising asymmetry - Set-Culture only applying to future sessions, but Get-Culture reporting the current session's (startup) culture - is something that may change in future PowerShell Core versions.

Related

PowerShell fails to interpret commands such as "which"

My windows Powershell gives the expected results when interpreting commands such as "date" and "echo", while problems occur when it interprets such commands as "which" and "tail".
I thought it might be that I haven't add the address of these commands to the target directories, but where can I probably find these commands.
What happens when I apply "which", with the same thing happening when applying "tail"
which and tail are the names of external programs, which are unrelated to PowerShell. These programs can only be expected to be present on Unix-like platforms, not (natively) on Windows. (However, they would be present in Unix-like subsystems on Windows, such as WSL.)
By contrast, date and echo are (potentially) commands that are built into PowerShell, irrespective of what platforms it runs on:
echo is an alias of PowerShell's Write-Output cmdlet on all platforms.
date - unless an external program by that name is present in a directory listed in $env:PATH on a given platform - refers to the built in Get-Date cmdlet.
Note: This relies on PowerShell's ill-conceived default verb feature, which falls back on prefixing a command name with Get- if no command form is found by the given name. This shouldn't be relied upon, both in the interest of conceptual clarity and to avoid unnecessary overhead. Also, this fallback is (unexpectedly) not reported by the Get-Command discussed below, and also not by Get-Help - see GitHub issue #3987.
Use Get-Command to determine what command form, if any, a given name refers to (add -All to see if potentially multiple forms exist, with the effective one being listed first).

Same script, same console, why do colors work in Powershell but not cmd.exe? [duplicate]

I wrote a program which prints a string, which contains ANSI escape sequences to make the text colored. But it doesn't work as expected in the default Windows 10 console, as you can see in the screenshot.
The program output appears with the escape sequences as printed characters.
If I feed that string to PowerShell via a variable or piping, the output appears as intended (red text).
How can I achieve that the program prints colored text without any workarounds?
This is my program source (Haskell) - but the language is not relevant, just so you can see how the escape sequences are written.
main = do
let red = "\ESC[31m"
let reset = "\ESC[39m"
putStrLn $ red ++ "RED" ++ reset
Note:
The following applies to regular (legacy) console windows on Windows (provided by conhost.exe), which are used by default, including when a console application is launched from a GUI application.
By contrast, the console windows (terminals) provided by Windows Terminal as well as Visual Studio Code's integrated terminal provide support for VT / ANSI escape sequences by default, for all console applications.
While console windows in Windows 10 do support VT (Virtual Terminal) / ANSI escape sequences in principle, support is turned OFF by default.
You have three options:
(a) Activate support globally by default, persistently, via the registry, as detailed in this SU answer.
In short: In registry key [HKEY_CURRENT_USER\Console], create or set the VirtualTerminalLevel DWORD value to 1
From PowerShell, you can do this programmatically as follows:
Set-ItemProperty HKCU:\Console VirtualTerminalLevel -Type DWORD 1
From cmd.exe (also works from PowerShell):
reg add HKCU\Console /v VirtualTerminalLevel /t REG_DWORD /d 1
Open a new console window for changes to take effect.
See caveats below.
(b) Activate support from inside your program, for that program (process) only, with a call to the SetConsoleMode() Windows API function.
See details below.
(c) Ad-hoc workaround, from PowerShell:
PowerShell (Core) 7+: Enclose external-program calls in (...) (invariably collects all output first before printing):
(.\test.exe)
Streaming Windows PowerShell-only alternative: Pipe output from external programs to Write-Host
.\test.exe | Out-Host
See details below.
Re (a):
The registry-based approach invariably activates VT support globally, i.e., for all console windows, irrespective of what shell / program runs in them:
Individual executables / shells can still deactivate support for themselves, if desired, using method (b).
Conversely, however, this means that the output of any program that doesn't explicitly control VT support will be subject to interpretation of VT sequences; while this is generally desirable, hypothetically this could lead to misinterpretation of output from programs that accidentally produce output with VT-like sequences.
Note:
While there is a mechanism that allows console-window settings to be scoped by startup executable / window title, via subkeys of [HKEY_CURRENT_USR\Console], the VirtualTerminalLevel value seems not to be supported there.
Even if it were, however, it wouldn't be a robust solution, because opening a console window via a shortcut file (*.lnk) (e.g. from the Start Menu or Task Bar) wouldn't respect these settings, because *.lnk files have settings built into them; while you can modify these built-in settings via the Properties GUI dialog, as of this writing the VirtualTerminalLevel setting is not surfaced in that GUI.
Re (b):
Calling the SetConsoleMode() Windows API function from inside the program (process), as shown here, is cumbersome even in C# (due to requiring P/Invoke declarations), and may not be an option:
for programs written in languages from which calling the Windows API is not supported.
if you have a preexisting executable that you cannot modify.
In that event, option (c) (from PowerShell), discussed next, may work for you.
Re (c):
PowerShell automatically activates VT (virtual terminal) support for itself when it starts (in recent releases of Windows 10 this applies to both Windows PowerShell and PowerShell (Core) 7+) - but that does not extend to external programs called from PowerShell, in either edition, as of v7.3.2.
Separately, in v7.2+ there is the $PSStyle.OutputRendering preference variable, which controls whether PowerShell commands produce colored output via the formatting system, such as the colored headers of Get-ChildItem output. However, this setting has no effect on (direct) output from external programs. $PSStyle.OutputRendering defaults to Host, meaning that only formatted output that prints to the terminal (console) is colored. $PSStyle.OutputRendering = 'PlainText' disables coloring, and $PSStyle.OutputRendering = 'Ansi' makes it unconditional; see this answer for more information.
However, as a workaround you can relay an external program's (stdout) output via PowerShell's (success) output stream, in which case VT sequences are recognized:
As of PowerShell (Core) 7.3.2, this only works either by enclosing the call in (...) or by using Out-String, but note that all output is invariably collected first before it is printed.[1]
(.\test.exe)
In Windows PowerShell, in addition to the above, streaming the relayed output is possible too, by piping to Write-Host (Out-Host, Write-Output or Out-String -Stream would work too)
.\test.exe | Write-Host
Note: You need these techniques only if you want to print to the console. If, by contrast, you want to capture the external program's output (including the escape sequences), use $capturedOutput = .\test.exe
Character-encoding caveat: Windows PowerShell by default expects output from external programs to use the OEM code page, as defined by the legacy system locale (e.g., 437 on US-English systems) and as reflected in [console]::OutputEncoding.
.NET console programs respect that setting automatically, but for non-.NET programs (e.g., Python scripts) that use a different encoding (and produce not just pure ASCII output (in the 7-bit range)), you must (at least temporarily) specify that encoding by assigning to [console]::OutputEncoding; e.g., for UTF-8:
[console]::OutputEncoding = [Text.Encoding]::Utf8.
Note that this is not only necessary for the VT-sequences workaround, but generally necessary for PowerShell to interpret non-ASCII characters correctly.
PowerShell Core (v6+), unfortunately, as of v7.3.2, still defaults to the OEM code page too, but that should be considered a bug (see GitHub issue #7233), given that it otherwise defaults to UTF-8 without BOM.
[1] Using Out-String -Stream or its built-in wrapper function, oss, is tempting in order to achieve streaming output, but this no longer works as of PowerShell 7.3.2, possibly due to the optimization implemented in GitHub PR #16612.
Thanks to user mklement0 for making me aware that VT support is not enabled automatically. This made me look in the right direction and I found this helpful post.
So to answer my question: Add or set the registry key
HKCU:\Console - [DWORD] VirtualTerminalLevel = 1
Restart the console and it works.
For Haskell specifically, you need to call the hSupportsANSIWithoutEmulation function to enable ANSI escape sequences in your program on Windows 10.

Tree looks different on Cmd than it does on Powershell

Why does the tree command look different on Powershell than what it does on Cmd.
The problem only occurs in the PowerShell ISE, where output from external programs such as tree.com isn't passed straight through to the console.
Consider migrating away from the PowerShell ISE, given that it is no longer actively developed and there are reasons not to use it (bottom section), notably the inability to run PowerShell [Core] 6+, where all future effort will go. The editor that offers the best PowerShell development experience, across platforms, is Visual Studio Code, combined with its PowerShell extension, which is under active development.
To fix it, you must (temporarily) change [Console]::OutputEncoding to match your system's active OEM legacy code page, because that is the character encoding tree.com uses:
# Switch the encoding that PowerShell expects external programs to use
# to the active OEM code page.
[Console]::OutputEncoding = [System.Text.Encoding]::GetEncoding(
[cultureinfo]::CurrentCulture.TextInfo.OEMCodePage
)
# tree.com now produces the expected output in the ISE
tree
Note:
Even in a regular console window / Windows Terminal window and in Visual Studio Code [Console]::OutputEncoding can come into play, but only when you capture or redirect an external program's output (e.g., $treeOutput = tree or tree | ...).
As indicated above, this is not necessary for direct-to-display output - except in the ISE, where [Console]::OutputEncoding matters even then, which default to the system's active ANSI legacy code page.
For PowerShell to correctly interpret an external program's output when capturing or redirecting it, [Console]::OutputEncoding must match the actual encoding used by that program.
Therefore, if you want to capture or redirect tree.coms output, you may have to set [Console]::OutputEncoding:
In short, unless [Console]::OutputEncoding.CodePage matches the code-page number reported by [cultureinfo]::CurrentCulture.TextInfo.OEMCodePage - e.g., 437 on US-English systems - setting [Console]::OutputEncoding is needed.
In console windows and Windows Terminal windows this is generally not necessary (as of PowerShell 7.0) - it is only necessary if you've explicitly changed the active code page to UTF-8, for instance - see this answer; note that UTF-8 may become the default over time.
In Visual Studio Code, however, it is necessary by default, because in the PowerShell Integrated Console [Console]::OutputEncoding defaults to UTF-8 (code page 65001).
I believe it's because it's one of those commands that PowerShell runs cmd for in the background then pipes the output to Write-Host, similar to ping or ipconfig

PowerShell errors output in prefered language

Env:
OS. Windows 7 client machine
Powershell v. 4
This could be a duplicate question,but the solution provide to this other question unfortunately did not worked for me.
I tried both in Powershell shell*as administrator and in ISE.
When indeed I run that in PS:
Update-Help -UICulture en-US
I just get another prompt apparently doing nothing.
Same for :
Update-Help -UICulture en-US
Still getting error non in English(my operating system language is in German and I don't have control to change it).
I also tried to include the $ENUS and then invoke it in both profile and machine profile. Same, still having errors in German.
Then I found this, and included in the profile that script, but still without success.
Only thing is that
$PSUICulture
is returning
de-DE
But using (as from official doc) :
Set-Culture -CultureInfo en-US
is giving me an error "Die Benennung "Set-Culture" wurde nicht als Name eines Cmdlet" basically that "Set-Culture" is not a recognised as Cmdlet
At this point seems to me that I cannot change error's language as it takes that of the OS.
Anything I did not considered, checked?
In my Windows 7 Ultimate I created an additional local user,
loaded the English language pack and changed the primary language for that user to English. (these settings still apply after having upgraded to Windows 10 some time ago)
I have bitwise SSH-server and bitwise SSH-client running (free for private use) and login via SSH to the other account on the same machine.

PowerShell - Set-Culture doesn't seem to change anything

I have a Cloud Service Web Role that I need to run some PowerShell on to ensure the server is always setup in the right culture: en-AU.
The reason for this is that Microsoft could, at anytime, reset the culture values.
When I run:
Get-Culture
I get:
1033 en-US English (United States)
So then I run:
Set-Culture en-AU
But I still get:
1033 en-US English (United States)
I have tried many things but nothing seems to really change the culture.
Any help would be great.
The root cause is because you are not running the PowerShell with Administrator privilege.
Set-Culture needs Administrator privilege to be set on the system.
Just run your PowerShell in Administrator mode and your culture will be set to the new one as below:
Hope this helps!
Like petseral said in a comment above:
Changing user locale does not affect already started PowerShell instances.
You have to start new PowerShell process.