I am running the following code on an italian OS:
Rename-Computer -NewName 'NewCompName' -ErrorAction Stop -DomainCredential ($dcreds)
In several different cases I see these error messages:
- Impossibile rinominare il computer 'OldCompName' in 'NewCompName' a causa dell'eccezione seguente: L'account di riferimento è momentaneamente bloccato e non è consentito l'accesso.
- Rename-Computer : Impossibile rinominare il computer 'OldCompName' in 'NewCompName' a causa dell'eccezione seguente: Nome utente o password non corretta.
- Impossibile rinominare il computer 'OldCompName' in 'NewCompName' a causa dell'eccezione seguente: Account già esistente.
- Rename-Computer : Impossibile rinominare il computer 'OldCompName' in 'NewCompName' a causa dell'eccezione seguente: Accesso negato.
- Rename-Computer : Il computer 'OldCompName' con il nuovo nome 'NewCompName' verrà ignorato perché il nuovo nome è uguale a quello corrente.
If I prepend [Threading.Thread]::CurrentThread.CurrentUICulture = 'en-US'; to the command above, I get the following errors (all of them are partially translated as you can see except the last one):
- Rename-Computer : Fail to rename computer 'OldCompName' to 'NewCompName' due to the following exception: L'account di riferimento è momentaneamente bloccato e non è consentito l'accesso.
- Rename-Computer : Fail to rename computer 'OldCompName' to 'NewCompName' due to the following exception: Nome utente o password non corretta.
- Rename-Computer : Fail to rename computer 'OldCompName' to 'NewCompName' due to the following exception: Account già esistente.
- Rename-Computer : Fail to rename computer 'OldCompName' to 'NewCompName' due to the following exception: Accesso negato.
- Rename-Computer : Skip computer 'OldCompName' with new name 'NewCompName' because the new name is the same as the current name.
Now my issue is that I am writing a script for which I need to handle different errors with different actions. My company has offices all around the World and we are dealing with OSes in more than a dozen different languages. The type of error matching I am doing is of this kind:
If ($_.Exception.Message -match 'The account already exists\.$') {...}
This is because all exceptions are of the kind [System.InvalidOperationException] (when catching typed exceptions) and even dissecting the exception I cannot find any reference to a numeric error code or else I can use through languages that is consistent and non-culture-specific.
Quite honestly I understand there are limitations when using MSDOS commands but in PS/.Net I expected that the developers have considered those challenges and given a way to work around them. I realize that the 2 different part of the errors come from different layers so the last part is likely surfacing from a stacked down call or something but it is in fact the second part that I care to address specifically all the various cases.
Any thoughts on how to deal with those various errors with different sections of code for each?
I have tried using [Threading.Thread]::CurrentThread.CurrentUICulture = 'en-US' and also set LANG=en_US.UTF-8 none did the trick.
The fact that you're getting localized PowerShell error messages implies that you're using Windows PowerShell rather than PowerShell (Core) 7+, given that the latter has never been localized.
The parts of the error messages that remain in Italian - despite switching the UI culture to
en-US(US English) with[Threading.Thread]::CurrentThread.CurrentUICulture = 'en-US'- presumably came from the exception messages associated with .NET Framework APIs, which PowerShell only surfaces.However, while built-in .NET Framework APIs respect an in-process UI-culture change too (unlike built-in .NET (Core) APIs, which seemingly aren't localized), this does not seem to extend to system error messages, i.e. those associated with the error codes returned from WinAPI functions - they remain in the language that is persistently configured for the current user.
In other words: You'd have to make
en-USthe current user's default UI language in order to see your error messages fully in English, e.g. withSet-WinUILanguageOverrideen-US, but that is presumably undesired - and would also require logging off and back on for the change to take effect.However, you may be able to bypass the issue in favor of a more robust solution that doesn't rely on matching the text of error/exception messages:
Inspect the
.FullyQualifiedErrorIdproperty of the[ErrorRecord]instances that PowerShell emits (which may or may not wrap .NET exceptions).Its value is culture-invariant, and usually provides a specific clue to the nature of the error - though I don't know if it is specific enough in all cases of interest to you.
Here's a simple example, which uses the common
-ErrorVariableparameter to capture (non-terminating) errors in a self-chosen variable for later inspection:In the example above, which uses a
switchstatement to evaluate the resulting errors, regex'^NewNameIsOldName'prefix-matches the full value of.FullyQualifiedErrorId,'NewNameIsOldName,Microsoft.PowerShell.Commands.RenameComputerCommand'(of course, you're free to match by the full value too).