1

I would like to install GIT if it's not installed and then use git clone using PowerShell.

My first attempt looks like this:

try {
  git --version | Out-Null
  Write-Host "GIT is already installed."

} catch [System.Management.Automation.CommandNotFoundException]{
  Write-Host "GIT ist not installed."
  Write-Host "Installing..."
  & gitsetup.exe /VERYSILENT /PathOption=CmdTools | Out-Null
}

git clone https://github.com/username/repository

I get a command not found error when it gets to git clone, because GIT has not finished installing.

Is there a good way to solve this problem?

3 Answers 3

2
  • Use Start-Process with the -Wait switch to launch your installer and wait for it to complete.

    • Note: As TToni's answer points out, piping to | Out-Null, as in your question, is a somewhat obscure shortcut to making invocation of a GUI application synchronous;
      in general, however, Start-Process gives you more control over the invocation, such as the ability to invoke an application hidden.
  • Additionally, you'll have to add the Git installation directory to $env:PATH manually for the current session (because the $env:PATH modifications made by the installer are only visible to future sessions), so that invocation with just git succeeds; the code below assumes the standard location, C:\Program Files\Git\cmd; adjust as needed - I'm unclear on what /PathOption=CmdTools does.

    • Note: TToni's answer shows an alternative approach that doesn't require knowing the installation directory ahead of time: by redefining $env:PATH based on the updated registry definitions, the Git installation dir. should be added; the only caveat is that you'll potentially wipe out custom in-process modifications of $env:PATH, such as additions performed in your $PROFILE file.
  • To make the code more robust, add a check if the installation succeeded, by retrying the original test.

$retrying = $false
do {
  try {

    # Test if git can be invoked.
    $null = git --version
    if (-not $retrying) { Write-Host "Git is already installed." }
    break # Git is (now) available, exit.

  } catch [System.Management.Automation.CommandNotFoundException] {

    if ($retrying) {
      Throw "Git is not installed, and installation on demand failed."
    }

    Write-Host "Git ist not installed."
    Write-Host "Installing..."

    # Install synchronously (wait for the installer to complete).
    Start-Process -NoNewWindow -Wait gitsetup.exe '/VERYSILENT /PathOption=CmdTools'

    # So that invocation by mere file name (`git`) works in this session too,
    # add the Git installation dir to $env:Path manually.
    $env:Path += ';C:\Program Files\Git\cmd'

    # Continue the loop, to see if git is now installed.
    $retrying = $true
  }
} while ($true)

git clone https://github.com/username/repository

Sign up to request clarification or add additional context in comments.

1 Comment

@MarcJefferson5, no: The if ($retrying) { Throw "Git is not installed, and installation on demand failed." } statement aborts, if the catch block is entered a second time.
1

The | Out-Null after the setup should already be sufficient to wait for the process exit.

But the installer will probably modify the global PATH variable to include the git path and this isn't visible in your current powershell process yet. It only looks up and copies the environment at process start.

If you put the following line after the setup call I expect it to work:

$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User")

1 Comment

Good point about Out-Null - it's easy to forget this somewhat obscure trick. Also a good idea to reload the persistent Path definitions from the registry, because it is more robust than adding an assumed location to the in-process value; the only - small - caveat is that you'll potentially wipe out custom in-process Path modifications.
0

add in catch scope this code to create pause until process end it's work:

while(Get-Process -Name <NameInstallerProc> -ErrorAction SilentlyContinue){
Start-Sleep -Seconds 2
}

1 Comment

Start-Process -Wait directly allows you to launch and wait synchronously. While the likelihood of failure is low in this case, note that your approach isn't robust, in that targeting a process by name doesn't guarantee that you'll get the process of interest.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.