Notice: Function _load_textdomain_just_in_time was called incorrectly. Translation loading for the twentyseventeen domain was triggered too early. This is usually an indicator for some code in the plugin or theme running too early. Translations should be loaded at the init action or later. Please see Debugging in WordPress for more information. (This message was added in version 6.7.0.) in /var/www/html/wp-includes/functions.php on line 6121
Uninstall – SCCMOG – Deployment Blog

SCCM PowerCLI Silent deployment script

A couple of months ago I was asked by a client to create a method of patching to automatically snap shot a VM before applying the monthly patches with SCCM.

This as I’m sure your thinking has to be done by Task Sequence with the use of SCCM. If you not then that is how I would suggest you do it. The issue was PowerCLI and how to deploy that silently to all servers to allow for the Task Sequence to harness the PowerShell commands locally on the box without using remote PowerShell. I came across a great blog here discussing the silent install and then decided to write a PowerShell wrapper to deploy the software silently and with the use of SCCM.

The following script can be run as an Application or Package that is purely up to you. There are 2 modes, Install and Uninstall. Add these deployment command lines to your application or program to silently install PowerCLI or just run them locally:

[code language=”text”]
Powershell.exe -Executionpolicy Bypass -File "Deploy_PowerCLI_Silent.ps1 -MODE Install"
Powershell.exe -Executionpolicy Bypass -File "Deploy_PowerCLI_Silent.ps1 -MODE Uninstall"
[/code]

You will probably notice that to uninstall it silently you need to remove “VMware Remote Console Plug-in 5.1” followed by the “VMware vSphere PowerCLI” software.
The script build the arguments to do so, but if you are using a different version you will have to change:

[code language=”powershell”]$RemConsole = $InstalledProducts | where { $_.ARPDisplayName -eq "VMware Remote Console Plug-in 5.1" }[/code]

name to match
Just change the “VMware Remote Console Plug-in 5.1” portion to the same text as seen in your “Programs and Features” (Appwiz.cpl).
Make sure the VMware-PowerCLI.exe is in the same folder as the script.
The Script:

#########################################################################################################
#Script Name:   Deploy VMware PowerCLI 6.3 Silently                                                     #
#Script Author: SCCMOG - Richie Schuster 16/12/2016 WWW.SCCMOG.COM                                      #
#########################################################################################################
#Script Usage: "Deploy_PowerCLI_Silent.ps1 -Mode Install" to install and "-Mode Uninstall" to uninstall.#
#########################################################################################################

#Install Mode Parameter
PARAM (
    [string]$MODE
)

#If entery is input run script
If ($mode -ne $null){
    
    #If Mode input is Install run install.
    If ($MODE -eq "Install"){
        #Install VMware PowerCLI 6.3 Silently and Remote Console silently
        Start-Process "$PSScriptRoot\VMware-PowerCLI-6.3.0-3737840.exe" -ArgumentList '/b"C:\Windows\Temp" /VADDLOCAL=ALL /S /V"/qn ALLUSERS=1 REBOOT=ReallySuppress' -wait -NoNewWindow
        }
    #If Mode input uninstall run uninstall
    ElseIf ($MODE -eq "Uninstall"){
        ##Get all Applications in SMS namespace
        $InstalledProducts = Get-WmiObject -Namespace 'root\cimv2\sms' -Class SMS_InstalledSoftware

        #Grab PowerCLI related
        $RemConsole = $InstalledProducts | where { $_.ARPDisplayName -eq "VMware Remote Console Plug-in 5.1" }
        $PowerCLI = $InstalledProducts | where { $_.ARPDisplayName -eq "VMware vSphere PowerCLI" }

        #Get store local msi for uninstall arguements
        $REMCLP = $RemConsole.LocalPackage
        $PCLILP = $PowerCLI.LocalPackage

        #Get process that must be killed to uninstall silently
        $Running = Get-Process -Name vmware-usbarbitrator64 -ErrorAction SilentlyContinue

            #Check if process is running
            If ($Running -ne $null){
                #Kill process if it is
                Stop-Process -Name vmware-usbarbitrator64 -Force
                #Start Removal of VMware Remote Console Plug-in 5.1
                Start-Process "msiexec.exe" -ArgumentList "/x $REMCLP /qn /L*v $env:windir\temp\Uninstall_VMwareREMConsolePlg5.1.log /norestart" -wait -NoNewWindow
                #Start Removal of VMware vSphere PowerCLI
                Start-Process "msiexec.exe" -ArgumentList "/x $PCLILP /qn /L*v $env:windir\temp\Uninstall_VMwarevSpherePowerCLI.log /norestart" -wait -NoNewWindow
            }
            Else{
                #Start Removal of VMware Remote Console Plug-in 5.1
                Start-Process "msiexec.exe" -ArgumentList "/x $REMCLP /qn /L*v $env:windir\temp\Uninstall_VMwareREMConsolePlg5.1.log /norestart" -wait -NoNewWindow
                #Start Removal of VMware vSphere PowerCLI
                Start-Process "msiexec.exe" -ArgumentList "/x $PCLILP /qn /L*v $env:windir\temp\Uninstall_VMwarevSpherePowerCLI.log /norestart" -wait -NoNewWindow
            }
    }
    #If mode input does not match inform user.
    Else{
        Write-host 'Incorrect Params please format this way: "Deploy_PowerCLI_Silent.ps1 -Mode Install" to install and "-Mode Uninstall" to uninstall.'
    }
}
#If params are not specified then inform.
Else{
    Write-host 'Script Params must be used : "Deploy_PowerCLI_Silent.ps1 -Mode Install" to install and "-Mode Uninstall" to uninstall.'
    }
#########################################################################################################

.Net 4 Downgrade PowerShell Script

Recently I re-captured a clients Windows 7 Gold image and published it out in there Production Windows 7 OSD Task Sequence. This was all fine for a month or 2 until a machine using the software “Information at Work” needed to be rebuilt by their Service Desk as there were issues.

The problem was that Information at Work required .Net 4.5.* and no other version. This it seems must have been coded into the installer and the application.  VERY frustrating…

So I had to create a script to downgrade it for Windows 7 Clients and here it is.

[code language=”powershell”]

#Commented due to PS version 5 only — $Release = Get-ItemPropertyValue -Name Release -Path "HKLM:\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full"

##Create Detection key function for ConfigMgr
$Unique = "InfoAtWork"
$DetectKey = "HKLM:\SOFTWARE\SOJ\SCRIPTS\$Unique"
function set-detectionKeys()
{
New-Item -Path HKLM:\SOFTWARE\ -Name SOJ –Force
New-Item -Path HKLM:\SOFTWARE\SOJ -Name SCRIPTS –Force
New-Item -Path HKLM:\SOFTWARE\SOJ\SCRIPTS -Name $Unique –Force

}

##Get .Net Version from Registry and hold it in variable $Release
$Key = ‘HKLM:\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full’

If (Test-Path $Key)
{

$Release = (Get-ItemProperty -Path $Key -Name Release).Release

##Check Release version is 4.5
if ($Release -eq 378389)

{
set-detectionKeys
Set-ItemProperty -Path $DetectKey -Name NetVersion -Value $Release -Force
Write-Host "Correct Version Found Exiting"
Exit 0
}
##If it is not 4.5 uninstall and reinstall 4.5

Else
{
##Get all applications installed
$InstalledProducts = Get-WmiObject -Namespace ‘root\cimv2\sms’ -Class SMS_InstalledSoftware
#Filter out .Net
$DotNet = $InstalledProducts | where { $_.ARPDisplayName -imatch ‘NET Framework 4’ }
#Get uninstall string
#$Uninstall = $DotNet.UninstallString
$CachedMSI = $DotNet.LocalPackage
#Uninstall Dot Net
$Passthru = Start-Process ‘msiexec.exe’ -ArgumentList "/x $CachedMSI /qb /L*v $env:windir\temp\DotNetRelease$Release.log /norestart" -Wait -NoNewWindow
$Exitcode = [string]$Passthru.ExitCode

if($Exitcode -eq 0 -Or 3010)
{
#Write successfuly removal to the registry
set-detectionKeys
Set-ItemProperty -Path $DetectKey -Name Removed -Value $Release -Force
#Install .Net 4.5.1
Start-Process "$PSScriptroot\SetupNet451.exe" -ArgumentList "/q /norestart /ChainingPackage ADMINDEPLOYMENT" -Wait -NoNewWindow
#Set Detection Keys
$ReleaseInst = (Get-ItemProperty -Path $Key -Name Release).Release
set-detectionKeys
Set-ItemProperty -Path $DetectKey -Name Installed451 -Value $ReleaseInst -Force
#Tell ConfigMgr to Reboot
Exit 3010
}
Else
{
set-detectionKeys
Set-ItemProperty -Path $DetectKey -Name FailedRemoval -Value "ExitCode: $Exitcode" -Force
Exit 9999

}
}

}
Else
{
#Write not found and install 4.5.1
#set-detectionKeys
#Set-ItemProperty -Path $DetectKey -Name DotNet4 -Value ‘NotFound Installing 451’ -Force
#Install .Net 4.5.1
Start-Process "$PSScriptroot\SetupNet451.exe" -ArgumentList "/q /norestart /ChainingPackage ADMINDEPLOYMENT" -Wait -NoNewWindow
#Set Detection Keys
$ReleaseInst = (Get-ItemProperty -Path $Key -Name Release).Release
set-detectionKeys
Set-ItemProperty -Path $DetectKey -Name Installed451 -Value $ReleaseInst -Force
#Tell ConfigMgr to Reboot
Exit 3010

}

[/code]

  • First I create the function to create the detection keys in the registry.
  • Then I test the version of the .Net client installed in the registry by using this version information chart from Microsoft.
  • If it matches, happy days if it doesn’t match… find the uninstall string, create it and remove it (if its not found at all.. then jump to line 74 and install a fresh copy).
  • Check exit code “0” being success and “3010” being reboot, else fail the script and write to registry.
  • Re-install .Net 4.5.1 from the directory of the script, set detection keys and then tell the ConfigMgr client to reboot the device gracefully.

This I deployed using a Task Sequence as the “Information at Work” Software is deployed in that way. Also note that this will only work on Windows 7, so you might want to set a requirement on your application or task sequence step for “All Windows 7” Only.

If you need help creating the command line to run this as an application or task sequence CMD line check out this post.

Mass Uninstall SCCM PowerShell Script by Publisher

Use SCCM or MDT to Uninstall all applications by a specific publisher or other unique ID using the SMS installed software class in WMI and PowerShell.

So that software….

If you have no idea what I’m talking about take a look at this post and it will come clear!

Unfortunately the Client had a huge variety of Versions of one specific piece of software, ranging from 4.1 to 4.3 with loads of revisions in the middle and it installed 3 products!

Usually to script a removal I can easily jump into the SMS software class and find all relevant entries to a specific software version and build the script from there.

Like this:

[code language=”powershell”]

##Get list of all products installed
$InstalledProducts = Get-WmiObject -Namespace ‘root\cimv2\sms’ -Class SMS_InstalledSoftware

## Check the matches
$InstalledProducts | where { $_.ARPDisplayName -imatch ‘eSigner’ }

## Add specific product to variable
$eSigner = $InstalledProducts | where { ($_.ARPDisplayName -eq ‘eSigner 4.2’) -and ($_.ProductVersion -eq ‘4.2.111’) }
[/code]

But this although a great way of doing it only allows me to remove specific versions that I know or the client  knows are out there. Using the bellow:

[code language=”powershell”]
##Get list of all products installed
$InstalledProducts = Get-WmiObject -Namespace ‘root\cimv2\sms’ -Class SMS_InstalledSoftware

## Add specific product to variable
$eSigner = $InstalledProducts | where { ($_.ARPDisplayName -eq ‘eSigner 4.2’) -and ($_.ProductVersion -eq ‘4.2.111’) }

## Check its the right product
$eSigner

## Grab tje local package to a variable for the uninstall process
$CachedMSI = $eSigner.LocalPackage

##Start the uninstall with the local package and verbose logging
Start-Process ‘msiexec.exe’ -ArgumentList "/x $CachedMSI /qn /norestart /L*v %windir%\temp\uninstall_eSigner42.log" -Wait -NoNewWindow
[/code]

I could have also created some queries/reports find all the specific versions but this would have taken serious time and as the software was critical for BAU, the site and clients requiring it are fresh, scripting was the only way!

Anyway the script…

  • It grabs all software listed in the ‘root\cimv2\SMS’ ‘SMS_InstalledSoftware’ class in WMI.
  • Then it selects out all the Software with a specific Publisher (this can be changed).
  • If there is none it will write the detection key to the registry and then quit with exit code 0.
  • If there is then it sets the detection keys in the registry.
  • Loops through each product of the application installed finding the name of the product and local MSI package.
  • Starts MSIexec.exe with the arguments of local package and logs to the %WINDIR%\temp\uninstall_$packagename.log for each product installed.
  • It also write the name of the product to the detection key and the exit code of that uninstall (use full for troubleshooting).
  • After this it exits with exit code 3010 telling the Config Mgr client that reboot is required.

[code language=”powershell”]
##Mass Uninstall the Application by unique ID – Publisher
### To Deploy use program string: powershell.exe -Executionpolicy Bypass -File MassUninstallMSI.ps1
### SCCM_OG 16/07/2016

##Enter unique Identifier – Remember to change line from Publisher if not using that as unique.
$Unique = "Gemalto"
$DetectKey = "HKLM:\SOFTWARE\RSDELL\SCRIPTS\MassRemMSI\$Unique"
function set-detectionKeys()
{
New-Item -Path HKLM:\SOFTWARE\ -Name RSDELL –Force
New-Item -Path HKLM:\SOFTWARE\RSDELL -Name SCRIPTS –Force
New-Item -Path HKLM:\SOFTWARE\RSDELL\SCRIPTS -Name MassRemMSI –Force
New-Item -Path HKLM:\SOFTWARE\RSDELL\SCRIPTS\MassRemMSI -Name $Unique –Force

}

##Get all Applications in SMS namespace
$InstalledProducts = Get-WmiObject -Namespace ‘root\cimv2\sms’ -Class SMS_InstalledSoftware

#Grab all of those applications with Publisher of….
$AppArray = $InstalledProducts | where { $_.Publisher -like $Unique }

If ($AppArray.Length -eq 0)
{
set-detectionKeys
Set-ItemProperty -Path $DetectKey -Name Array -Value ‘NoneFound’ -Force
Write-Host "No applcations Found Exiting with code 0"
Exit 0
}

Elseif ($AppArray.Length -gt 0)

{
set-detectionKeys
#Uninstall the applications found
for ($i=0; $i -lt $AppArray.Length; $i++)
{
"`$AppArray[$i]=" + $AppArray[$i].ARPDisplayName
"`$AppArray[$i]=" + $AppArray[$i].Localpackage
$packagename = $AppArray[$i].ARPDisplayName
$packagename = $packagename -replace ‘\s’,”
$log = "/l*v $env:windir\temp\uninstall_$packagename.log"
$arguments = "/x " + $AppArray[$i].Localpackage + " /qn /norestart $log"
$Passthru = Start-Process ‘msiexec.exe’ -ArgumentList $arguments -Wait -NoNewWindow -PassThru
$Exitcode = [string]$Passthru.ExitCode
Set-ItemProperty -Path $DetectKey -Name $packagename -Value "ExitCode: $ExitCode" -Force
}

Write-Host "Applcations Found and removed. Exiting with code 3010 for reboot."
Exit 3010
}
Else
{
set-detectionKeys
Set-ItemProperty -Path $DetectKey -Name Else -Value ‘NoneFound’ -Force
Write-Host "No applcations Found Exiting with code 0"
Exit 0
}

##The End 🙂
########################################################

[/code]

Copyright 2016 SCCMOG | All Rights Reserved