Showing posts with label PowerShell tip. Show all posts
Showing posts with label PowerShell tip. Show all posts

Friday, September 11, 2015

PowerShell Tip - Manage .NET Assemblies in your session

The more I use PowerShell, the more I become a an automation fan!!!
PowerShell provides me the ability to automate almost everything I encounter in my daily work. Most of the time the cmdlets are available as part of the snapins, but sometimes you need to use the functionalities in a .NET assembly that should be loaded into the session and utilize the functionality provided by the classes in these assemblies. To properly manage the assemblies I’ve created a module, which you can also use for your work.

function Initialize-Assembly
{
       param
       (
              [Parameter(Mandatory=$true, Position=0, ParameterSetName="Single")]
              [ValidateNotNullOrEmpty()]
              [string] $Name,

              [Parameter(Mandatory=$true, Position=0, ParameterSetName="Array")]
              [ValidateNotNullOrEmpty()]
              [string[]] $Names

       )
      
       switch($PSCmdlet.ParameterSetName)
       {
              "Single"
              {
                     [void][System.Reflection.Assembly]::LoadWithPartialName($Name)
                     break
              }
              "Array"
              {
                     $Names |% { [void][System.Reflection.Assembly]::LoadWithPartialName($_) }
                     break
              }
       }
}

function Test-AssemblyLoaded
{
       param
       (
              [Parameter(Mandatory=$true, Position=0, ParameterSetName="Single")]
              [ValidateNotNullOrEmpty()]
              [string] $Name,

              [Parameter(Mandatory=$true, Position=0, ParameterSetName="Array")]
              [ValidateNotNullOrEmpty()]
              [string[]] $Names

       )

       switch($PSCmdlet.ParameterSetName)
       {
              "Single"
              {
                     (Get-AssemblyLoaded |? {$_ -match $Name}) -ne $null
                     break
              }
              "Array"
              {
                     $result = $true
                     $assemblies = Get-AssemblyLoaded
                     $Names |% {
                           $assembly = $_
                           if(($assemblies |? {$_ -match $assembly}) -eq $null)
                           {
                                  $result = $false
                           }
                     }

                     $result
                     break
              }
       }
}

function Get-AssemblyLoaded
{
       [System.AppDomain]::CurrentDomain.GetAssemblies()
}

Export-ModuleMember *Assembly*



PS E:\> Get-AssemblyLoaded | select fullname

FullName                                                                                                               
--------                                                                                                                
mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089                                            
powershell_ise, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35                                      
System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089                                
System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089                                              
System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a                                      
System.Management.Automation, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35                        
System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089                                         
Microsoft.PowerShell.ISECommon, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35                      
Microsoft.PowerShell.GPowerShell, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35                    








PS E:\> Initialize-Assembly -Name "Microsoft.TeamFoundation.Client"

PS E:\> Test-AssemblyLoaded  -Name "Microsoft.TeamFoundation.Client"
True

PS E:\> 



Thursday, September 10, 2015

Silent installation of Visual Studio using PowerShell DSC

Given that you have the setup created for silent installation of Visual Studio from a network Share or local drive location, you can use DSC to ensure that the Product is available or not available in your machine. To setup the Visual studio media follow the documentation here.

Once you have the media created you can use the DSC resource given below to install Visual Studio on your machine.

enum Ensure
{
       Absent
       Present
}

[DscResource()]
class xVisualStudio2015
{
       [DscProperty(Key)]
       [string] $ProductName

       [DscProperty(Mandatory)]
       [string] $ExecutablePath

       [DscProperty(Mandatory)]
       [string] $AdminDeploymentFile

       [DscProperty()]
       [string] $ProductKey

       [DscProperty(Mandatory)]
       [Ensure] $Ensure

       [DscProperty(NotConfigurable)]
       [bool] $IsValid


       [xVisualStudio2015] Get()
       {
              $vsPackage = $this.GetInstalledSoftwares() |? {$_.DisplayName -eq $this.ProductName}
              if(($this.Ensure -eq [Ensure]::Present) -and $vsPackage)
              {
                     $this.IsValid = $true
              }
              else
              {
                     $this.IsValid = $false
              }
              return $this
       }

       [void] Set()
       {
              if(-not (Test-Path $this.ExecutablePath))
              {
                     throw "Invalid path : $($this.ExecutablePath)"
              }
              if($this.Ensure -eq [Ensure]::Present)
              {
                     if(-not (Test-Path $this.AdminDeploymentFile))
                     {
                           throw "Invalid path : $($this.AdminDeploymentFile)"
                     }

                     $args = "/Quiet /NoRestart /AdminFile $this.AdminDeploymentFile /Log $Env:Temp\VisualStudio2015_Install.log"
                     if($this.ProductKey)
                     {
                           $args = $args + " /ProductKey $this.ProductKey"
                     }
                     "Installation arguments : $args" | Write-Debug

                     "Starting installation" | Write-Verbose

                     Start-Process -FilePath $this.ExecutablePath -ArgumentList $args -Wait -NoNewWindow      

                     "Successfully completed the installation" | Write-Verbose
              }
              else
              {
                     $args = "/Quiet /Force /Uninstall /Log $Env:Temp\VisualStudio2015_Uninstall.log"

                     "Uninstallation arguments : $args" | Write-Debug
                     "Starting uninstallation" | Write-Verbose

                     Start-Process -FilePath $this.ExecutablePath -ArgumentList $args -Wait -NoNewWindow      

                     "Successfully completed the uninstallation" | Write-Verbose
              }
       }

       [bool] Test()
       {
              $vsPackage = $this.GetInstalledSoftwares() |? {$_.DisplayName -eq $this.ProductName}
              if($this.Ensure -eq [Ensure]::Present)
              {
                     if($vsPackage)
                     {
                           return $true
                     }
                     else
                     {
                           return $false
                     }
              }
              else
              {
                     if($vsPackage)
                     {
                           return $false
                     }
                     else
                     {
                           return $true
                     }
              }
       }

       [PSObject[]] RetrievePackages($path, $registry)
       {
              $packages = @()
              $key = $registry.OpenSubKey($path)
              $subKeys = $key.GetSubKeyNames() |% {
                     $subKeyPath = $path + "\\" + $_
                     $packageKey = $registry.OpenSubKey($subKeyPath)
                     $package = New-Object PSObject
                     $package | Add-Member -MemberType NoteProperty -Name "DisplayName" -Value $($packageKey.GetValue("DisplayName"))
                     $package | Add-Member -MemberType NoteProperty -Name "DisplayVersion" -Value $($packageKey.GetValue("DisplayVersion"))
                     $package | Add-Member -MemberType NoteProperty -Name "UninstallString" -Value $($packageKey.GetValue("UninstallString"))
                     $package | Add-Member -MemberType NoteProperty -Name "Publisher" -Value $($packageKey.GetValue("Publisher"))           
                     $packages += $package     
              }
              return $packages
       }

       [PSCustomObject] GetInstalledSoftwares()
       {
              $installedSoftwares = @{}
              $path = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall"
              $registry32 = [microsoft.win32.registrykey]::OpenBaseKey([Microsoft.Win32.RegistryHive]::LocalMachine, [Microsoft.Win32.RegistryView]::Registry32)
              $registry64 = [microsoft.win32.registrykey]::OpenBaseKey([Microsoft.Win32.RegistryHive]::LocalMachine, [Microsoft.Win32.RegistryView]::Registry64)
       
              $packages = $this.RetrievePackages($path, $registry32)
              $packages += $this.RetrievePackages($path, $registry64)

              $packages.Where({$_.DisplayName}) |% {
                     if(-not($installedSoftwares.ContainsKey($_.DisplayName)))
                     {
                           $installedSoftwares.Add($_.DisplayName, $_)
                     }
              }
              return $installedSoftwares.Values
       }
}

Creating a configuration for the resource needs an Executable path, Product name and AdminDeploymentFile.xml.

Configuration VisualStudio2015Config
{
    Import-Dscresource -ModuleName xVisualStudio2015   
  
    xVisualStudio2015 VisualStudio2015
    {
        ExecutablePath = "C:\Softwares\VS2015\vs_enterprise.exe"
        ProductName = "Microsoft Visual Studio Enterprise 2015"
        AdminDeploymentFile = " C:\Softwares\VS2015\AdminDeployment.xml"
        Ensure = "Present"       
    }      
}

VisualStudio2015Config 

PS C:\PowerShell\DSC> Start-DscConfiguration -Path .\VisualStudio2015Config -Wait -Verbose -Force
VERBOSE: Perform operation 'Invoke CimMethod' with following parameters, ''methodName' = SendConfigurationApply,'className' = MSFT_DSCLocalConfigurationManager,'name
spaceName' = root/Microsoft/Windows/DesiredStateConfiguration'.
VERBOSE: An LCM method call arrived from computer VM2012-PRADEV with user sid S-1-5-21-1229272821-1801674531-839522115-133922.
VERBOSE: [VM2012-PRADEV]: LCM:  [ Start  Set      ]
VERBOSE: [VM2012-PRADEV]: LCM:  [ Start  Resource ]  [[xVisualStudio2015]VisualStudio2015]
VERBOSE: [VM2012-PRADEV]: LCM:  [ Start  Test     ]  [[xVisualStudio2015]VisualStudio2015]
VERBOSE: [VM2012-PRADEV]: LCM:  [ End    Test     ]  [[xVisualStudio2015]VisualStudio2015]  in 1.5860 seconds.
VERBOSE: [VM2012-PRADEV]: LCM:  [ Skip   Set      ]  [[xVisualStudio2015]VisualStudio2015]
VERBOSE: [VM2012-PRADEV]: LCM:  [ End    Resource ]  [[xVisualStudio2015]VisualStudio2015]
VERBOSE: [VM2012-PRADEV]: LCM:  [ End    Set      ]
VERBOSE: [VM2012-PRADEV]: LCM:  [ End    Set      ]    in  2.4780 seconds.
VERBOSE: Operation 'Invoke CimMethod' complete.
VERBOSE: Time taken for configuration job to complete is 2.626 seconds