8 years after this question with Windows 11 22H2 FR, in Powershell PSVersion 5.1.22621.169 the command:
FindWindow("ConsoleWindowClass", "Administrateur : X:\windows\system32\cmd.exe")
outputs 0
.
After some rechearch, I use SPY for reading caption and class.
I have copy/pasted from the editbox of SpY into a PS string variable ($title
).
And I notice in this copy/pasted $title
string:
[byte]$title[14]= 160
[byte]$title[14]
looks like a space and is here, in the middle "r :"
String index 14
is for french version of OS.
FindWindow
returns a good handle with this character!
Question : Why [byte]$title[14] = 160
(at index 14
in the string for FR) is found in the title of an elevated cmd
console? Is it normal? Where is it documented?
The code I used:
$code = @'
[DllImport("user32.dll", CharSet=CharSet.Unicode, SetLastError = true)]
public static extern IntPtr FindWindow(string ClassName,string WindowName);
[DllImport("user32.dll", CharSet=CharSet.Unicode, SetLastError = true)]
public static extern bool ShowWindow( IntPtr hWnd, int nCmdShow);
[DllImport("user32.dll", CharSet=CharSet.Unicode, SetLastError = true)]
public static extern IntPtr SetWindowText(IntPtr HWND, string Text);
'@
Add-Type -MemberDefinition $code -Name Window -Namespace Test
# please, open an elevated console cmd
#Be carrefull, "administrateur" in french OS. So, adapt if you test...
# here, "[byte]$title[14] = 32" -> it's a space, it's not 160
$name = "Administrateur : X:\windows\system32\cmd.exe"
$classW = "ConsoleWindowClass"
[Test.Window]::FindWindow($classW, $name)
#it gives 0
I don't know how to put a code point of 160
into a system.string
(I can only copy/paste the title from SPY ). So I can't give the correct code for the second test.
In summary:
I launch a cmd console elevated and see the title:
"Administrateur : X:\windows\system32\cmd.exe"
...............|..............................
The above line is for locating the position of the "strange" character with code point of 160
.
With PS, i try to use FindWindow
to get a handle on this window
If I copy/paste the title from SPY ([byte]$title[14] = 160
), FindWindow
is OK.
If I enter the text from the keyboard ([byte]$title[14] = 32
), FindWindow
returns 0 (error).
Is it normal to get a title text with code point 160
(at index 14
in the string for FR)?
CodePudding user response:
The Unicode character whose code point is 160
(decimal) / 0xA0
(hexadecimal) is:
U 00A0
)
It looks just like a space, but is obviously different from it.
To embed in a string, you have several options; the easiest is to use an expandable (double-quoted) string ("..."
) with either an embedded subexpression ($(...)
or, in PowerShell (Core) 6 only, a Unicode escape sequence:
# Subexpression:
# Works in Windows PowerShell too.
"Administrateur$([char] 0xA0): X:\windows\system32\cmd.exe"
# Unicode escape sequence:
# Works in PowerShell (Core) 6 only
"Administrateur`u{A0}: X:\windows\system32\cmd.exe"
As for why this character is present:
The original purpose of the character is to prevent automatic line breaks between words, which a regular space character wouldn't do - see Wikipedia's article on the non-breaking space.
Given that window titles are always single-line, that alone cannot be the reason for the character's use.
With English or German as the system language, for instance, the character is not present: there's simply no character between the (localized) word for administrator and :
zett42 observes the following with respect to why the character is present in French, for instance:
In French (and possibly other languages),
:
(and other punctuation) must be preceded by a (non-breaking) space - see What’s The Deal With French Spacing?In general, it makes sense to use a no-break space between
:
and the word that precedes it, so as not have a "dangling":
on a new line.Possibly, there is shared code that inserts the no-break space before
:
for text localized to French, so that it just happens to surface in this context too.
Pragmatically speaking:
The behavior is obscure with respect to finding windows running elevated sessions by title.
With respect to parsing such a title (once found), splitting into the part before and after the
:
actually then works the same in all languages, but only if you split by regular spaces only, such as with"Administrateur$([char] 0xA0): X:\windows\system32\cmd.exe" -split ' '
(by contrast,-split "Administrateur$([char] 0xA0): X:\windows\system32\cmd.exe"
would split by the no-break space too).
As for how to diagnose the problem programmatically:
(Get-Process -Name cmd | Where-Object MainWindowTitle -Match '^Administr').MainWindowTitle |
ForEach-Object ToCharArray |
ForEach-Object {
[pscustomobject] @{ Char = $_; CodePoint = '0x{0:x}' -f ([uint16] $_) }
}
The above prints each character alongside its Unicode code point on its own line.
This answer shows convenience function Debug-String
, which greatly simplifies examining strings for unexpected characters.