https://gitforwindows.org/ has an option to put bash into PowerShell. I need that so no installing WSL and etc. I need to install git unattended, that is, with command line only. Existing tutorials like this only launch the installer using PowerShell, but I have to use the mouse to install stuff.
So, how can I install git, with bash on PowerShell, using PowerShell?
UPDATE:
I tried
Write-Host "Installing Git for windows..." -ForegroundColor Cyan
$exePath = "$env:TEMP\git.msi"
Write-Host "Downloading..."
(New-Object Net.WebClient).DownloadFile('https://github.com/git-for-windows/git/releases/download/v2.37.1.windows.1/Git-2.37.1-64-bit.exe', $exePath)
Write-Host "Installing..."
Start-Process msiexec.exe -Wait -ArgumentList '$exePath /NORESTART /NOCANCEL /SP- /CLOSEAPPLICATIONS /RESTARTAPPLICATIONS /COMPONENTS="icons,ext\reg\shellhere,assoc,assoc_sh" /LOG="C:git-for-windows.log"'
git --version
bash
but it gets stuck on "Installing..." and does not print any other outputs.
There are two problems:
Git for Windows does not get released as an MSI package. And you cannot convert a regular executable into an MSI package just by renaming it. You do not need msiexec.exe at all. The installer itself has already paramaters to perform a silent installation. Just execute it as is:
$exePath = "$env:TEMP\git.exe"
Start-Process $exePath -Wait -ArgumentList '/NORESTART /NOCANCEL /SP- /CLOSEAPPLICATIONS /RESTARTAPPLICATIONS /COMPONENTS="icons,ext\reg\shellhere,assoc,assoc_sh" /LOG="C:\git-for-windows.log"'
But: This will sill launch a GUI. So you have to add more parameters to make the installation really silent. Further reading:
Git: Silent or Unattended Installation
Git For Windows Silent Install Silent Arguments
TL;DR: Also add /VERYSILENT and you might want to use /LOADINF to customize some settings.
After the successful installation, you will face the same problem, you already did in your similar question, I just answered. TL;DR:
The environment variables in your current Process scope are not updated automatically. Update them manually by:
foreach($level in "Machine","User") {
[Environment]::GetEnvironmentVariables($level).GetEnumerator() | % {
# For Path variables, append the new values, if they're not already in there
if($_.Name -match 'Path$') {
$_.Value = ($((Get-Content "Env:$($_.Name)") + ";$($_.Value)") -split ';' | Select -unique) -join ';'
}
$_
} | Set-Content -Path { "Env:$($_.Name)" }
}
This code is taken from this answer.
After that, git --version and Get-Command git will work.
Full script:
$exePath = "$env:TEMP\git.exe"
# Download git installer
Invoke-WebRequest -Uri https://github.com/git-for-windows/git/releases/download/v2.37.1.windows.1/Git-2.37.1-64-bit.exe -UseBasicParsing -OutFile $exePath
# Execute git installer
Start-Process $exePath -ArgumentList '/VERYSILENT /NORESTART /NOCANCEL /SP- /CLOSEAPPLICATIONS /RESTARTAPPLICATIONS /COMPONENTS="icons,ext\reg\shellhere,assoc,assoc_sh"' -Wait
# Optional: For bash.exe, add 'C:\Program Files\Git\bin' to PATH
[Environment]::SetEnvironmentVariable('Path', "$([Environment]::GetEnvironmentVariable('Path', 'Machine'));C:\Program Files\Git\bin", 'Machine')
# Make new environment variables available in the current PowerShell session:
foreach($level in "Machine","User") {
[Environment]::GetEnvironmentVariables($level).GetEnumerator() | % {
# For Path variables, append the new values, if they're not already in there
if($_.Name -match 'Path$') {
$_.Value = ($((Get-Content "Env:$($_.Name)") + ";$($_.Value)") -split ';' | Select -unique) -join ';'
}
$_
} | Set-Content -Path { "Env:$($_.Name)" }
}
# Work with git
git --version
bash
# Make new environment variables available in the current PowerShell session:
function reload {
foreach($level in "Machine","User") {
[Environment]::GetEnvironmentVariables($level).GetEnumerator() | % {
# For Path variables, append the new values, if they're not already in there
if($_.Name -match 'Path$') {
$_.Value = ($((Get-Content "Env:$($_.Name)") + ";$($_.Value)") -split ';' | Select -unique) -join ';'
}
$_
} | Set-Content -Path { "Env:$($_.Name)" }
}
}
Write-Host "Installing git..." -ForegroundColor Cyan
$exePath = "$env:TEMP\git.exe"
Invoke-WebRequest -Uri https://github.com/git-for-windows/git/releases/download/v2.37.1.windows.1/Git-2.37.1-64-bit.exe -UseBasicParsing -OutFile $exePath
Start-Process $exePath -ArgumentList '/VERYSILENT /NORESTART /NOCANCEL /SP- /CLOSEAPPLICATIONS /RESTARTAPPLICATIONS /COMPONENTS="icons,ext\reg\shellhere,assoc,assoc_sh"' -Wait
[Environment]::SetEnvironmentVariable('Path', "$([Environment]::GetEnvironmentVariable('Path', 'Machine'));C:\Program Files\Git\bin", 'Machine')
reload
git --version
bash --version
This is not the exact answer for your question.
Since you do not prefer something as heavy as WSL, I have a good alternative for your purpose that also promises native windows filesystem support. Use MSYS2 instead of gitbash. This is far better and git-bash is originally based on MSYS2
Download the prefered package of MSYS2.
If you downloaded the GUI installer, install it via CLI with
.\msys2-x86_64-latest.exe in --confirm-command --accept-messages --root C:/msys64
Or if you had downloaded the self extracting archive, install it using
.\msys2-base-x86_64-latest.sfx.exe -y -oC:\
Lauch MSYS2, then update the packages list with pacman -Syu.
Install git with pacman -S git
You will eventually come to love it.
Note that some keyboard shortcuts you are used to in linux may not work example Ctrl+Shift+v for pasting is not supported and Windows uses Shift+Insert
Credits
Just in case, check if the /LOG="C:git-for-windows.log" part of your command has a typo
/LOG="C:\git-for-windows.log"
^^^
(\ was missing)
That way, you can try again, and monitor C:\git-for-windows.log for logs.
Also, make sure you have the right to write directly under C:\.
A /LOG="$env:userprofile\git-for-windows.log" might be safer.
Run the git install once with the SAVEINF parameter, choosing all the options that you'd like to install in the installation UI:
.\Git-2.37.1-64-bit.exe /SAVEINF="c:\temp\git-install.inf"
This will create an install configuration file, which you can use to do a silent install of git using powershell:
$uri = 'https://github.com/git-for-windows/git/releases/download/v2.37.1.windows.1/Git-2.37.1-64-bit.exe'
Invoke-WebRequest -Uri $uri -OutFile git-install.exe
.\git-install.exe /LOADINF="c:\temp\git-install.inf" /VERYSILENT
This will spawn a background process and exit immediately. You can wait for it to complete like this:
while (Get-Process *git-install*) { sleep -seconds 5 }
Now its very easy to use git terminal on PowerShell just use following commands
First, Set execution policy as remotesigned.
Run powershell as Administrator and run below command
set-executionpolicy remotesigned
To install the git on powershell
Install-Module posh-git -Scope CurrentUser -Force
To import the git module
Import-Module posh-git
To load profile by default on powershell startup
Add-PoshGitToProfile -AllHosts
Related
UserData by default will run with Powershell V5.1 on the Windows Server 2022 AMI on an AWS EC2 instance that spins up. However, I want to use some cmdlets that are only supported in Powershell version 7 and greater.
How am I best able to run a script with Powershell 7+ when booting the instance with UserData?
I currently have a script that installs powershell 7, but then from that point I am not sure how to use v7 to run the rest of the commands that I have.
Invoke-WebRequest -Uri https://github.com/PowerShell/PowerShell/releases/download/v7.3.1/PowerShell-7.3.1-win-x64.msi -OutFile PowerShell.msi
Start-Process msiexec.exe -ArgumentList '/i PowerShell.msi /quiet' -Wait
I am using the WINDOWS_SERVER_2022_ENGLISH_FULL_BASE AMI.
I have tried using something like Invoke-Expression, and also have tried to get the script to call itself recursively with some conditionals, e.g.
# First Run with ps 5.1
if ($PSVersionTable.PSVersion -lt [Version]"7.0") {
Invoke-WebRequest -Uri https://github.com/PowerShell/PowerShell/releases/download/v7.3.1/PowerShell-7.3.1-win-x64.msi -OutFile PowerShell.msi
Start-Process msiexec.exe -ArgumentList '/i PowerShell.msi /quiet' -Wait
cd "C:\Program Files\PowerShell\7"
# Run this same script with ps7
./pwsh $PSCommandPath
exit
}
#
if ($PSVersionTable.PSVersion -gt [Version]"7.0") {
# Do the things I need to do with ps7...
}
Both of my attempts have been silently failing, and with ec2 userdata it is very hard to get info on why.
The approach that ended up working was to have 2 different scripts. The first script installs PS7, and then downloads the second script from S3 and executes it using PS7.
User Data exectued with PS5:
#init.ps1
<powershell>
Invoke-WebRequest -Uri https://github.com/PowerShell/PowerShell/releases/download/v7.3.1/PowerShell-7.3.1-win-x64.msi -OutFile PowerShell.msi
Start-Process msiexec.exe -ArgumentList '/i PowerShell.msi /quiet' -Wait
cd "C:\Program Files\PowerShell\7"
mkdir (Split-Path -Path 'C:/temp/setupGateway.ps1' ) -ea 0
Read-S3Object -BucketName 'my-bucket' -key 'setupGateway.ps1' -file 'C:/temp/setupGateway.ps1' -ErrorAction Stop
& "C:\Program Files\PowerShell\7\pwsh" "C:\temp\setupGateway.ps1"
</powershell>
<persist>true</persist>
PS7 script, executed separately:
# setup.ps1
Write-Output $PSVersionTable
Write-Output "Hello from PS7"
All that needs to happen to make this work is to make sure that you copy the setup.ps1 script to an S3 location. Which can be achieved in lots of different ways depending on the rest of your setup.
I'm trying to install Visual Studio Build Tools unattended, in PowerShell. I followed https://silentinstallhq.com/visual-studio-build-tools-2022-silent-install-how-to-guide/ and came up with this script:
Write-Host "Installing visual studio build tools..." -ForegroundColor Cyan
$exePath = "$env:TEMP\vs.exe"
Invoke-WebRequest -Uri https://aka.ms/vs/17/release/vs_BuildTools.exe -UseBasicParsing -OutFile $exePath
Write-Host "layout..." -ForegroundColor Cyan
Start-Process $exePath -ArgumentList "--layout .\vs_BuildTools" -Wait
cd vs_BuildTools
Write-Host "actual installation..." -ForegroundColor Cyan
Start-Process vs_setup.exe -ArgumentList "--installPath $env:USERPROFILE\vs_BuildTools2022 --nocache --wait --noUpdateInstaller --noWeb --allWorkloads --includeRecommended --includeOptional --quiet --norestart" -Wait
however it keeps stuck on layout... for hours. My guesses are that it either is asking for permission or some dialog opens. Is there a way to print what's happening?
# Visual Studio build tools
Write-Host "Installing visual studio build tools..." -ForegroundColor Cyan
cd $env:USERPROFILE
$exePath = "$env:TEMP\vs.exe"
Invoke-WebRequest -Uri https://aka.ms/vs/17/release/vs_BuildTools.exe -UseBasicParsing -OutFile $exePath
Write-Host "layout..." -ForegroundColor Cyan
Start-Process $exePath -ArgumentList "--layout .\vs_BuildTools --quiet" -Wait
cd vs_BuildTools
Write-Host "actual installation..." -ForegroundColor Cyan
Start-Process vs_setup.exe -ArgumentList "--installPath $env:USERPROFILE\vs_BuildTools2022 --nocache --wait --noUpdateInstaller --noWeb --allWorkloads --includeRecommended --includeOptional --quiet --norestart" -Wait
[Environment]::SetEnvironmentVariable('Path', "$([Environment]::GetEnvironmentVariable('Path', 'Machine'));$env:USERPROFILE\vs_BuildTools2022", 'Machine')
Before trying to automate the installation, I highly recommend to do it manually at least once. You can just copy the above commands into an interactive PowerShell session and you will see what is going on:
It is just taking ages to install!
And I am not talking about minutes here, but about hours. If you do it interactively, you will see a second console which will print all download steps and display the current progress. You just have to wait a long time until it finishes.
If you want to install it on multiple machines, I recommend to download it only once, serve the layout files (basically your offline installer) on premise and install VS from there.
I want to install CMake without any interaction. I tried this script, but there's no Install-FromMsi on my PowerShell.
Is there a fix for that or an easier way to install CMake and put it into the PowerShell path just with scripts?
PS: how to call Install-CMake with parameters?
UPDATE:
I followed https://silentinstallhq.com/cmake-silent-install-how-to-guide/ and tried
Write-Host "Installing Cmake..." -ForegroundColor Cyan
$exePath = "$env:TEMP\cmake.exe"
Write-Host "Downloading..."
(New-Object Net.WebClient).DownloadFile('https://github.com/Kitware/CMake/releases/download/v3.24.0/cmake-3.24.0-windows-x86_64.msi', $exePath)
Write-Host "Installing..."
MsiExec.exe /i $exePath ADD_CMAKE_TO_PATH=User /qn
but my Windows does not recognize the command MsiExec.exe
I changed to
Start-Process msiexec.exe -Wait -ArgumentList "/i $exePath ADD_CMAKE_TO_PATH=User /qn"
cmake --version
It looks like it installs but cmake --version says that cmake is not a command in PowerShell, so either it's not installing or not putting into PATH.
ADD_CMAKE_TO_PATH=User does what it should do, but there are two problems in your case:
You have to wait until msiexec.exe finishes. To do that, either pipe the result of the direct invocation to somewhere:
msiexec.exe /i $exePath ADD_CMAKE_TO_PATH=User /qn | Out-Null
Or use Start-Process with the -Wait parameter (which you already did):
Start-Process msiexec.exe -ArgumentList "/i $exePath ADD_CMAKE_TO_PATH=User /qn" -Wait
You can read more about that in this Q&A.
When you update the environment variables of the Machine or User scope, existing processes will not inherit them into their existing Process scope. That's why your already running PowerShell process still does not know cmake after its installation. You can read more about that in this Q&A.
You either have to start a really new PowerShell process (see above linked Q&A) or you have to reimport the environement variables of the Machine and User scope into your Process scope:
foreach($level in "Machine","User") {
[Environment]::GetEnvironmentVariables($level).GetEnumerator() | % {
# For Path variables, append the new values, if they're not already in there
if($_.Name -match 'Path$') {
$_.Value = ($((Get-Content "Env:$($_.Name)") + ";$($_.Value)") -split ';' | Select -unique) -join ';'
}
$_
} | Set-Content -Path { "Env:$($_.Name)" }
}
This code is taken from this answer.
After that, cmake --version and Get-Command cmake will work.
Side notes:
If Start-Process can find msiexec.exe, then the direct invocation should also work. Maybe you just had a typo, when trying that.
A more PowerShelly way to download a file is:
Invoke-WebRequest -Uri https://github.com/Kitware/CMake/releases/download/v3.24.0/cmake-3.24.0-windows-x86_64.msi -UseBasicParsing -OutFile $exePath
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
I have a power shell script to download and install windows updates on Windows server 2012 R2. The script is working fine when i login to the remote machine and execute the script. The script fails when i try tio install it via powershell using invoke command. When i use invoke command the script downloads the files without any issue but it never installs the files. Below is the script i have
$MSUs = #('https://download.microsoft.com/download/D/6/0/D60ED3E0-93A5-4505-8F6A-8D0A5DA16C8A/Windows8.1-KB2919442-x64.msu',
'https://download.microsoft.com/download/2/5/6/256CCCFB-5341-4A8D-A277-8A81B21A1E35/Windows8.1-KB2919355-x64.msu',
'https://download.microsoft.com/download/2/5/6/256CCCFB-5341-4A8D-A277-8A81B21A1E35/Windows8.1-KB2932046-x64.msu',
'https://download.microsoft.com/download/2/5/6/256CCCFB-5341-4A8D-A277-8A81B21A1E35/Windows8.1-KB2934018-x64.msu',
'https://download.microsoft.com/download/2/5/6/256CCCFB-5341-4A8D-A277-8A81B21A1E35/Windows8.1-KB2938439-x64.msu'
)
foreach ($MSU in $MSUs) {
$FileName = "C:\Temp\$(Split-Path $MSU -Leaf)"
Write-Host "Downloading package: $(Split-Path $MSU -Leaf)"
(New-Object System.Net.WebClient).DownloadFile($MSU, $FileName)
Write-Host "Installing package: $(Split-Path $MSU -Leaf)"
Start-Process wusa -ArgumentList "$FileName /quiet /norestart" -Wait
}
I try to execute the script with below command
Invoke-Command -Credential $cred -ComputerName 10.xx.xx.xxx -ScriptBlock { C:\\Temp\\1_KB.ps1| write-host}