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
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
I'm trying to get a script together to remotely install some windows updates on some remote servers that are connected in an offline domain.
I have tried regular PS Remoting and after some research, I think what I am trying to do isnt supported by microsoft. When checking my event logs I have a bunch of these errors.
Edit
I wanted to add that I have tried running the .\Install2012R2.ps1 script from my local computer, modified to have the Invoke-Command in that and have it run the update portion of the original Install2012R2.ps1 and I would get the same errors.
I was hoping that by placing the script on each server that it would like that more.
End Edit
Windows update could not be installed because of error 2147942405 "Access is denied."
(Command line: ""C:\Windows\System32\wusa.exe" "C:\Updates\windows8.1-kb4556853-x64.msu" /quiet /norestart")
I have tried running Invoke-Command as credentialed to an administrator account on the servers but I have been having no luck and was looking for some advice if someone has maybe tried/done this before.
$Servers = #("V101-Test1","V101-Test2")
$Username = 'admin'
$Password = 'Password'#not actual password
$pass = ConvertTo-SecureString -AsPlainText $Password -Force
$Cred = New-Object System.Management.Automation.PSCredential -ArgumentList $Username,$pass
Get-PSSession | Remove-PSSession
New-PSSession -ComputerName $Servers
foreach($Server in $Servers){
Get-ChildItem -Path C:\Source\Temp -Recurse | Copy-Item -Destination "\\$Server\c$\Updates\" -Force
}
Invoke-Command $Servers -Credential $Cred -ScriptBlock{
& "C:\Updates\Install2012R2.ps1"
}
EDIT 2
Here is the actual install code of the Install2012R2.ps1 script
$updatedir= "./"
$files = Get-ChildItem $updatedir -Recurse
$msus = $files | ? {$_.extension -eq ".msu"}
$exes = $files | ? {$_.extension -eq ".exe"}
foreach ($file in $msus){
$KBCtr++
$fullname = $file.fullname
# Need to wrap in quotes as folder path may contain space
$fullname = "`"" + $fullname + "`""
$KBN = $fullname.split('-')[1]
# Need to wrap in quotes as folder path may contain space
$fullname = "`"" + $fullname + "`""
# Specify the command line parameters for wusa.exe
$parameters = $fullname + " /quiet /norestart"
# Start services and pass in the parameters
$install = [System.Diagnostics.Process]::Start( "wusa",$parameters )
$install.WaitForExit()
}
I'm not sure why wusa.exe is failing here with Access Denied, but here is a PowerShell-native approach you can try. If nothing else, it should give you a clearer indication via the captured error information as to what the underlying issue is:
Add-WindowsPackage -Path C:\Updates\OurHeroicUpdate.msu -Online -PreventPending -NoRestart
-Path is the path to the msu file
-Online tells Add-WindowsPackage to modify the currently "mounted image" (the running version) of Windows (as opposed to an offline disk image you could also apply it to)
-PreventPending prevents installing the msu if there is already a pending change, like needing to reboot for updates.
Add-WindowsPackage is part of the DISM module available under Windows PowerShell, and is the functional equivalent of dism /packagepath:"cabfile", although it can take an msu where dism.exe only allows a cab.
I've setup a deployment group successfully via Azure Pipelines and have deployed my Api successfully as well. My homework says that I have to prove that the Api was deployed successfully so I thought that I should run this via IIS. However, a 502.5 error is being thrown and I find out that a server hosting bundle is needed. How do you automate this via Azure PIpelines? I found an Invoke-Webrequest script that does this but it only installs 1.0.0...
I'm not sure if there is a built in way to do this, but in our project we've done it by including the DotNetCore.2.0.7-WindowsHosting.exe installer in our build artifacts and simply executing the installer with a Powershell step at the beginning of the release process.
You'll want to use the /quiet and /norestart flags:
$Path = "path to your installer exe in artifacts"
$args = New-Object -TypeName System.Collections.Generic.List[System.String]
$args.Add("/quiet")
$args.Add("/norestart")
Start-Process -FilePath $Path -ArgumentList $args -NoNewWindow -Wait -PassThru
Good luck!
if you are looking to download this directly from MS instead you can use this script:
$ErrorActionPreference="Stop";
If(-NOT ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent() ).IsInRole( [Security.Principal.WindowsBuiltInRole] “Administrator”)){
throw "Run command in Administrator PowerShell Prompt"
};If($PSVersionTable.PSVersion -lt (New-Object System.Version("3.0"))){ throw "The minimum version of Windows PowerShell that is required by the script (3.0) does not match the currently running version of Windows PowerShell." };
$tempDir = [System.IO.Path]::GetTempPath()
$downloadPath="$tempdir\netCoreHostingBundle.exe";
$DefaultProxy=[System.Net.WebRequest]::DefaultWebProxy;
$securityProtocol=#();
$securityProtocol+=[Net.ServicePointManager]::SecurityProtocol;
$securityProtocol+=[Net.SecurityProtocolType]::Tls12;
[Net.ServicePointManager]::SecurityProtocol=$securityProtocol;
$WebClient=New-Object Net.WebClient;
$Uri='https://download.visualstudio.microsoft.com/download/pr/9b9f4a6e-aef8-41e0-90db-bae1b0cf4e34/4ab93354cdff8991d91a9f40d022d450/dotnet-hosting-3.1.6-win.exe';
if($DefaultProxy -and (-not $DefaultProxy.IsBypassed($Uri))){$WebClient.Proxy= New-Object Net.WebProxy($DefaultProxy.GetProxy($Uri).OriginalString, $True);};
$WebClient.DownloadFile($Uri, $downloadPath);
$args = New-Object -TypeName System.Collections.Generic.List[System.String]
$args.Add("/quiet")
$args.Add("/norestart")
Start-Process -FilePath $downloadPath -ArgumentList $args -NoNewWindow -Wait -PassThru -WorkingDirectory $tempDir
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}