Listing (and Checking) PowerShell Profiles

Profile scripts are PowerShell scripts that launch automatically once PowerShell starts. The path to the primary profile file can be found in $profile.

To get a list of potential profile script paths, try this:

#requires -Version 1
($profile | Get-Member -MemberType NoteProperty).Name | ForEach-Object { $profile.$_ }

To check which profiles are in use on your machine, check out this example:

#requires -Version 3
($profile | Get-Member -MemberType NoteProperty).Name | 
  ForEach-Object { 
      $path = $profile.$_
      New-Object PSObject -Property ([Ordered]@{Path=$Path; Exists=(Test-Path $Path) }) 

The output would look similar to this:

Path                                                                            Exists
----                                                                            ------
C:\Windows\System32\WindowsPowerShell\v1.0\profile.ps1                           False
C:\Windows\System32\WindowsPowerShell\v1.0\Microsoft.PowerShellISE_profile.ps1   False
C:\Users\user09\Documents\WindowsPowerShell\profile.ps1                           True
C:\Users\user09\Documents\WindowsPowerShell\Microsoft.PowerShellISE_profile.ps1   True


The interesting part in this example is how to programmatically access object properties. You can use Get-Member to find out the property names of an object. We’ll look at the hidden gems of this technology in one of the upcoming tips.

Twitter This Tip! ReTweet this Tip!

Wednesday, September 2, 2015
Posted by AsifSaif

Creating New Objects - Oneliner

Sometimes you may want to create your own objects to store multiple pieces of information. Here is a pretty dense oneliner that illustrates a quick way of creating new objects:

#requires -Version 3 

$Info = 'Test'
$SomeOtherInfo = 12

New-Object PSObject -Property ([Ordered]@{Location=$Info; Remark=$SomeOtherInfo })

When you run this, the result is a new object that contains the two pieces of information, and displays them in the properties Location and Remark. Simply rename the keys in the hash table to rename the object properties to your liking.

Location Remark
-------- ------
Test         12

Note that [Ordered] was added in PowerShell 3.0 and produces ordered hash tables. You can use the same code on PowerShell 2.0 when you omit [ordered]. Without it, the order of the properties in the new object will be random.

Twitter This Tip! ReTweet this Tip!

Tuesday, September 1, 2015
Posted by AsifSaif

Mapping Network Drives (Part 3)

If you migrated from VBScript to PowerShell, you may remember how VBScript mapped network drives. This option is still available in PowerShell.

$helper = New-Object -ComObject WScript.Network


Test-Path -Path O:\
explorer.exe O:\
Get-PSDrive -Name O

$helper.RemoveNetworkDrive('O:', $true, $true) 

If you want to log on with alternate credentials, try this overload instead:

$helper.MapNetworkDrive('O:','\\dc-01\somefolder',$true, 'training\user02', 'topSecret') 

Twitter This Tip! ReTweet this Tip!

Monday, August 31, 2015
Posted by AsifSaif

Mapping Network Drives (Part 2)

Beginning with PowerShell 3.0, you can use New-PSDrive to map network drives. They will be visible in File Explorer as well. Here is some sample code:

#requires -Version 3

New-PSDrive -Name N -PSProvider FileSystem -Root '\\dc-01\somefolder' -Persist 

Test-Path -Path N:\
explorer.exe N:\
Get-PSDrive -Name N

Remove-PSDrive -Name N -Force

If you’d like to provide logon credentials, add the –Credential parameter to New-PSDrive, and submit a username in the format domain\username. The password will be securely prompted.

Twitter This Tip! ReTweet this Tip!

Friday, August 28, 2015
Posted by AsifSaif

Mapping Network Drives (Part 1)

PowerShell supports console commands, so if you need to map a network drive, often the most reliable way is to use good old net.exe like this:

#requires -Version 1
net.exe use M: '\\dc-01\somefolder' /PERSISTENT:YES 

Test-Path -Path M:\

explorer.exe M:\

If you omit "/PERSISTENT:YES", the mapped drive will be temporary and not reconnected once you log off and on again.

Note that you get an error if drive M: is in use already. Replace M: with a star to automatically use the next available drive letter.

To submit logon credentials, use this approach instead:

net.exe use * '\\dc-01\somefolder' /PERSISTENT:YES /USER:training\user03 *

This would authenticate you as training\user03, use the next available drive letter, and interactively ask for the password. Note that this would work in a regular PowerShell console only. It cannot be used in the PowerShell ISE because the PowerShell ISE has no real console and thus cannot interactively ask for a password.

To submit a password, replace the star after the username with the password. This of course is not recommended as this would expose the password to anyone who can look at your code.

Twitter This Tip! ReTweet this Tip!

Thursday, August 27, 2015
Posted by AsifSaif

Executing with Timeout

Start-Process can start processes but does not support a timeout. If you wanted to kill a runaway process after a given timeout, you could use an approach like this:

#requires -Version 2

$maximumRuntimeSeconds = 3

$process = Start-Process -FilePath powershell.exe -ArgumentList '-Command Start-Sleep -Seconds 4' -PassThru

    $process | Wait-Process -Timeout $maximumRuntimeSeconds -ErrorAction Stop
    Write-Warning -Message 'Process successfully completed within timeout.'
    Write-Warning -Message 'Process exceeded timeout, will be killed now.'
    $process | Stop-Process -Force

Wait-Process is used to wait for the process. If it did not end within the specified timeout, Wait-Process raises an exception. Your error handler can then decide what do to.

In the example, the catch block would kill the process.

Note that the example process in this sample is a second PowerShell instance, basically executing a Start-Sleep command to simulate some long running task. If you change the Start-Sleep parameter to less than the number of seconds specified in $maximumRuntimeSeconds, then the process will complete within the timeout, and your script would not try and kill it.

Twitter This Tip! ReTweet this Tip!

Wednesday, August 26, 2015
Posted by AsifSaif

Executing Selected Code as Admin

If you need to run selected parts of your script with Administrator privileges, you could temporarily launch a second PowerShell with Administrator privileges, then run the privileged command in the temporary shell.

Here is a sample that stops the Windows Update service. When you run it as regular user, it automatically pops up the elevation dialog, then executes your code in the new admin shell:

#requires -Version 2

Start-Process -FilePath powershell.exe -Verb runas -ArgumentList 'Stop-Service -Name wuauserv' -WindowStyle Minimized

Twitter This Tip! ReTweet this Tip!

Tuesday, August 25, 2015
Posted by AsifSaif

Finding Drive Letters

Here is a simple function to find out the reserved drive letters:

#requires -Version 3

function Get-DriveLetter
    (Get-WmiObject -Class Win32_LogicalDisk).DeviceID

To list all drive letters in use, try this:

PS> Get-DriveLetter


To find out whether a given drive letter is reserved, you could use it like this:

PS> $letters = Get-DriveLetter

PS> $letters -contains 'c:'

PS> $letters -contains 'f:'


Twitter This Tip! ReTweet this Tip!

Monday, August 24, 2015
Posted by AsifSaif

Quickly Setting Multiple Environment Variables

To quickly (and permanently) set a bunch of environment variables, here is a nice approach:

$hashtable = @{
    Name = 'Weltner'
    ID = 12
    Ort = 'Hannover'
    Type = 'Notebook'
    ABC = 123

$hashtable.Keys | ForEach-Object {
    $Name = $_
    $Value = $hashtable.$Name
    [Environment]::SetEnvironmentVariable($Name, $Value, "User")


Simply define the variables in a hash table. The script will create one environment variable per key-value pair. Replace "User" by "Machine" to create machine-wide environment variables. This would require Administrator privileges, though.

With the very same approach, you can also delete environment variables. Simply assign an empty string to it inside the hash table.

Twitter This Tip! ReTweet this Tip!

Friday, August 21, 2015
Posted by AsifSaif

Quickly Finding Scripts

To quickly locate a PowerShell script anywhere in your MyDocuments folder, take a look at this Find-Script function:

#requires -Version 3
function Find-Script
    [Parameter(Mandatory = $true)]
    $Path = [Environment]::GetFolderPath('MyDocuments')

  Get-ChildItem -Path $Path  -Filter *.ps1 -Recurse -ErrorAction SilentlyContinue |
  Select-String -Pattern $SearchPhrase -List |
  Select-Object -Property Path, Line |
  Out-GridView -Title "All Scripts containing $SearchPhrase" -PassThru |
  ForEach-Object -Process {
    ise $_.Path

Run it like this:

Find-Script 'childitem' 

This would return a list of all PowerShell scripts in your user profile that contain the search word. When you select scripts in a grid view window and click OK, they are automatically opened in the PowerShell ISE.

To set a different search base, use the –Path parameter. This way, you can search your USB media or some network location just as easily.

Twitter This Tip! ReTweet this Tip!

Thursday, August 20, 2015
Posted by AsifSaif

Recent Certifications

Popular Post

Recent Tweets

(c) 2011 - Asif R. Saif. Powered by Blogger.

- Copyright © Asif Saif -