Keeping a log of things I come across, discover or learn is a very recent idea, so I didn’t write anything down before. I’ll still try to get a list about what I remember from January.
miscellaneous
- Read Learn PowerShell Scripting in a Month of Lunches, in about four days (I was ripe). The best thing I read since their previous book. I started to rewrite scripts right away.
- Definitely made the switch to VSCode, thanks to the former.
- Started to read a lot about Pester, that one is more difficult, you’ve got to change your frame of mind, and it gets in the way of doing. But I’ll persevere, I see how important it is.
- Upgraded ITIL certification to ITIL2011
- You can forget the “Get-“ part of any Get-Smthing cmdlet.
- Execution Policy set by GPO cannot be overwritten. But the Authorization Manager is an object that can be manipulated as any object in Powershell.
- AD cmdlets have a quirk: their properties are not fixed. It obviously comes with the territory of the -Properties parameter, but it’s worse than that: when you try to access a property, it creates it, usually empty. So there’s no testing for a AD attribute existence by query the corresponding property: it always exists, as soon as you try to look for it. What’s that for an observer effect, he?
Quick Access links and default names
- Had a problem about QuickLinks shortcuts ending in $, in Citrix sessions (so resolution could not be deferred to second session, looking at you, Desktop.ini):
- Win32_MappedLogicalDisk has the drives
- Display names for mapped drives are at
HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\MountPoints2
- Two properties: _LabelFromDesktopINI & _LabelFromRegistry. The later wins.
- Works immediately (for newly opened windows).
- Quick Access items can be listed and accessed this way:
$QuickAccess = New-Object -ComObject shell.application
$QuickAccess.Namespace("shell:::{679f85cb-0220-4080-b29b-5540cc05aab6}").Items()
Self signed certificates for local development
- Needed self signed certificates for PowerShell development:
New-SelfSignedCertificate
- Move created cert to Cert:<user or machine>\Root to allow signing
- Copy (export/import) to Cert:<user or machine>\TrustedPublisher for no-nagging execution.
Getting current user info
$env:USERNAME
, but can be tempered with.[Environment]::UserName
, cannot be changed.[Security.Principal.WindowsIdentity]::GetCurrent()
is a secure as it gets. Includes short domain name, SID, isSystem (great for scripts)…- Good way to interrogate Active Directory from a station without the AD module: FindByIdentity() in the DirectoryServices.AccountManagement.UserPrincipal namespace.
- FindByIdentity() only provides default attributes. You can find the others thanks to the GetUnderLyingObject() member function.
- The user currently logged on the console can be found in the UserName property of the single Win32_ComputerSystem instance. Doesn’t work for RDP.
- Had to write a
New-ProtocolAgnosticCimSession
, our security still thinks it’s 2011. - To find logon time for the current user:
$Account = Get-CimInstance Win32_UserAccount -filter ...
$Account | Get-CimAssociatedInstance -ResultClassName Win32_LogonSession
It’s a pain in the arse because Win32_UserAccount gets all domain accounts and is awfully slow (but on my station, why?), though. But you can trick the system by creating the account with New-CimInstance -ClientOnly
. Needs Caption, User, Domain, and the later two as keys.
Keyboard information
That was a fun one: I needed to export all keyboard information for users. We have a hugely multilingual environment with custom keymaps. The info can be found by following this Rube Goldberg machine:
- The preload (list of keyboard/languages) is in
HKU:\Keyboard Layout\Preload
- The language ID is the last four bytes of the preload.
- Info about he language can be found with [Globalization.CultureInfo]::new(Language ID as hexa)
- If there is an value in
HKCU:Keyboard Layout\Substitute
whose name is the preload, it means than the keyboard is not the default one for the language. - The Keyboard layout ID is then either the one in Preload, or the one in substitute, if it exists.
- Each Keyboard Layout ID (should) have its own key in
HKLM:\SYSTEM\ControlSet001\Control\Keyboard Layouts
- The property Layout Text contains the English name of the layout.
- The property Layout Display Name points to the DLL containing the localized name.
- That last piece of info usually does not exist for non standard layouts.
- It is possible to extract those strings from DLLs in Powershell.