Checksum error in installing software using chocolatey - hash

# 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

Related

How do I add a powershell script to be run post setup during a windows 10 unattended install?

I may be going about this the wrong/more difficult way. I am open to suggestions.
I am running NTLite v2.3.8.8920 [HOME] ((c) NTlitesoft d.o.o) to create unattended Windows 10 discs. After years of doing unattended discs and realizing the ever expanding size of the disc, (Latest disc was 32.73GB!), I found WinGet, the absolutely amazing repository, and have even gone as far as to create my own installer!
The issue for today is: how do I access WinGet during an unattended installation? I have compiled a list of applications that I use frequently; most that I have been hard coding to the disc and thus this incredible size; and I would love to be able to run this script post-setup and save the time and space. Here is my code:
#The first batch here is a function I created for notification purposes. Not sure how to do timed popups in Powershell yet.
#Get Words
function GW($myinput){
$WS = New-Object -ComObject "Wscript.Shell"
$ws.popup($myinput,3,'TK Installer',64)|SET-CLIPBOARD}
SET-CLIPBOARD to offload the popup response code. Need to find a better output or a way to prevent printing this response.
function install-myapps(){
Clear-Host
#Variable to hold the application list
$myapps = (
'Microsoft.PowerShell',
'Microsoft-Windows.Terminal',
'Microsoft.DotNet.SDK.3_1',
'Microsoft.DotNet.SDK.5',
'Microsoft.DotNet.SDK.6',
'Microsoft.MSIXCore',
'Microsoft.msmpisdk',
'Microsoft.ADKPEAddon',
'Microsoft.WebDeploy',
'9N5LW3JBCXKF',
'Nlitesoft.NTLite',
'Libretro.RetroArch',
'Notepad++.Notepad++',
'CodecGuide.K-LiteCodecPack.Full',
'Foxit.FoxitReader',
'7zip.7zip',
'OBSProject.OBSStudio',
'XnSoft.XnConvert',
'XnView.Classic',
'XnSoft.XnViewMP',
'corel.winzip',
'XP8K0J757HHRDW')
#Parser
ForEach-Object($aa in $myapps.Split(',')){
#Notification
GW "Installing $aa`nPlease wait..."
#Installer
WinGet install $aa --silent --accept-package-agreements --accept-source-agreements --force}
}
This code works perfectly in both command line and exe format; the latter using PS2EXE or IExpress. I just cannot figure out how to instantiate it post-setup from the unattended Win1021H2 side. Any help or insight would be greatly appreciated!
I was unable to figure out the process for this so I worked it around differently.
Below is how I fixed this situation:
# The first section opens and names function and
# declares variable $Hopeful applied to the full URI for the application we are installing
# !Considering using get-input but for now we will just use a replaceable variable!
# The second section begins the downloading and saving process
# Begins by separating the application from the URI assuming the format is as www.domain.com/application.exe
# Note now that the variable $JustApp will pull the just the last portion of the URI which is the application name
# Also, we'll make sure that what we're trying to do is possible by checking the extension of the last object
# Because wget needs 2 things; the URI and a place for the download to go; I am creating a directory to put these
# downloads in. Thus, $MyDir\$JustApp is now the default file point.
cls
Clear-Host
$MyDir = "d:\TKDI\"
# Create directory
if($mydir|Test-Path){
"My Directory Already Exists!"
}else{
md $MyDir -Force
}
# Section 1
Function TKDI($Hopeful,$MyArgs){
$_|select
# Section 2
$JustApp = $hopeful -split('/')|select -last 1
if($justapp -match "exe")
{
switch($MyArgs)
{
inno{$x ='/sp- /silent /forcecloseapplications /restartapplications /norestart'}
S{$x ='/S'}
silent{$x ='/silent'}
quiet{$x ='/quiet'}
passive{$x ='-passive'}
default{$x =$myargs}
un{$x ='-uninstall'}
$null{$x='/?'}
}
cls
echo "Processing $justapp"
if(Test-Path $mydir$justapp -PathType Leaf){echo 'File Downloaded Already!'}else{wget -Uri $hopeful -OutFile $MyDir$justapp}
$noteit = 'Installing $justapp in 5 seconds...'
$x=6;while($x-- -ge 1){cls;Write-host $x;sleep 1}
start -verb runas -wait -FilePath $mydir$justapp -ArgumentList $x
}elseif($justapp -match "msi")
{
cls
echo "You're file will be downloaded and installed!"
wget -Uri $hopeful -OutFile $MyDir$justapp
start -wait -Verb runas msiexec.exe -ArgumentList "-i $mydir$justapp /passive /norestart"
}else{
echo "This URI does not result in an application!"
}
}
tkdi www.example.com/index.exe inno #Installs beautifully```

PowerShell script for software installation using chocolatey

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.

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.

Using -Confirm in Powershell

I am trying to understand what the relationship between the $? and $lastexitcode variables versus the -Confirm flag in Powershell cmdlets.
Say for example you run a command with -confirm it will prompt you accordingly for action:
PS C:\temp> rm .\foo.txt -confirm
Confirm
Are you sure you want to perform this action?
Performing the operation "Remove Directory" on target "C:\temp\foo.txt".
[Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help
(default is "Y"):n
PS C:\temp> $?
True
I understand that technically the command ran successfully, but if the user chose no then the command did not run.
My question is how to I obtain the user's answer to the -Confirm flag?
$?, $LastExitCode, and -Confirm are completely unrelated to each other.
$? is an automatic variable with a boolean value indicating whether or not the last (PowerShell) operation was executed successfully.
$LastExitCode is an automatic variable with the exit code of the external command that was last executed (an integer value).
-Confirm is a common parameter controlling whether or not a cmdlet prompts the user for confirmation of its action.
To my knowledge PowerShell does not store the answer given to a -Confirm prompt anywhere, so if you need that response for something else you'll have to prompt the user yourself, e.g. like this:
function Read-Confirmation {
Param(
[Parameter(Mandatory=$false)]
[string]$Prompt,
[Parameter(Mandatory=$false)]
[string]$Message
)
$choices = New-Object Collections.ObjectModel.Collection[Management.Automation.Host.ChoiceDescription]
$choices.Add((New-Object Management.Automation.Host.ChoiceDescription -ArgumentList '&Yes'))
$choices.Add((New-Object Management.Automation.Host.ChoiceDescription -ArgumentList '&No'))
-not [bool]$Host.UI.PromptForChoice($Message, $Prompt, $choices, 1)
}
$doRemove = if ($PSBoundParameters['Confirm'].IsPresent) {
Read-Confirmation -Prompt 'Really delete'
} else {
$true
}
if ($doRemove) {
Remove-Item .\foo.txt -Force
}
AFAIK, it is not possible to capture the user's response to the confirmation prompt; it is not a part of PowerShell's command history, and while you might be able to get the information from the buffer somehow that would only be supported in the default PowerShell host as other hosts will use different buffers. In this case it is probably best to either do a separate confirmation within your script using an if statement.
$userAnswer = Read-Host "Are you sure you wish to proceed?"
if($userAnswer -eq "yes"){
rm .\foo.txt
}
Then just use the $userAnswer variable to know what your user responded with. Alternatively you could determine their answer by checking to see if the operation was completed. This would be my preferred method as this way you are SURE that the file has been deleted rather than assuming so because the cmdlet successfully executed and the user confirmed (the reliability is probably not any different here considering that remove-item is incredibly well tested but it could make a difference if you are using a third-party library of some kind) that would look something like the below.
rm .\foo.txt -Confirm
if(Test-Path .\foo.txt){
$success = $false
} else {
$success = $true
}
and if you really need to know whether it failed to delete due to an error or the user saying no you could do something like
rm .\foo.txt -Confirm
if(Test-Path .\foo.txt){
$success = $false
} else {
$success = $true
}
if(!($success) -and (!($?))){
$status = "Previous command failed"
} elseif (!($success) -and $?){
$status = "User cancelled operation"
}
Hope that helps.

Powershell: Brute-forcing password-protected .zip file (speeding up the process)

First-time questioner, so here's hoping I'm doing it right. :)
A co-worker and I have been playing around with Powershell, getting the lay of the land and see what you can do with it. Using info we found online (mostly here), we've managed to whip together a script to brute-force a password-protected .zip file using a .txt containing a list of passwords:
# Stopwatch for measurement
$stopWatch = [System.Diagnostics.Stopwatch]::startNew()
$7zipExec = """-7z.exe (7zip) location-"""
$input = """-.zip location-"""
$output = """-where to drop contents of .zip file-"""
$passwordfile = "-location of .txt file containing passwords-"
$windowStyle = "Hidden"
[long] $counter = 0
# Correct password is 12341234
foreach ($password in (get-content $passwordfile)) {
$counter++
Write-Host -NoNewLine "Attempt #($counter): $password"
$arguments = "x -o$output -p$password -aoa $input"
$p = Start-Process $7zipExec -ArgumentList $arguments -Wait -PassThru -WindowStyle $windowStyle
if ($p.ExitCode -eq 0) {
# Password OK
Write-Host " ...OK!"
Write-Host ""
Write-Host "Password is $password, found it after $counter tries."
break
}
elseif ($p.ExitCode -eq 2) {
# Wrong password
Write-Host " ...wrong"
}
else {
# Unknown
Write-Host " ...ERROR"
}
}
# Halt the stopwatch and display the time spent for this process
$stopWatch.Stop()
Write-Host
Write-Host "Done in $($stopWatch.Elapsed.Hours) hour(s), $($stopWatch.Elapsed.Minutes) minute(s) and $($stopWatch.Elapsed.Seconds) seconds(s)"
Read-Host -Prompt "Press Enter to exit"
It actually works! Probably not as clean as it could be, but we've managed to reach our goal to make a functioning script.
However! It takes about 1 second for each password try, and if you have a file with, say, the 10,000 most common passwords...that could take a while.
So now we're trying to figure out how to speed up the process, but we've hit a wall and need help. I'm not asking for someone to get 'er done, but I would really appreciate some tips/tricks/hints for someone who has only recently started getting into Powershell (and loving it so far!).
Took a while to get back to this, real life and all that, but while I did not manage to speed up the script, I did manage to speed up the process.
What I do now is run 4 instances of the script simultaneously (using an extra PS script to start them, which itself can be started with a batch file).
All of them have their own lists of passwords, and their own output directory (I found that when they use the same location, the file extracted by the script that found the password becomes unusable).
This way, it takes about 7-8 hours to attempt 100,000 of the most commonly used passwords! While I'm sure there are quicker scripts/programs out there, I'm pretty happy with the result.
Thanks all for the input!