How to download latest Git for Windows using cmd or powershell ? (or other built-in windows software)
Currently, i have a script to check if Windows is x32 or x64 :
# eq is equal
# ne is not equal
if ((gwmi win32_operatingsystem | select osarchitecture).osarchitecture -ne "64-bit")
{
#32 bit logic here
Write "32-bit OS"
Read-Host -Prompt "Press Enter to continue"
}
else
{
#64 bit logic here
Write "64-bit OS"
Read-Host -Prompt "Press Enter to continue."
}
Thanks in advance!
The easiest approach would be to use chocolatey on the target machine. After chocolatey is installed a simple:
choco install git
downloads and installs git for windows. Check the package site first, if the latest version has been packaged. It might sometimes take a couple of days after the release of a new version before that happens.
If you are looking for a manual way to download the latest release from github, you can use the github api.
First figure out the name of the asset, that you want to download. They are listed here : https://github.com/git-for-windows/git/releases/latest. The assets you are interested in look like this:
Git-2.25.1-64-bit.exe
Git-<version>-<architecture>.exe
Now get the page you were just looking at as a json object. The github api does that for you: https://api.github.com/repos/git-for-windows/git/releases/latest
Finally find your asset in there and pass the download link to Invoke-WebRequest.
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$architecture = '64-bit'
$assetName = "Git-*-$architecture.exe"
$gitHubApi = 'https://api.github.com/repos/git-for-windows/git/releases/latest'
$response = Invoke-WebRequest -Uri $gitHubApi -UseBasicParsing
$json = $response.Content | ConvertFrom-Json
$release = $json.assets | Where-Object Name -like $assetName
Invoke-WebRequest $release.browser_download_url -OutFile ".\$($release.name)"
Note: Depending on the scale on which you want to use this, you should know that the github api allows only 60 calls per hour, if you are an unauthenticated user: https://developer.github.com/v3/#rate-limiting
Related
I am writing a script in Power-shell that does basically the same thing that WSUS servers do,
Following the steps below:
WSUS server Downloads and installs the required patches on the client systems.
The PS script if patch is not successfully installed retries the installation on the client systems, by getting & executing the patch installation file (.cab,.msu,.exe) from the client systems.
The patches are selected by a independent process and send to a 3rd party location from where the PS script gets it.
The issue I am facing is the data in the 3rd party location for the patches contains UPDATE_ID as a patch identifier and I need a way to recognise whats is the UPDATE_ID for the existing patch installation file is.
NOTE: I can work through Hotfix_ID as the directory patches are stored in naming standards similar to "$Hotfix_ID". But single Hotfix_ID can have multiple patches.
The affected code is as follows:
param(
$KbFailed
)
foreach($KbNumber IN $KbFailed){
[array]$files_att=Get-ChildItem "C:\Windows\SoftwareDistribution\Download\*\*$KbNumber*"
Write-Host "Installing $KbNumber ..."
if ($null -eq $files_att){
Write-Error "Required file not found for $KbNumber"
}else{
foreach($file_att IN $files_att){
$file_extension=($file_att |Select-Object Extension).Extension
if ($file_extension -eq ".cab"){
dism.exe /online /add-package /PackagePath:$file_att /NoRestart
}
elseif($file_extension -eq ".exe"){
Start-Process "$file_att" -ArgumentList "/q" -Wait
}
elseif($file_extension -eq ".msu"){
Start-Process -FilePath "wusa.exe" -ArgumentList "$file_att /quiet /norestart" -Wait
}
else{
Write-Error "File type $file_extension not supported"
}
}
}
}
As mentioned I am managing it right now with HotFix_ID(Kb_number), but would like to replace it with UPDATE_ID
I am using the following code to uninstall google chrome software from my remote machines, But this script is executed with no output. And when i check the control panel, still the google chrome program exists. Can someone check this code?
foreach($computer in (Get-Content \path\to\the\file))
{
$temp1 = Get-WmiObject -Class Win32_Product -ComputerName $computer | where { $_.name -eq "Google Chrome"}
$temp1.Uninstall()
}
You shouldn't use the Win32_Product WMI class, one of the side effects of enumeration operations is it checks the integrity of each installed program and performs a repair installation if the integrity check fails.
It is safer to query the registry for this information instead, which also happens to contain the uninstall string for removing the product with msiexec. The uninstall string here will be formatted like MsiExec.exe /X{PRODUCT_CODE_GUID}, with PRODUCT_CODE_GUID replaced with the actual product code for that software.
Note: This approach will only work for products installed with an MSI installer (or setup executables which extract and install MSIs). For pure executable installers which make no use of MSI installation, you'll need to consult the product documentation for how to uninstall that software, and find another method (such as a well-known installation location) of identifying whether that software is installed or not.
Note 2: I'm not sure when this changed but ChromeSetup.exe no longer wraps an MSI as it used to. I have modified the code below to handle the removal of both the MSI-installed and EXE-installed versions of Chrome.
# We need to check both 32 and 64 bit registry paths
$regPaths =
"HKLM:\SOFTWARE\Wow6432node\Microsoft\Windows\CurrentVersion\Uninstall",
"HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"
# Since technically you could have 32 and 64 bit versions of the same
# software, force $uninstallStrings to be an array to cover that case
# if this is reused elsewhere. Chrome usually should only have one or the
# other, however.
$productCodes = #( $regPaths | Foreach-Object {
Get-ItemProperty "${_}\*" | Where-Object {
$_.DisplayName -eq 'Google Chrome'
}
} ).PSPath
# Run the uninstall string (formatted like
$productCodes | ForEach-Object {
$keyName = ( Get-ItemProperty $_ ).PSChildName
# GUID check (if the previous key was not a product code we'll need a different removal strategy)
if ( $keyName -match '^{[a-z0-9]{8}-([a-z0-9]{4}-){3}[a-z0-9]{12}}$' ) {
# Use Start-Process with -Wait to wait for PowerShell to finish
# /qn suppresses the prompts for automation
$p = Start-Process -Wait msiexec -ArgumentList "/l*v ""$($pwd.FullName)/chromeuninst.log"" /X${keyName} /qn" -PassThru
# 0 means success, but 1638 means uninstallation is pending a reboot to complete
# This should still be considered a successful execution
$acceptableExitCodes = 0, 1638
}
else {
Write-Host "Stopping all running instances of chrome.exe, if any are running"
Get-Process chrome.exe -EA Ignore | Stop-Process -Force
# The registry key still has an uninstall string
# But cannot be silently removed
# So we will have to get creating and control the uninstall window with PowerShell
# We need to use the undocumented --force-uninstall parameter, added to below command
$uninstallString = "$(( Get-ItemProperty $_).UninstallString )) --force-uninstall"
# Break up the string into the executable and arguments so we can wait on it properly with Start-Process
$firstQuoteIdx = $uninstallString.IndexOf('"')
$secondQuoteIdx = $uninstallString.IndexOf('"', $firstQuoteIdx + 1)
$setupExe = $uninstallString[$firstQuoteIdx..$secondQuoteIdx] -join ''
$setupArgs = $uninstallString[( $secondQuoteIdx + 1 )..$uninstallString.Length] -join ''
Write-Host "Uninstallation command: ${setupExe} ${setupArgs}"
$p = Start-Process -Wait -FilePath $setupExe -ArgumentList $setupArgs -PassThru
# My testing shows this exits on exit code 19 for success. However, this is undocumented
# behavior so you may need to tweak the list of acceptable exit codes or remove this check
# entirely.
#
$acceptableExitCodes = 0, 19
}
if ( $p.ExitCode -notin $acceptableExitCodes ) {
Write-Error "Program exited with $($p.ExitCode)"
$p.Dispose()
exit $p.ExitCode
}
exit 0
}
Incidentally, if you already know the MSI ProductCode of a given program you don't have to find the uninstall string this way. You can simply execute msiexec /X{PRODUCT_CODE_GUID}.
If you have further problems which aren't caused by the syntax of the above this would be an operational issue and would be better troubleshot over at the https://superuser.com site.
Edit
As discovered via our chat conversation, you are installing per user and with the 79.0.3945.130 version. You can remove per user Chrome with the following command if installed per user (if the version is different you will need the correct version path):
&"C:\Users\username\AppData\Local\Google\Chrome\Application\79.0.3945.130\Installer\setup.exe" --uninstall --channel=stable --verbose-logging --force-uninstall
In the future, it is not recommended to use ChromeSetup.exe or ChromeStandaloneSetup64.exe to install and manage Chrome in an enterprise environment, you should instead use the Enterprise MSI and install system-wide so you can manage Chrome more efficiently. This is the supported way to deploy Chrome in an enterprise environment, and the script I provided will work to uninstall Chrome via msiexec and searching the registry for the {PRODUCT_CODE} as provided.
Assuming it's an msi install and remote powershell is enabled:
invoke-command -computername comp001 { uninstall-package 'google chrome' }
For the programs provider (all users), it's something like:
get-package *chrome* | % { $_.metadata['uninstallstring'] }
"C:\Program Files\Google\Chrome\Application\95.0.4638.54\Installer\setup.exe" --uninstall --channel=stable --system-level --verbose-logging
And then run that uninstallstring, but you'd have to figure out the silent uninstall option (--force-uninstall). It also runs in the background.
This script asks the user if they want to install a program.
$program = Read-Host -Prompt 'Would you like to install program? Please type Yes or No'
It is then lead to an If statement below
if ( $program -eq 'Yes' )
{
start-process <exe file>
}
else
{
Write-Host "Install <application> was skipped"
}
This is asked for multiple applications when prompted to install. The problem I have is that after it askes, The installation of all the applications happen at once. Is there a way to use a loop to install the first application then move on to the next? I am new to PowerShell so I am trying to make this effective.
Set an array of links of apps that you want to install. You can use CSV
$import_CSV = Import-CSV "Path_to_file"
foreach($link in $import_CSV){ your code here }
This would be kind of easy way to get you going. start-process <$link> and you are good to go.
Windows: Assuming that PowerShell Core is not installed on Windows scenario.
Linux : Assuming that PowerShell Core was not installed by default and need to make a shell script to install it scenario.
MacOS : Assuming that Tried other method to download latest PS Core than Microsoft provided script, but failed. Removing the files, but found leftovers that must be removed by the script
How to download and install latest PowerShell Core of a specified channel (release , beta, rc)
for specified OS (-win- ; -osx ; -1.ubuntu-18.04-) with specified architecture (-amd64 ; -x86 ; -x64) using bash or powershell? (Without requiring manual config)
Here's the code :
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$location = Get-Location
$architecture = "x" + (Get-WmiObject Win32_Processor).AddressWidth
$assetName = "PowerShell-*-win-$architecture.msi"
$gitHubApi = 'https://api.github.com/repos/PowerShell/PowerShell/releases/latest'
$response = Invoke-WebRequest -Uri $gitHubApi -UseBasicParsing
$json = $response.Content | ConvertFrom-Json
$release = $json.assets | Where-Object Name -like $assetName
Invoke-WebRequest $release.browser_download_url -OutFile "$location\$($release.name)"
Start-Process msiexec.exe -Wait -ArgumentList '/A $($release.name) /I $location\$($release.name) /quiet /qb ADD_EXPLORER_CONTEXT_MENU_OPENPOWERSHELL=1 REGISTER_MANIFEST=1 ENABLE_PSREMOTING=1'
Write-Host Ok
So I currently have a Powershell script that installs various software silently
What I have at the moment are all of the commands which work perfectly:
Start-Process 'C:\Files\Install files\Firefox' -ArgumentList "/S" -Wait
Start-Process 'C:\Files\Install files\Office' -ArgumentList "/s" -Wait
Start-Process 'C:\Files\Install files\Zeb' -ArgumentList "/S" -Wait
What I now want to implement is 'checking if the installation is succeeded'.
I start the program by checking the install files:
Write-Host "Checking if install files are present..."
if(Test-Path 'C:\Files\Install files\')
{
Write-Host "Files located. Installation will begin"
Write-Host ""
} else
{
Write-Host "Files not located, please check the directory"
Write-Host ""
break
}
And since the code of above is working I thought that I could maybe to the same for installing my software? But using the software directory as a test-path function:
Write-Host "Installing Firefox"
Start-Process 'C:\Files\Install files\Firefox' -ArgumentList "/S" -Wait
if (Test-Path C:\Program Files(x86)\Firefox)
{
Write-Host "Firefox succesfully installed!"
}else
{
Write-Host "Error, FireFox hasn't been installed"
}
.... And continue like this for the other programs
I thought 'why not?' since all of the PC's are the same and I must admit that the code also works.
But how would someone would judge this method? And what are alternatives?
Thanks
Just a note, I think this is more a question for Server Fault or Super User.
There are some high end tools like Desired State Configuration that handle all this but it really depends on the environment. We build standalone servers in an offsite datacentre and it's so much more convenient and less setup to just have a script that installs and configures everything that can't be imaged. Sure it takes two hours to complete but it's unattended, and since the OS is installed from a template we guarantee they're all exactly the same.
Perhaps I wouldn't recommend this method if the hardware were drastically different or if not imaging the OS to run the script on, I used to have a batch file to deploy customer desktops (back in WinXP days) but eventually cut it down to just detect the model and install drivers because it was too much hassle to maintain. I would also not recommend this method if it will be maintained by more than one person, or if the person maintaining it will be maybe/definitely not long term staff.
Overall it's up to the company. DSC is certainly a more professional and complete approach and much more easily maintained by multiple people, so put it to them and if they won't devote resources for a deployment server and training then you don't have much choice either way.
I would recommend to have a look at something more professionell like "PowerShell App Deployment Toolkit". (http://psappdeploytoolkit.com/)
It will take some time for you to start, but it is not that complex.
It outputs logs and so on.