Using PowerShell Remoting with PIN-enabled Accounts

If you have set up a PIN to log into your computer, PowerShell remoting against your own machine may fail with a weird error message:

 
PS C:>  Invoke-Command { "Hello" } -ComputerName $env:computername 
[DESKTOP-7AAMJLF]  Connecting to remote server DESKTOP-7AAMJLF failed with the following error  message : WinRM cannot process the request. The following error with  errorcode 0x8009030e occurred while using Negotiate authentication: A specified logon session does not exist. It may already have been terminated. 
 Possible causes are:
  -The user name or password specified are  invalid.
  -Kerberos is used when no authentication  method and no user name are specified.
  -Kerberos accepts domain user names, but not  local user names.
  -The Service Principal Name (SPN) for the  remote computer name and port does not exist.
  -The client and remote computers are in  different domains and there is no trust between the two domains.
 After checking for the above issues, try the  following:
  -Check the Event Viewer for events related to  authentication.
  -Change the authentication method; add the  destination computer to the WinRM TrustedHosts configuration setting or use  HTTPS transport.
 Note that computers in the TrustedHosts list  might not be authenticated.
  -For more information about WinRM  configuration, run the following command: winrm help config. For more  information, see the 
about_Remote_Troubleshooting  Help topic.
    + CategoryInfo          : OpenError: (DESKTOP-7AAMJLF:String)  [], PSRemotingTransportException
    + FullyQualifiedErrorId :  1312,PSSessionStateBroken
 

To work around this, you have two choices:

  • Set up a user account with a password (needs local Administrator privileges). Then, use -Credential when you run Invoke-Command, and specify the account and password
  • If your computer is not domain-joined, and you enabled Negotiate authentication for PowerShell remoting, use the machine’s IP address instead of a computer name.

Twitter This Tip! ReTweet this Tip!

Separating Results by Property Value

If you use PowerShell remoting to receive information from remote machines, you can use fan-out simply by specifying more than one computer name. PowerShell will then automagically contact all machines simultaneously, which saves a lot of time (all of this requires that you have set up and enabled PowerShell on the affected machines, of course, which is not covered here).

The results come back in random order because all contacted machines return their information to you when they are ready.

To separate result data again per computer, use Group-Object:

$pc1 = $env:computername
$pc2 = '192.168.2.112'

$code = 
{
  Get-Service | Where-Object Status -eq Running
}

# get all results
$result = Invoke-Command -ScriptBlock $code -ComputerName $pc1, $pc2 

# separate per computer
$groups = $result | Group-Object -Property PSComputerName -AsHashTable 
$groups

# access per computer results separately
$groups.$pc1
$groups.$pc2

When you specify -AsHashTable, Group-Object creates a hash table and uses the computer name as key. This way, you can use the time-saving parallel processing and still consume results per computer.

Twitter This Tip! ReTweet this Tip!

Analyzing Result Frequencies (without Wasting Memory)

Use Group-Object to group objects based on shared property values, but don’t forget to use –NoElement parameter to discard the actual objects and return only the frequency.

Here is a simple line telling you what the file types are that you have in a given folder:

Get-ChildItem -Path c:Windows -File | Group-Object -Property Extension -NoElement

The result may look like this:

 
Count Name                     
----- ----                     
   11 .exe                     
    1 .dat                     
    9 .log                     
    4 .xml                     
    1 .txt     
...
 

By specifying -NoElement, you save considerable memory because the original objects are not included in the result.

Twitter This Tip! ReTweet this Tip!

Finding Unapproved Verbs

Cmdlets and functions should use only approved verbs to make it easier on user to find commands, and improve consistency.

Here is quick audit code that shows all commands not adhering to this rule:

$approved = Get-Verb | Select-Object -ExpandProperty Verb

Get-Command -CommandType Cmdlet, Function |
  Where-Object { $approved -notcontains $_.Verb }

Any cmdlet and function returned here uses non-approved or no verbs at all.

Twitter This Tip! ReTweet this Tip!

Most Popular Verbs

Let’s explore which command verbs are most popular in your PowerShell:

Get-Command -CommandType cmdlet, function | 
Group-Object -Property Verb | 
Sort-Object -Property Count -Descending

Here is the result on our system:

 
Count Name                      Group                                            
----- ----                      -----                                            
  456 Get                       {Get-AppBackgroundTask, Get-AppvVirtualProcess...
  210 Set                       {Set-AssignedAccess, Set-AutologgerConfig, Set...
  120 Remove                    {Remove-AutologgerConfig, Remove-BCDataCacheEx...
  102 New                       {New-AutologgerConfig, New-DAEntryPointTableIt...
   72 Enable                    {Enable-BCDistributed, Enable-BCDowngrading, E...
   70                           {A:, ABC, AfterAll, AfterAll...}                 
   67 Add                       {Add-BCDataCacheExtension, Add-BitLockerKeyPro...
   65 Disable                   {Disable-BC, Disable-BCDowngrading, Disable-BC...
   28 Start                     {Start-Animation, Start-AppBackgroundTask, Sta...
   26 Update                    {Update-Disk, Update-DscConfiguration, Update-...
   24 Clear                     {Clear-AssignedAccess, Clear-BCCache, Clear-Bi...
   22 Export                    {Export-Application, Export-BCCachePackage, Ex...
   22 Invoke                    {Invoke-AsWorkflow, Invoke-Background, Invoke-...
   20 Import                    {Import-BCCachePackage, Import-BCSecretKey, Im...
   19 Stop                      {Stop-DscConfiguration, Stop-Dtc, Stop-DtcTran...
   19 Rename                    {Rename-DAEntryPointTableItem, Rename-MaskingS...
   19 Test                      {Test-Ancestor, Test-Descendent, Test-Dtc, Tes...
   16 Register                  {Register-ClusteredScheduledTask, Register-Dns...
   15 ConvertTo                 {ConvertTo-DataTemplate, ConvertTo-GridLength,...
   14 Write                     {Write-DtcTransactionsTraceSession, Write-Prin...
   14 Show                      {Show-Clock, Show-Details, Show-NetFirewallRul...
   14 Reset                     {Reset-BC, Reset-DAClientExperienceConfigurati...
   13 Unregister                {Unregister-AppBackgroundTask, Unregister-Clus...
   11 Out                       {Out-GridViewVertical, Out-Notepad, Out-Voice,...
   11 Copy                      {Copy-DependencyProperty, Copy-NetFirewallRule...
    9 Send                      {Send-EtwTraceSession, Send-PSCONFConfirmation...
    9 Find                      {Find-Command, Find-DscResource, Find-Module, ...
    9 ConvertFrom               {ConvertFrom-SddlString, ConvertFrom-TypeToScr...
    7 Save                      {Save-Module, Save-NetGPO, Save-NetworkSwitchC...
    7 Repair                    {Repair-FileIntegrity, Repair-VirtualDisk, Rep...
    7 Debug                     {Debug-FileShare, Debug-MMAppPrelaunch, Debug-...
    7 Format                    {Format-Hex, Format-Volume, Format-Custom, For...
    6 Suspend                   {Suspend-BitLocker, Suspend-PrintJob, Suspend-...
    6 Install                   {Install-Dtc, Install-ISEPreviewShortcut, Inst...
    6 Publish                   {Publish-BCFileContent, Publish-BCWebContent, ...
    6 Resume                    {Resume-BitLocker, Resume-PrintJob, Resume-Bit...
    6 Move                      {Move-Control, Move-SmbWitnessClient, Move-App...
    5 Restore                   {Restore-DscConfiguration, Restore-NetworkSwit...
    5 Restart                   {Restart-NetAdapter, Restart-PcsvDevice, Resta...
    5 Select                    {Select-Date, Select-UIType, Select-Object, Se...
    5 Mount                     {Mount-DiskImage, Mount-AppvClientConnectionGr...
    4 Uninstall                 {Uninstall-Dtc, Uninstall-Module, Uninstall-Sc...
    4 Disconnect                {Disconnect-IscsiTarget, Disconnect-VirtualDis...
    4 Connect                   {Connect-IscsiTarget, Connect-VirtualDisk, Con...
    4 Receive                   {Receive-DtcDiagnosticTransaction, Receive-Job...
    4 Unblock                   {Unblock-FileShareAccess, Unblock-SmbShareAcce...
    4 Assert                    {Assert-MockCalled, Assert-MockCalled, Assert-...
    4 Wait                      {Wait-Debugger, Wait-Event, Wait-Job, Wait-Pro...
    3 Complete                  {Complete-BitsTransfer, Complete-DtcDiagnostic...
    3 Resize                    {Resize-Partition, Resize-StorageTier, Resize-...
    3 Optimize                  {Optimize-StoragePool, Optimize-Volume, Optimi...
    3 Initialize                {Initialize-Disk, Initialize-EventHandler, Ini...
    3 Expand                    {Expand-Archive, Expand-WindowsCustomDataImage...
    3 Dismount                  {Dismount-DiskImage, Dismount-AppxVolume, Dism...
    3 Close                     {Close-Control, Close-SmbOpenFile, Close-SmbSe...
    3 Convert                   {Convert-Alias, Convert-Path, Convert-String}    
    2 Use                       {Use-Transaction, Use-WindowsUnattend}           
    2 Undo                      {Undo-DtcDiagnosticTransaction, Undo-Transaction}
    2 Trace                     {Trace-Command, Trace-SteroidsOutput}            
    2 Split                     {Split-Path, Split-WindowsImage}                 
    2 Resolve                   {Resolve-DnsName, Resolve-Path}                  
    2 Measure                   {Measure-Command, Measure-Object}                
    2 Join                      {Join-DtcDiagnosticResourceManager, Join-Path}   
    2 Exit                      {Exit-PSHostProcess, Exit-PSSession}             
    2 Read                      {Read-PrinterNfcTag, Read-Host}                  
    2 Block                     {Block-FileShareAccess, Block-SmbShareAccess}    
    2 Enter                     {Enter-PSHostProcess, Enter-PSSession}           
    2 Revoke                    {Revoke-FileShareAccess, Revoke-SmbShareAccess}  
    2 Do                        {Do-Something, Do-SomethingWeird}                
    2 Sync                      {Sync-NetIPsecRule, Sync-AppvPublishingServer}   
    2 Edit                      {Edit-StringList, Edit-CIPolicyRule}             
    2 Hide                      {Hide-UIElement, Hide-VirtualDisk}               
    2 Grant                     {Grant-FileShareAccess, Grant-SmbShareAccess}    
    1 Unlock                    {Unlock-BitLocker}                               
    1 Unpublish                 {Unpublish-AppvClientPackage}                    
    1 Unprotect                 {Unprotect-CmsMessage}                           
    1 Open                      {Open-NetGPO}                                    
    1 Lock                      {Lock-BitLocker}                                 
    1 Tee                       {Tee-Object}                                     
    1 Switch                    {Switch-Certificate}                             
    1 Sort                      {Sort-Object}                                    
    1 Backup                    {Backup-BitLockerKeyProtector}                   
    1 Protect                   {Protect-CmsMessage}                             
    1 Compress                  {Compress-Archive}                               
    1 Pop                       {Pop-Location}                                   
    1 Merge                     {Merge-CIPolicy}                                 
    1 Encrypt                   {Encrypt-Text}                                   
    1 Limit                     {Limit-EventLog}                                 
    1 Group                     {Group-Object}                                   
    1 ForEach                   {ForEach-Object}                                 
    1 Confirm                   {Confirm-SecureBootUEFI}                         
    1 Decrypt                   {Decrypt-Text}                                   
    1 Compare                   {Compare-Object}                                 
    1 Checkpoint                {Checkpoint-Computer}                            
    1 Push                      {Push-Location}                                  
    1 Where                     {Where-Object}
 

What’s even more interesting, here are the top 6 PowerShell cmdlet verbs:

 
PS C:> Get-Command -CommandType cmdlet, function  | 
Group-Object -Property Verb | 
Sort-Object -Property Count -Descending |
Where-Object { $_.Name } |
Select-Object -First 6 -Property Count, Name

Count Name  
----- ----  
  456 Get   
  210 Set   
  120 Remove
  102 New   
   72 Enable
   67 Add
 

So these top six verbs account for just 6% of all verbs, but for more than 60% of all commands.

Twitter This Tip! ReTweet this Tip!

Safely Encrypting and Decrypting Text

When you encrypt secret information, the challenge is to find a good secret. One particular safe secret would be your Windows identity, paired with your computer’s identity. This can be used to encrypt sensitive personal information on a particular computer.

Here are two functions that illustrate how it’s done:

function Decrypt-Text
{
  
  param
  (
    [String]
    [Parameter(Mandatory,ValueFromPipeline)]
    $EncryptedText
  )
  process
  {
    $secureString = $EncryptedText | ConvertTo-SecureString
    $BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($secureString)
    [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)
  }
}

function Encrypt-Text
{
  
  param
  (
    [String]
    [Parameter(Mandatory,ValueFromPipeline)]
    $Text
  )
  process
  {
     $Text | 
       ConvertTo-SecureString -AsPlainText -Force | 
       ConvertFrom-SecureString
  }
}

'PowerShell Rocks' | Encrypt-Text 
'Hello, World!' | Encrypt-Text | Decrypt-Text

You can safely save the encrypted text to a file. Only you will be able to read in and decrypt that text again, and only if it is done on the computer used to encrypt the data.

Twitter This Tip! ReTweet this Tip!