Archive

Posts Tagged ‘Profile’

PowerShell Default Parameter Values – Time to Tweak Your Profile Again!

January 18th, 2017 No comments

One of the great things about a PowerShell profile is you get to customize the environment. One nice feature to accomplish this is the ability to set default parameter values for cmdlets. A great write-up about this is available at About Parameters Default Values. You can see similar info by running get-help about_Parameters_Default_Values. I’m not going to go into great detail about the feature, as those two resources are more than sufficient. What I am going to list here are some great examples that I’ve come to love. They are all in my profile.

This first example if my favorite. When you use the Get-Help cmdlet, the resulting info is shown in a popup window. This is great as I can keep it open while I work on my code in the main console window.

$PsDefaultParameterValues.add("Get-Help:ShowWindow",$True)

If you’re an OCD type like me, you want output of commands to be formatted and everything to line up. This example defaults the Format-Table cmdlet to autosize its output.

$PsDefaultParameterValues.add("Format-Table:AutoSize",$True)

We can actually set this behavior for both Format-Wide and Format-Table at the same time (courtesy of TechNet):

$PSDefaultParameterValues.add("Format-[wt]*:Autosize",$True)

How about we capture the output of the last PowerShell command into a variable, such as $0 (courtesy of TechNet):

$PSDefaultParameterValues.add("Out-Default:OutVariable",“0”)

If you can’t tell by my other articles and scripts here, I spend a lot of time writing scripts to help in deployments, migrations, etc. When you’re getting or setting data in Active Directory, the last thing you want is for replication (intersite or intrasite) to be an issue. So, when possible, you specify a specific domain controller to send all of your commands together. This example comes from serverfault:

$PSDefaultParameterValues = @{"*-AD*:Server"='YOUR-CHOSEN-DC'}

Now that’s not completely perfect, as it would have a hard coded DC name. And just our luck, it will be migrated out of existence and then our stuff breaks. So, let’s set a default parameter value with the result of a PowerShell query. In this case, a DC in the same site for each of our Lync/Skype for Business cmdlets that support the Server parameter:

$PSDefaultParameterValues.add("*-Cs*:Server",(Get-ADDomainController -Discover -NextClosestSite))

Or maybe you want to specify the PDC emulator instead? (courtesy Tommy Maynard)

$PSDefaultParameterValues.Add("Get-ADPrincipalGroupMembership:Server",$((Get-ADDomain).PDCEmulator))

Or, we can use a variable. Let’s say we assign $DC to a DC in the same site, and then use that going forward:

$dc = Get-ADDomainController -Discover -NextClosestSite
$PSDefaultParameterValues.add("*-AD*:Server","$dc")
$PSDefaultParameterValues.add("*-Cs*:Server","$dc")

Now, how many times do you get the “Are you sure” prompt? Force the command instead of getting prompted!

$PSDefaultParameterValues['*:Force']= $true

Fellow MVP Boe Prox also has a great list of examples on his post Using $PSDefaultParameterValues in PowerShell. Check it out!

Now, you can list each of these, or any combination, in your profile, each on a separate line. Or, we can use an array to set all at one time:

$PSDefaultParameterValues=@{
'Format-Table:AutoSize'=$True;
'Get-Help:ShowWindow'=$True;
'Send-MailMessage:SmtpServer'=$smtpserver
}

Something to keep an eye on here. In previous examples, I was using the $PSDefaultParameterValues.add method which ADDS the value to the existing list. If you omit the “.add” and instead use “=” or “=@{}”, you are replacing all existing values with what you specify. Additionally, you can use the $PSDefaultParameterValues.remove method to remove specific parameter values and keep any remaining values. An example of removing a single default parameter value:

$PsDefaultParameterValues.remove("Get-Help:ShowWindow",$True)

Are all of these changes permanent? No. They are valid for the life of the PowerShell session. If you need to remove them mid-session, you can clear them using:

$PsDefaultParameterValues.clear()

Defining default parameter values can also be defined at various scopes, as well, including Global, Script, etc. See Get-Help about_Scope for more info.

I mentioned at the beginning that these are great in your profile. Well, they’re great in your scripts as well. They allow for global changes instead of going through a script and updating each call to a cmdlet. By all means, send me your favorites. We’ll build a big list!

Categories: PowerShell Tags: ,

One Liner: Enabling Mapped Drives in Elevated PowerShell Sessions

July 18th, 2016 No comments

If you’ve worked with mapped drives in PowerShell sessions, you know it’s problematic to access mapped drives from an elevated PowerShell session when UAC is configured to prompt to prompt for credentials. Microsoft released a TechNet KB article on this issue quite some time ago. The article shows different ways to address the problem, from using the Local Security Policy, mapping the drives again in the elevated prompt, and using the registry. We’ll focus on the registry here for several reasons. The first is that using the local security policy seems burdensome; mapping the drives again seems redundant, and potentially confusing if the original mappings change and the ones in your PowerShell session don’t; and thirdly, and most important, we’re talking PowerShell here!

The local security policy really just changes registry settings under HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System, so using PowerShell to set registry settings accomplishes the same thing. We can add new property, EnableLinkedConnections using the New-ItemProperty cmdlet, which also lets us set its value to 1. A value of 1 will enable the mapped drives in elevated session, while a value of 0, or completely removing the property, disables those mapped drives in an elevated session. So let’s implement this:

New-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" -Name EnableLinkedConnections -Value 1 -PropertyType "DWord"

Now, if you want to put this in your PowerShell profile, then it will get processed every time. The problem is that you’ll get a “The property already exists” exception error every time it runs after the first time. So, we just wrap it in an IF statement using Get-ItemProperty, checking to see if it exists first. If not, create the item property.

if (-not (Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" -Name EnableLinkedConnections)){
  New-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" -Name EnableLinkedConnections -Value 1 -PropertyType "DWord"
}

Why would we want to include this in our profile? Because when we get new machines, or reload an existing machine, we don’t want to have to go back and manually configure everything again. We can just manually run the profile script and have it configure everything for us.

Categories: PowerShell Tags: , ,

Easily Configuring Your PowerShell Profile on Multiple Machines

July 15th, 2016 No comments

Description

I mentioned in One Liner: Enable Windows Explorer Preview of PowerShell Files that I use the same PowerShell profile script on all of my machines, courtesy of OneDrive. I wanted to show a couple of lines that are at the top of my profile that make this even easier. When I reload a computer, or get a new one, I need to configure that machine to use the shared profile. This is super easy. The profile .ps1 file is just dot sourced. So the file resides in my OneDrive hierarchy. I merely wait for OneDrive to finish its initial sync, and then open an elevated PowerShell session and run the shared file. At the top of the file is the following code:

if (-not (Test-Path $profile)){
	New-Item -Path $profile -Type file -Force
	$MyName = $MyInvocation.MyCommand.Definition
	Add-Content -Path $profile -value ". `".\$MyName`""
}

For information on the various files that can be used for a PowerShell profile, see Windows PowerShell Profiles. Since, by default, no profile exists, the top line in the code above, which verifies that a profile does not exist, passes. The next line creates the empty file. The third line gets the path and name of script file running (the one in OneDrive), and the fourth line adds that path as a dot source to the newly created profile. So, when you look in the newly created profile file, It has a single line:

. "d:\OneDrive\PowerShell\profile\profile.ps1"

So, when PowerShell is opened, and the profile is evaluated, the dot sourced file is loaded. Easy peasy! And, since it’s in OneDrive, all of the hard work you put into your profile is safe and secure in the event of a computer problem. But more importantly, when working from a different machine, you still have the same experience.

Feel free to comment below, including ideas, suggestions, and code sample for things you’ve done, or would like to see.

Donations

I’ve never been one to really solicit donations for my work. My offerings are created because *I* need to solve a problem, and once I do, it makes sense to offer the results of my work to the public. I mean, let’s face it: I can’t be the only one with that particular issue, right? Quite often, to my surprise, I’m asked why I don’t have a “donate” button so people can donate a few bucks. I’ve never really put much thought into it. But those inquiries are coming more often now, so I’m yielding to them. If you’d like to donate, you can send a few bucks via PayPal at https://www.paypal.me/PatRichard. Money collected from that will go to the costs of my website (hosting and domain names), as well as to my home lab.

 

Categories: PowerShell Tags:

One Liner: Enable Windows Explorer preview of PowerShell Files

July 14th, 2016 No comments

I really like the Preview Pane in Windows Explorer. It saves me from having to open files in their default app. The problem is that PowerShell files are not visible in Windows Explorer by default. And if you’re like me, you probably often look for code snippets in your .ps1 files. That’s pretty easy to fix, however, with a single line entered in an elevated PowerShell session utilizing the Set-ItemProperty cmdlet:

Set-ItemProperty Registry::HKEY_CLASSES_ROOT\.ps1 -Name PerceivedType -Value text

What this does is tell Windows Explorer to treat .ps1 files as text.

What I’ve done is add that in my PowerShell profile. My PowerShell profile is stored on OneDrive, and every machine I have references that same profile file. So, no matter what machine I’m on, I get the same experience, including the preview of PowerShell files. However, you must run it in an elevated session. So in my profile, to prevent errors, I check to see if the session is elevated, and if it is, set the property. It’s easy with:

if ((New-Object Security.Principal.WindowsPrincipal $([Security.Principal.WindowsIdentity]::GetCurrent())).IsInRole([Security.Principal.WindowsBuiltinRole]::Administrator)) {
  Set-ItemProperty Registry::HKEY_CLASSES_ROOT\.ps1 -Name PerceivedType -Value text
}

Now some of you will quickly note that only .ps1 files are included in my example. But PowerShell can also include .psm1 and .psd1 files as well. Can we still accomplish handing all three extensions in a single line of code? Absolutely. We can use Get-Item with the Include parameter to retrieve info for all three extensions, and then pipe that to Set-ItemProperty. Here’s an example:

Get-Item Registry::HKEY_CLASSES_ROOT\* -Include .ps1,.psd1,.psm1 | Set-ItemProperty -Name PerceivedType -Value text

And of course we can wrap this with the previously mentioned elevated check:

if ((New-Object Security.Principal.WindowsPrincipal $([Security.Principal.WindowsIdentity]::GetCurrent())).IsInRole([Security.Principal.WindowsBuiltinRole]::Administrator)) {
  Get-Item Registry::HKEY_CLASSES_ROOT\* -Include .ps1,.psd1,.psm1 | Set-ItemProperty -Name PerceivedType -Value text
}

I’ll be writing about more things in my PowerShell profile in the coming weeks. I welcome comments and suggestions, including things you include in your profile to help your productivity.

Categories: PowerShell Tags: