While working on an update to one of my projects, PoshPAIG, I decided that I wanted to take a look at using a DataGrid as a possible replacement to the use of a ListView. The problem I ran into right out of the gate was that I was unable to use the DataGrid in my WPF test script as it was only available with .Net 4.0.
Not looking so good, is it?
After some researching I came across this article from PowerShell MVP Thomas Lee written back in August 2010 showing how you can enable the .Net 4.0 access by creating a config file, 1 for the console and 1 for the ISE. After the file has been created, a restart of the console/ISE is necessary for PowerShell to read the config file and begin allowing use of the new .Net 4.0 framework.
This is great news! However, not one to just perform a manual update like that, I took up the initiative to write an advanced function that would not only perform the change on my local system, but also my remote systems as well, if needed. There is not a lot to it other than creating the Here-String listing the data for the config file and then adding some parameters for Computername, Console and ISE to let the user decide what they want to do. Also since this does make a change to the system, the use of –WhatIf is also enabled in the function.
You can see what version PowerShell is using for the .Net Framework by running the following command:
[environment]::Version
Currently, PowerShell is running under .Net 2.0.
Now we dot source my advanced function and run a command to enable .Net 4.0 access to PowerShell.
. .\Enable-DotNet4Access.ps1 Enable-DotNet4Access -Console -Verbose
Pretty simple, now lets restart the console and check the version being used now.
Yep, using .Net 4.0 now!
Now lets run that script again and see if it works any better…
And there you have it! I can now use a WPF DataGrid with PowerShell!
Download Script:
Source Code:
Function Enable-DotNet4Access { <# .SYNOPSIS Enables PowerShell access to the .NET 4.0 framework by creating a configuration file. .DESCRIPTION Enables PowerShell access to the .NET 4.0 framework by creating a configuration file. You will need to restart PowerShell in order for this to take effect. In a default installation of PowerShell V2, these files do not exist. .PARAMETER Computername Name of computer to enable .NET 4 for PowerShell against. .PARAMETER Console Apply configuration change for console only .PARAMETER ISE Apply configuration change to ISE only .NOTES Name: Enable-DotNet4Access Author: Boe Prox DateCreated: 10JAN2012 .LINK https://learn-powershell.net .EXAMPLE Enable-DotNet4Access -Console -ISE Description ----------- Enables .NET 4.0 access for PowerShell on console and ISE #> [cmdletbinding( SupportsShouldProcess = $True )] Param ( [parameter(Position='0',ValueFromPipeLine = $True,ValueFromPipelineByPropertyName=$True)] [Alias('__Server','Computer','Server','CN')] [string[]]$Computername, [parameter(Position='1')] [switch]$Console, [parameter(Position='2')] [switch]$ISE ) Begin { Write-Verbose ("Creating file data") $file = @' <?xml version="1.0"?> <configuration> <startup useLegacyV2RuntimeActivationPolicy="true"> <supportedRuntime version="v4.0.30319"/> <supportedRuntime version="v2.0.50727"/> </startup> </configuration> '@ } Process { If (-Not $PSBoundParameters['Computername']) { Write-Warning ("No computername given! Using {0} as computername." -f $Env:Computername) $Computername = $Env:Computername } ForEach ($Computer in $computername) { If ($PSBoundParameters['Console']) { If ($pscmdlet.ShouldProcess("Console","Enable .NET 4.0 Access")) { Try { $file | Out-file "\\$computer\C$\Windows\System32\WindowsPowerShell\v1.0\PowerShell.Exe.Config" -Force Write-Host ("{0}: Console must be restarted before changes will take effect!" -f $Computer) -fore Green -Back Black } Catch { Write-Warning ("{0}: {1}" -f $computer,$_.Exception.Message) } } } If ($PSBoundParameters['ISE']) { If ($pscmdlet.ShouldProcess("ISE","Enable .NET 4.0 Access")) { Try { $file | Out-file "\\$computer\C$\Windows\System32\WindowsPowerShell\v1.0\PowerShellISE.Exe.Config" -Force Write-Host ("{0}: ISE must be restarted before changes will take effect!" -f $Computer) -fore Green -Back Black } Catch { Write-Warning ("{0}: {1}" -f $computer,$_.Exception.Message) } } } } } }
I just ran across this article and it worked beautifully. I appreciate the effort on your part. Thank you.
That is a very good initiative and thanks for putting everything together.
I would like to make a small suggestion in your code.
I see that you are using below code to validate if a value is specified for the parameter or not.
If (-Not $PSBoundParameters[‘Computername’]) {
Write-Warning (“No computername given! Using {0} as computername.” -f $Env:Computername)
$Computername = $Env:Computername
}
Instead, you can do like below which gives you same functionality and saves some execution time.
Param (
[parameter(Position=’0′,ValueFromPipeLine = $True,ValueFromPipelineByPropertyName=$True)]
[Alias(‘__Server’,’Computer’,’Server’,’CN’)]
[ValidateNotNullOrEmpty()]
[string[]]$Computername = $env:ComputerName,
[parameter(Position=’1′)]
[switch]$Console,
[parameter(Position=’2′)]
[switch]$ISE
)
I just added [ValidateNotNullOrEmpty()] to $computername variable so that if the parameter value is left black it will throw error. I also assigned $env:computername to $computername so that when -ComputerName parameter is not specified it assumes the local computer. That is standard most people in PS world are using.
Hope this helps…
Sitaram Pamarthi
http://techibee.com
Nice catch Sitaram! Although the execution time would probably be minimal, it does save about 4 lines of unneeded code which is always a good thing and a good practice to get into. The [ValidateNotNullOrEmpty()] is also a nice touch as you say to prevent someone giving a null value!