PowerShell script for software installation using chocolatey - powershell

enter code here
# Step 1) install Chocolatey when needed
if (-not (Test-Path -Path "$env:ProgramData\Chocolatey\choco.exe" -PathType Leaf)) {
# from https://chocolatey.org/install
Set-ExecutionPolicy Bypass -Scope Process -Force
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072
Invoke-Expression ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))
}
# Step 2) define the array of packages you are offering
$Packages = 'googlechrome','firefox','codeblocks','windbg','nasm',
'explorersuite','pestudio','vscode','sysinternals','python'
# Step 3) define the Show-Menu function
function Show-Menu {
Clear-Host
Write-Host "**********************************************"
Write-Host "LIST OF SOFTWARES"
# write the options using the array of packages
for ($i = 0; $i -lt $Packages.Count; $i++) {
# {0,2} means right align with spaces to max 2 characters
Write-Host ('{0,2}. {1}' -f ($i + 1), $Packages[$i])
}
Write-Host " q. Exit the script"
Write-Host "*************************************************"
Write-Host
}
# Step 4) enter an endless loop you only exit if the user enters 'q'
while ($true) {
Show-Menu
$UserInput = Read-Host "Enter the software number to be installed"
# test if the user wants to quit and if so, break the loop
if ($UserInput -eq 'q') { break }
# test if the user entered a number between 1 and the total number of packages (inclusive)
if ([int]::TryParse($UserInput,[ref]$null) -and 1..$Packages.Count -contains [int]$UserInput) {
# here you install the chosen package using the array index number (= user input number minus 1)
$packageIndex = [int]$UserInput - 1
Write-Host "Installing $($Packages[$packageIndex])"
choco install $Packages[$packageIndex] -y
}
else {
$availableOptions = 1..$Packages.Count -join ','
Write-Host "Error in selection, choose $availableOptions or q" -ForegroundColor Red
}
$null = Read-Host "Press Enter to continue"
}
Problem Statement:
I am writing power shell script using chocolatey for software downloading and installing automatically. My script will display a menu with the list of software's whenever users enter the number the corresponding software will download and install.
When i run the script the executable files are not showing in control panel and desktop icon is also not creating but i am getting the message in power-shell terminal that the software is installed but i am not able to see that application.
I need to put some conditions in my script they are:
If the software is already installed then the software should not be downloaded
When the software is installed it has to shown in control panel and desktop icon should be created.
If any upgrade is their like for googlechrome and firefox generally up gradation takes place then the script has to upgrade.
Please help me and edit my script if anything is wrong
Thanks in advance

Referencing this answer, check to see if the relevant software is installed by checking the following registry keys:
$InstalledSoftware = Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*
$InstalledSoftware += Get-ItemProperty HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*
If it's installed, you can either skip the installation altogether, or...
You can get the package managed under Chocolatey by "installing" the package anyways, but provide the -n (--skippowershell) parameter:
choco install -n packageName
This will download the package metadata but skip the actual PowerShell code (chocolateyInstall.ps1, which is embedded into all Chocolatey packages). This is the piece which runs MSIEXEC, an EXE installer, extracts zip archives for packages without a proper installer, etc. This has the benefit of allowing future updates to be manageable by Chocolatey without reinstalling the software which already exists.
Note: There may be some nuance surrounding specific packages you'll have to figure out, but for the majority of what is available as a Chocolatey package this approach will work.

Related

Checksum error in installing software using chocolatey

# Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass (Before running the script execute the command in terminal for admin rights)
# Step 1) install Chocolatey when needed
#if (-not (Test-Path -Path "$env:ProgramData\Chocolatey\choco.exe" -PathType Leaf))
#{
# from https://chocolatey.org/install
# Set-ExecutionPolicy Bypass -Scope Process -Force
# [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072
# Invoke-Expression ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))
#}
if (-not (Test-Path -Path "$env:ProgramData\Chocolatey\choco.exe" -PathType Leaf))
{
Set-ExecutionPolicy Bypass -Scope Process -Force;
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072;
iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))
}
# Step 2) define the array of packages you are offering
$Packages = 'googlechrome',
'firefox',
'codeblocks',
'windbg',
'nasm',
'explorersuite',
'pestudio',
'vscode',
'sysinternals',
'python',
'ccleaner',
'anaconda3',
'wireshark',
'sublimetext3',
'google earth',
'notepadplusplus',
'iTunes'
# Step 3) define the Show-Menu function
function Show-Menu
{
Clear-Host
Write-Host "**********************************************"
Write-Host "LIST OF SOFTWARES"
# write the options using the array of packages
for ($i = 0; $i -lt $Packages.Count; $i++)
{
# {0,10} means right align with spaces to max 2 characters
Write-Host ('{0,10}. {1}' -f ($i + 1), $Packages[$i])
}
Write-Host " q. Exit the script"
Write-Host "*************************************************"
Write-Host
}
# Step 4) enter an endless loop you only exit if the user enters 'q'
while ($true)
{
Show-Menu
$UserInput = Read-Host "Enter the software number to be installed"
# test if the user wants to quit and if so, break the loop
if ($UserInput -eq 'q') { break }
# test if the user entered a number between 1 and the total number of packages (inclusive)
if ([int]::TryParse($UserInput,[ref]$null) -and 1..$Packages.Count -contains [int]$UserInput)
{
# here you install the chosen package using the array index number (= user input number minus 1)
$packageIndex = [int]$UserInput - 1
Write-Host "Installing $($Packages[$packageIndex])"
choco install $Packages[$packageIndex] -y
}
else
{
$availableOptions = 1..$Packages.Count -join ','
Write-Host "Error in selection, choose $availableOptions or q" -ForegroundColor Red
}
$null = Read-Host "Press Enter to continue"
}
The script is working correct all softwares are getting installed properly, but when i try to install some softwares like nasm, pestudio i am getting checksum error,i.e the hash value of the downloaded file is not matching with the package maintainer hash value so i am getting checksum error. I came to know that the checksum error can be ignored. The syntax for ignoring the checksum is choco install SoftwareName --ignore-checksums
but where should i put this statement in my script can anyone put this statement in my script i tried to put but it is not reflecting. please can anyone edit my script.
Thanks in advance.
You've already answered your own question:
The syntax for ignoring the checksum is choco install SoftwareName --ignore-checksums
So add --ignore-checksums to get things working for now. The best long-term solution would be to either:
Search for the package on https://chocolatey.org and contact the package maintainers about the mismatched checksums, so they can push an update.
Maintain your own nuget feed and packages for the software you need. This is the most recommended approach in a business setting.
I would recommend the --checksum command line argument, way safer than --ignore-checksums
This requires a bit little extra work compared to just ignoring.
You have three options how to get the correct checksum, safest a), then b) then least safe is c)
a) go to the original source of download, (I mean, where the package
author also intend to download the installable) and if there is a
checksum information use that.
b) go to the original source of download, download yourself, then
check it with virustotal. This servers two purpose: you got a trust/no trust picture, and secondly, the hash what virustotal calculates is exactly what choco expects. So if you decide to trust in the downloaded stuff based on virustotal, then you can instantly use that virustotal hash in your --checksum command line argument.
c) use the checksum in the choco install error message

silent installation using powershell

I am trying to install software using powershell silent scripting. To install this software we need to have JRE installed on machine. For this first we need to check weather JRE installed or not, if not installed then it needs to be installed. What approach needs to be followed?
I have tried with the below of code.
$LASTEXITCODE = 0
$workdir = "C:\Program Files (x86)\Java"
If (!(Test-Path $workdir))
{
$LASTEXITCODE = (Start-Process "D:\jre-6u26-windows-i586.exe" -ArgumentList "/s" -Wait -PassThru).Exitcode
}
If($LASTEXITCODE -eq 0)
{
$DCBdir = "C:\Program Files (x86)\Compart"
If (!(Test-Path $DCBdir))
{
$Installer="D:\sw.exe"
$responsefile="D:\Sresponse.varfile"
$a=#("-q", "-varfile", "$responsefile")
start-process $Installer -ArgumentList $a -wait
}
}
$chkdir = "C:\Program Files (x86)\SWFolder"
if(Test-Path -eq $chkdir)
{
[System.Windows.MessageBox]::Show('Installation completed successfully')
}
When I run script its workingfine as it is checking the previous installation and performing installation if not found the installation. But here I am getting as issue with this code.
If Java installed alredy means it should start the other installation. but here in my case its stopping the complete installation.
after installation completed, I need to display the message like " Installation completed". But here its not working. AnNy wrong in the above code..??
One package manager that I like to use is Chocolatey which has an approved package for JRE, it looks like. A quick check wmi will tell you whether or not java is installed:
$x = Get-WmiObject -Class Win32_Product -Filter "Name like 'Java(TM)%'" | Select -Expand Version
You could also use Test-Path pointed at registry keys you know exist for the package. Once you verify that JRE is not on the machine, then you can call out to Chocolatey to install it.

PowerShell Script/Refresh

I have a script that installs software and logs what is happening. At the end of the install I use a command to check if the software is installed via the registry. Here is part of the script:
#Install Adobre Reader
Write-Verbose "$(Get-Date): Installing Adobe Reader"
$AdobeInstaller = "\\server\AcroRead.msi"
$AdobeArgs = 'TRANSFORMS="\\server\AcroRead.mst" /qn /norestart'
Start-Process $AdobeInstaller $AdobeArgs -Wait
#Check Adobe Reader Install
$InstalledProgs2 = Get-ItemProperty HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\* |
Select-Object DisplayName
$CheckProg2 = $InstalledProgs -like "*Adobe Acrobat Reader DC*"
if ( $CheckProg2 ) {
Write-Verbose "$(Get-Date): Adober Reader install finished successfully"
} else {
Write-Verbose "$(Get-Date): Adobe Reader install failed"
}
The script waits for the installer to finish, as it should, but then always reports as "Adobe Reader install failed" even though it is installed. If I run "check" part of the script after the initial script has finished it works as it should. It appears to me that PowerShell caches the current registry at the start of PowerShell and does not see the new install. Is there a command to refresh this or am I thinking incorrectly?

Speed up uninstallation with PowerShell

I use PowerShell script to uninstall software, remove services and delete installation folder. Full clean up. This software has core app and 11 addins. So I use this code for addins:
$appAddIns = #(Get-WmiObject -Class Win32_Product | Where-Object { $_.Name -match "SE0008*" })
foreach ($appAddIn in $appAddIns)
{
Write-Host "Uninstalling: " $appAddIn.Name
$appAddIn.Uninstall() | out-null
}
But it's terribly slow to even start the script. I run it, and it's just blank. My colleague at work didn't use my script because after 10 seconds he assumed that it doesn't work and terminated it.
Is there any way to write it better, or just add:
Write-Host "Sit and wait you impatient bastard"
at the beginning?
win32_product is slow ,you can utilize this registry path (HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall) to get the uninstallation command and run it
You could use Write-Progress and then update it with the name of the program you are uninstalling and a calculated percentage based on the number of programs being uninstalled.
Here is an example:
Write-Progress -Activity "Uninstalling programs..."
for ($i = 1; $i -le 5; $i++) {
Write-Progress -Activity "Uninstalling programs..." -Status "Program $i" -PercentComplete ($i / 5 * 100)
Start-Sleep -Seconds 1
}
Win32_product is broken and should not be used (even Microsoft wrote some articles about this broken WMI class). Besides it being very slow, it also causes problems with the current installed MSI packages since it forces a re-register on all registered MSI packages.
The easiest way to uninstall software is nowadays Powershell Desired State Configuration (note that you need at least Windows 8.1 for this). With DSC you can also change Service behaviour, remove files, install / uninstall MSI packages, run Powershell scripts etc.

Remove AppV package using Administrator credentials

I am trying to create a script that removes a certain AppV package. The problem I am having is the AppV package is installed under the local user which does not have admin access so I get this message:
"Permission denied"
However, when I run the script as administrator and give my credentials, the AppV package does not show up. Here is the section of code I am using to list and remove the package.
# Remove AppV version of inProcess
$allAppV = Get-AppvClientPackage
If ($allAppV.Count -ge 0) {
$i = 1
#This part lists the packages
Write-Host "List AppV packages"
ForEach($Package in $allAppV) {
Write-Host `t $i - $Package.Name
$i +=
1
}
# Select which package to remove
$NumbertoRemove = Read-Host
"Which one would you like to remove? Type 0 if none"
If ($NumbertoRemove -eq 0) {
Write-Host "Not removing any App-V Client Package"
$Global:More = $False
}
else {
If ($NumbertoRemove -le $allAppV.Count) {
$NumbertoRemove -= 1
Write-Host "Removing package" $allAppV[$NumbertoRemove].Name
$PackageToRemove = $allAppV[$NumbertoRemove]
If ($PackageToRemove.IsPublishedGlobally)
{Unpublish-AppvClientPackage $allAppV[$NumbertoRemove]}
# I need to provide admin credentials for this step
Remove-AppvClientPackage $allAppV[$NumbertoRemove]
Write-Host "AppV Client Package has been removed"
This is what it looks like when I run the script as the local user. If I enter 1 it will try to remover inProcess but gets permission denied error.
If I run as administrator it looks the same except it lists no packages. I imagine because the script is running as administrator so it is listing packages installed under the admin account which their are none.
I need to either run the script as administrator but list the Appv packages of the local user or provide credentials for the remove-AppvClientPackages step. It would be preferable to prompt for credentials to remove the package. Thanks
Use the Get-AppvClientPackage cmdlet with the -All switch, this will list all AppV packages on the computer regardless of the current user. You will still need to run the cmdlet with administrative credentials to uninstall the package.
$allAppV = Get-AppvClientPackage -All