Skip to content

Commit

Permalink
Block Exec of Code.exe while installing/upgrading
Browse files Browse the repository at this point in the history
- Fixes #2
- Updated README
  • Loading branch information
VertigoRay committed Jun 18, 2018
1 parent 673d30b commit fce1a49
Show file tree
Hide file tree
Showing 2 changed files with 157 additions and 0 deletions.
49 changes: 49 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
[VS Code](https://vscode.microsoft.com) [doesn't do completely silent updates](https://github.com/Microsoft/vscode/issues/9539#issuecomment-397772482).
This works around that shortcoming and allows the user to just *use* VS Code.

# Description

This is a simple implementation of a more complex installer/updater process that I manage for work.
I expect this script to be implemented as a scheduled task; either manually or via GPO.

## Quick Start

See the [Base64 Example, below](#base64-encoded).

# Parameters

Parameters let you customize some installer options.
Expand All @@ -11,6 +20,14 @@ Keep in mind that environment variables are always strings.
So, setting a switch parameter to `'$false'` via an environment variable would still be `$true`.
You can see what I mean with these examples: `[bool]'true'`, `[bool]'false'`, `[bool]'$true'`, `[bool]'$false'`, `[bool]'0'`, and `[bool]''`.

## DoNotBlock

- Type: `[switch]`

Set this if you don't want to have VS Code blocked from executing during the installation/upgrade of VS Code.
I'm not sure what the implications of this are, but I do know that VS Code's `setup.exe` checks for VS Code to be running and doesn't let the installer proceed if it is.
I also realize the VS Code can install in the background if you initiate the install from withing VS Code.

## LogPath

- Type: `[IO.FileInfo]`
Expand All @@ -24,6 +41,38 @@ In other words: the logging will not append to the previous run of this script.
This keeps the log file from getting bloated.
I tend to believe that only the latest iteration is ever really needed anyway.

## PopupTitle

- Type: `[string]`
- Default: `'VS Code: Installing/Upgrading'`

[When blocking VS Code from launching during an install/upgrade](#donotblock), there will be a message box that pops up if someone attempts to launch VS Code.
This sets the title of that message box.

## PopupText

- Type: `[string]`
- Default: `'VS Code is currently being installed or upgraded. It will not be accessible for the duration of the install. This won''t take long ... try again in a minute.'`

[When blocking VS Code from launching during an install/upgrade](#donotblock), there will be a message box that pops up if someone attempts to launch VS Code.
This sets the body text of that message box.

## PopupDuration

- Type: `[int]`
- Default: `30`

[When blocking VS Code from launching during an install/upgrade](#donotblock), there will be a message box that pops up if someone attempts to launch VS Code.
This sets the auto-close timeout in seconds of that message box.

## PopupType

- Type: `[int32]`
- Default: `0x30`

[When blocking VS Code from launching during an install/upgrade](#donotblock), there will be a message box that pops up if someone attempts to launch VS Code.
This sets the alert icon of that message box.

## SetupMergeTasks

- Type: `[string]`
Expand Down
108 changes: 108 additions & 0 deletions Update-VSCode.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,30 @@

[CmdletBinding()]
Param(
[Parameter()]
[switch]
$DoNotBlock,

[Parameter()]
[IO.FileInfo]
$LogPath = $(if ($env:UpdateVSCodeLogPath) { $env:UpdateVSCodeLogPath } else { "${env:SystemRoot}\Logs\Update-VSCode.ps1.log" }),

[Parameter()]
[string]
$PopupTitle = $(if ($env:UpdateVSCodePopupTitle) { $env:UpdateVSCodePopupTitle } else { 'VS Code: Installing/Upgrading' }),

[Parameter()]
[string]
$PopupText = $(if ($env:UpdateVSCodePopupText) { $env:UpdateVSCodePopupText } else { 'VS Code is currently being installed or upgraded. It will not be accessible for the duration of the install. This won''t take long ... try again in a minute.' }),

[Parameter()]
[string]
$PopupDuration = $(if ($env:UpdateVSCodePopupDuration) { $env:UpdateVSCodePopupDuration } else { '30' }),

[Parameter()]
[string]
$PopupType = $(if ($env:UpdateVSCodePopupType) { $env:UpdateVSCodePopupType } else { '0x30' }),

[Parameter()]
[string]
$SetupMergeTasks = $(if ($env:UpdateVSCodeSetupMergeTasks) { $env:UpdateVSCodeSetupMergeTasks } else { '!runcode,addcontextmenufiles,addcontextmenufolders,associatewithfiles,addtopath' }),
Expand Down Expand Up @@ -49,12 +69,16 @@ if (
}

$applicationName = 'Microsoft Visual Studio Code'
$processNames = @('Code')
$scriptGuid = 'a229ded3-1ecb-4a0a-b627-9c66b7692d3e'
$urlTags = 'https://api.github.com/repos/Microsoft/vscode/tags'
$urlDownload = 'https://az764295.vo.msecnd.net/stable/{0}/VSCodeSetup-x64-{1}.exe'
$vscodeSetup = "${env:Temp}\VSCodeSetup.exe"

Write-Host "# General Settings"
Write-Host "## Application Name: ${applicationName}"
Write-Host "## Process Names: ${processNames}"
Write-Host "## Script GUID: ${scriptGuid}"
Write-Host "## URL Tags: ${urlTags}"
Write-Host "## URL Download: ${urlDownload}"
Write-Host "## VS Code Setup *Download To* Location: ${vscodeSetup}"
Expand Down Expand Up @@ -124,6 +148,52 @@ if ($versionInstalled -ne $versionLatest) {
}
Write-Host "## VS Code not in use"

[System.Collections.ArrayList] $vbsFilePaths = @()
if ((-not $DoNotBlock.IsPresent) -or (-not $env:UpdateVSCodeDoNotBlock)) {
Write-Host '## Will block VS Code from executing during the installation ...'

$debuggerCommand = 'wscript.exe //E:vbscript {0}'
$blockedAppVbs = @'
Dim wshShell: Set wshShell = WScript.CreateObject("WScript.Shell")
WshShell.Popup "{0}", {1}, "{2}", {3}
'@ -f @(
$PopupText,
($PopupDuration -as [int]),
$PopupTitle,
($PopupType -as [int32])
)

foreach ($processName in $processNames) {
Write-Host ('### Blocking: {0}.exe' -f $processName)

$vbsFilePath = New-TemporaryFile
$vbsFilePaths.Add($vbsFilePath) | Out-Null

($blockedAppVbs -f $processName) | Out-File -Encoding ascii -LiteralPath $vbsFilePath

[string] $processKey = Join-Path $ifeoKey "${processName}.exe" -ErrorAction Stop
try {
# The $processKey key already exists
[string] $processKey = Resolve-Path $processKey -ErrorAction Stop
} catch [System.Management.Automation.ItemNotFoundException] {
# The $processKey key does not exist
New-Item -Type Directory $processKey -ErrorAction Stop | Out-Null
[string] $processKey = Resolve-Path $processKey -ErrorAction Stop
New-ItemProperty -Path $processKey -Name ('{0}MadeMe' -f $scriptGuid) -Type 'DWORD' -Value $true | Out-Null
}

$debuggerExisting = (Get-ItemProperty $processKey).Debugger
if (($debuggerExisting | Measure-Object).Count) {
# The 'Debugger' value already exists
New-ItemProperty -Path $processKey -Name ('Debugger_{0}RenamedMe' -f $scriptGuid) -Value $debuggerExisting -ErrorAction 'SilentlyContinue' | Out-Null
Remove-ItemProperty -Path $processKey -Name 'Debugger' | Out-Null
}

New-ItemProperty -Path $processKey -Name 'Debugger' -Value ($debuggerCommand -f $vbsFilePath) | Out-Null
New-ItemProperty -Path $processKey -Name ('{0}MadeDebugger' -f $scriptGuid) -Type 'DWORD' -Value $true | Out-Null
}
}

Write-Host "## Running VSCode Setup"
if ($SetupSilentNoCancel.IsPresent -or $env:UpdateVSCodeSetupSilentNoCancel) {
$ArgumentList = @('/SILENT', '/NOCANCEL')
Expand All @@ -147,6 +217,44 @@ if ($versionInstalled -ne $versionLatest) {

$result = Start-Process @startProcess
Write-Host "Exit Code: $($result.ExitCode)"

Write-Host '## Time to unblock VS Code from executing ...'
foreach ($processName in $processNames) {
Write-Host ('### Unblocking: {0}.exe' -f $processName)

[string] $processKey = Join-Path $ifeoKey "${processName}.exe" -ErrorAction Stop
Write-Debug "### Process Key: ${processKey}"

try {
$properties = Get-ItemProperty -Path $processKey -ErrorAction Stop
Write-Host "### Process Key Properties: $($properties | Out-String)"
} catch [System.Management.Automation.ItemNotFoundException] {
Write-Error "[ItemNotFoundException] Unexpected Error; should never see this: $_"
continue
}

Write-Debug "### MadeMe: $($properties["${scriptGuid}MadeMe"])"

if ($properties.$("${scriptGuid}MadeMe")) {
Write-Host "### Deleting Key: ${processKey}"
Remove-Item $processKey -Recurse -Force -ErrorAction Stop | Out-Null
} elseif ($properties.$("${scriptGuid}MadeDebugger")) {
Write-Host "### Deleting Key Value: ${processKey} : Debugger"
Remove-ItemProperty -Path $processKey -Name 'Debugger' -ErrorAction Stop | Out-Null

Write-Host "### Deleting Key Value: ${processKey} : ${scriptGuid}MadeDebugger"
Remove-ItemProperty -Path $processKey -Name "${scriptGuid}MadeDebugger" -ErrorAction Stop | Out-Null
} elseif ($properties.$("Debugger_${scriptGuid}RenamedMe")) {
Write-Host "### Deleting Key Value: ${processKey} : Debugger"
Remove-ItemProperty -Path $processKey -Name 'Debugger' -ErrorAction Stop | Out-Null

Write-Host "### Renaming Key: ${processKey} : Debugger_${scriptGuid}RenamedMe > Debugger"
New-ItemProperty -Path $processKey -Name 'Debugger' -Value $properties.$("Debugger_${scriptGuid}RenamedMe") -ErrorAction Stop | Out-Null
Remove-ItemProperty -Path $processKey -Name "Debugger_${scriptGuid}RenamedMe" -ErrorAction Stop | Out-Null
}
}

$vbsFilePaths | Remove-Item -Force
} else {
Write-Host "## Latest version already installed."
}
Expand Down

0 comments on commit fce1a49

Please sign in to comment.