Test for File or Folder

Test-Path can check whether a file or folder exists. If you add -PathType and specify Leaf (for files) or Container (for folders), the result can be even more specific:

$path = 'c:windows'

Test-Path -Path $path
Test-Path -Path $path -PathType Leaf
Test-Path -Path $path -PathType Container

Twitter This Tip! ReTweet this Tip!

System Memory, Units, and Rounding

Sometimes, you’d like to use different units of measurements. The total system memory is reported in bytes, for example. Here are some examples how you can turn bytes into GB and still make the result look nice:

$memory = Get-WmiObject -Class Win32_ComputerSystem | 
  Select-Object -ExpandProperty TotalPhysicalMemory

$memoryGB = $memory/1GB

# raw result in bytes
$memoryGB

# rounding
[Int]$memoryGB
[Math]::Round($memoryGB)
[Math]::Round($memoryGB, 1)

# string formatting
'{0:n1} GB' -f $memoryGB

The result looks similar to this:

 
15.8744087219238
16
16
15.9
15.9 GB
 

Twitter This Tip! ReTweet this Tip!

Creating Time Spans

You can use New-TimeSpan to define “amounts” of time, and then add or subtract them from dates. Here is an example:

$1Day = New-TimeSpan -Days 1
$today = Get-Date
$yesterday = $today - $1Day

$yesterday

A much easier way uses the built-in methods for DateTime objects:

$today = Get-Date
$yesterday = $today.AddDays(-1)

$yesterday

Also, you can use the TimeSpan .NET type to create time span objects:

 
PS C:> [Timespan]::FromDays(1)


Days              : 1
Hours             : 0
Minutes           : 0
Seconds           : 0
Milliseconds      : 0
Ticks             : 864000000000
TotalDays         : 1
TotalHours        : 24
TotalMinutes      : 1440
TotalSeconds      : 86400
TotalMilliseconds : 86400000
 

Twitter This Tip! ReTweet this Tip!

Waiting for Processes to Exit

Sometimes, a PowerShell script needs to wait for external processes to finish. Here is what some users do:

$processNameToWaitForExit = 'notepad'
do
{
    Start-Sleep -Seconds 1
} while (Get-Process -Name $processNameToWaitForExit -ErrorAction SilentlyContinue)

This approach is not ideal though because it waits at least for one second, even if the process is no longer running. Here is a better way:

$processNameToWaitForExit = 'notepad'
Wait-Process -Name $processNameToWaitForExit -ErrorAction SilentlyContinue

Not only is the code shorter. Wait-Process also supports a timeout that you can use to cancel the wait if it takes too long.

Twitter This Tip! ReTweet this Tip!

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!