Skip to content

Commit

Permalink
Merge pull request #748 from aaronparker/apps
Browse files Browse the repository at this point in the history
Apps
  • Loading branch information
aaronparker authored Sep 28, 2024
2 parents e798c3a + 86d1c04 commit f666014
Show file tree
Hide file tree
Showing 10 changed files with 125 additions and 48 deletions.
45 changes: 45 additions & 0 deletions Evergreen/Apps/Get-MicrosoftWindowsApp.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
function Get-MicrosoftWindowsApp {
<#
.NOTES
Site: https://stealthpuppy.com
Author: Aaron Parker
Twitter: @stealthpuppy
#>
[OutputType([System.Management.Automation.PSObject])]
[CmdletBinding(SupportsShouldProcess = $false)]
param (
[Parameter(Mandatory = $false, Position = 0)]
[ValidateNotNull()]
[System.Management.Automation.PSObject]
$res = (Get-FunctionResource -AppName ("$($MyInvocation.MyCommand)".Split("-"))[1])
)

foreach ($Url in $res.Get.Download.Uri) {
# Grab the download link headers to find the file name
$params = @{
Uri = $Url
Method = "Head"
ReturnObject = "Headers"
}
$Headers = Invoke-EvergreenWebRequest @params
if ($null -ne $Headers) {

# Match filename
$Filename = [RegEx]::Match($Headers['Content-Disposition'], $res.Get.Download.MatchFilename).Captures.Groups[1].Value

# Match version
$Version = [RegEx]::Match($Headers['Content-Disposition'], $res.Get.Download.MatchVersion).Captures.Value
if ($Version.Length -eq 0) { $Version = "Unknown" }

# Construct the output; Return the custom object to the pipeline
$PSObject = [PSCustomObject] @{
Version = $Version
Date = $Headers['Last-Modified'] | Select-Object -First 1
Architecture = Get-Architecture -String $Filename
Filename = $Filename
URI = $Url
}
Write-Output -InputObject $PSObject
}
}
}
33 changes: 33 additions & 0 deletions Evergreen/Manifests/MicrosoftWindowsApp.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"Name": "Microsoft Windows App",
"Source": "https://learn.microsoft.com/en-us/windows-app/whats-new",
"Get": {
"Update": {},
"Download": {
"Uri": [
"https://query.prod.cms.rt.microsoft.com/cms/api/am/binary/RW1pC6G",
"https://query.prod.cms.rt.microsoft.com/cms/api/am/binary/RW1pHol",
"https://query.prod.cms.rt.microsoft.com/cms/api/am/binary/RW1pJV5"
],
"ApiUri": "https://query.prod.cms.rt.microsoft.com/cms/api",
"ApiHeader1": "X-CMS-Tenant",
"ApiHeader2": "X-CMS-Type",
"ApiHeader3": "X-CMS-DocumentId",
"MatchFilename": "(WindowsApp_.*_Release_.*.msix)",
"MatchVersion": "(\\d+(\\.\\d+){1,4})",
"SplitText": "filename=",
"DatePattern": "ddd, dd MMM yyyy HH:mm:ss GMT"
}
},
"Install": {
"Setup": "",
"Physical": {
"Arguments": "",
"PostInstall": []
},
"Virtual": {
"Arguments": "",
"PostInstall": []
}
}
}
8 changes: 4 additions & 4 deletions docs/invoke.md → docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,12 @@ PS C:\> Invoke-RestMethod -Uri "https://evergreen-api.stealthpuppy.com/app/Unsup
Invoke-RestMethod: {message: "Application not found. List all apps for valid application names. Application names are case sensitive.}
```

## Invoke-EvergreenApp
## Get-EvergreenAppFromApi

Evergreen includes the `Invoke-EvergreenApp` function that is used in much the same way as `Get-EvergreenApp`. This function is simpler than using `Invoke-RestMethod`, and it automatically filters for available applications. For example, to query the API for application data for Microsoft Edge, use:
Evergreen includes the `Get-EvergreenAppFromApi` function that is used in much the same way as `Get-EvergreenApp`. This function is simpler than using `Invoke-RestMethod`, and it automatically filters for available applications. For example, to query the API for application data for Microsoft Edge, use:

```powershell
PS C:\> Invoke-EvergreenApp -Name "MicrosoftEdge"
PS C:\> Get-EvergreenAppFromApi -Name "MicrosoftEdge"
Version : 89.0.774.76
Platform : Windows
Expand All @@ -63,5 +63,5 @@ This returns the current version and download URLs for Microsoft Edge using the
Just as with `Get-EvergreenApp`, the output can be filtered for the specific application installer with `Where-Object`. The example below returns the current version and download URL for the Stable channel of the 64-bit Enterprise ring of Microsoft Edge.

```powershell
Invoke-EvergreenApp -Name "MicrosoftEdge" | Where-Object { $_.Architecture -eq "x64" -and $_.Channel -eq "Stable" -and $_.Release -eq "Enterprise" }
Get-EvergreenAppFromApi -Name "MicrosoftEdge" | Where-Object { $_.Architecture -eq "x64" -and $_.Channel -eq "Stable" -and $_.Release -eq "Enterprise" }
```
14 changes: 7 additions & 7 deletions docs/getlibraryapp.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
# Install an application from a library

Once an Evergreen library is populated with application downloads, it can be queried for a specific application for the available versions of that application with `Get-EvergreenLibraryApp`. Details of the Evergreen library must be passed to `Get-EvergreenLibraryApp` from `Get-EvergreenLibrary`.
Once an Evergreen library is populated with application downloads, it can be queried for a specific application for the available versions of that application with `Get-EvergreenAppFromLibrary`. Details of the Evergreen library must be passed to `Get-EvergreenAppFromLibrary` from `Get-EvergreenLibrary`.

The application details that are returned will include the version and path to the installer binaries for installing the target application. Application details are returned in descending order of version, thus the latest available version can be used or the details filtered for a specific version.

## Examples

In this example, details of the target library at `\\server\EvergreenLibrary` are returned with `Get-EvergreenLibrary` and placed into a variable `$Library`. `Get-EvergreenLibraryApp` is then used to search for Microsoft Visual Studio Code in the library.
In this example, details of the target library at `\\server\EvergreenLibrary` are returned with `Get-EvergreenLibrary` and placed into a variable `$Library`. `Get-EvergreenAppFromLibrary` is then used to search for Microsoft Visual Studio Code in the library.

```powershell
PS C:\> $Library = Get-EvergreenLibrary -Path "\\server\EvergreenLibrary"
PS C:\> Get-EvergreenLibraryApp -Inventory $Library -Name "MicrosoftVisualStudioCode"
PS C:\> Get-EvergreenAppFromLibrary -Inventory $Library -Name "MicrosoftVisualStudioCode"
Version : 1.74.3
URI : https://az764295.vo.msecnd.net/stable/97dec172d3256f8ca4bfb2143f3f76b503ca0534/VSCodeSetup-x64-1.74.3.exe
Expand All @@ -29,10 +29,10 @@ Channel : Stable
Architecture : x64
```

This syntax can be simplified by passing details of the Evergreen library at `\\server\EvergreenLibrary` to `Get-EvergreenLibraryApp` via the pipeline to return details for Microsoft Visual Studio Code.
This syntax can be simplified by passing details of the Evergreen library at `\\server\EvergreenLibrary` to `Get-EvergreenAppFromLibrary` via the pipeline to return details for Microsoft Visual Studio Code.

```powershell
PS C:\> Get-EvergreenLibrary -Path "\\server\EvergreenLibrary" | Get-EvergreenLibraryApp -Name "MicrosoftVisualStudioCode"
PS C:\> Get-EvergreenLibrary -Path "\\server\EvergreenLibrary" | Get-EvergreenAppFromLibrary -Name "MicrosoftVisualStudioCode"
Version : 1.74.3
URI : https://az764295.vo.msecnd.net/stable/97dec172d3256f8ca4bfb2143f3f76b503ca0534/VSCodeSetup-x64-1.74.3.exe
Expand All @@ -54,7 +54,7 @@ Architecture : x64
Application information returned from an Evergreen library can be used in a script to install the latest available version (in this case) of Microsoft Visual Studio Code:

```powershell
$App = Get-EvergreenLibrary -Path "\\server\EvergreenLibrary" | Get-EvergreenLibraryApp -Name "MicrosoftVisualStudioCode" | Select-Object -First 1
$App = Get-EvergreenLibrary -Path "\\server\EvergreenLibrary" | Get-EvergreenAppFromLibrary -Name "MicrosoftVisualStudioCode" | Select-Object -First 1
$params = @{
FilePath = $App.Path
ArgumentList = "/VERYSILENT /NOCLOSEAPPLICATIONS /NORESTARTAPPLICATIONS /NORESTART /SP- /SUPPRESSMSGBOXES /MERGETASKS=!runcode"
Expand All @@ -69,7 +69,7 @@ Start-Process @params
Where a specific version of Visual Studio Code needs to be installed instead of the latest version, the specific version can be selected before installing:

```powershell
$App = Get-EvergreenLibrary -Path "\\server\EvergreenLibrary" | Get-EvergreenLibraryApp -Name "MicrosoftVisualStudioCode" | Where-Object { $_.Version -eq "1.74.0" }
$App = Get-EvergreenLibrary -Path "\\server\EvergreenLibrary" | Get-EvergreenAppFromLibrary -Name "MicrosoftVisualStudioCode" | Where-Object { $_.Version -eq "1.74.0" }
$params = @{
FilePath = $App.Path
ArgumentList = "/VERYSILENT /NOCLOSEAPPLICATIONS /NORESTARTAPPLICATIONS /NORESTART /SP- /SUPPRESSMSGBOXES /MERGETASKS=!runcode"
Expand Down
File renamed without changes.
28 changes: 19 additions & 9 deletions docs/index.md
Original file line number Diff line number Diff line change
@@ -1,25 +1,35 @@
# Evergreen

Evergreen is a PowerShell module that returns the latest version and download URLs for a set of common Windows applications. The module consists of simple functions to use in scripts when performing several tasks including:
Evergreen is a PowerShell module that returns the latest version and download links for a set of common Windows applications.

* Retrieve the latest version of an application to compare against a version already installed or downloaded
* Return the URL for the latest version of the application to download it for local installation or deployment to target machines
## Trust

Evergreen is intended for use with solutions used to automate software deployments. These solutions could be:
The goal of this project is to provide trust. Evergreen executes in your environment and queries application vendor sources only. To find application versions, Evergreen queries the same update APIs used by the application to find new updates or a source owned by the vendor. This means that you can trust what Evergreen returns because there is no middle man.

* Image creation with Hashicorp Packer - images can be created with the latest version of a set of applications
* Import applications into Configuration Manager or [Microsoft Intune](https://github.com/aaronparker/packagefactory) - keep up to date with the latest versions of applications
* Validating or auditing a desktop image to ensure the current version of an application is installed
* Create a [library of application installers](https://stealthpuppy.com/apptracker) - by regularly running Evergreen functions, you can retrieve and download the current version of an application and store it in an application directory structure for later use
## Why

Evergreen helps solve several challenges including:

* Finding the latest version of an application to compare against a version already installed or downloaded
* Finding the URL for the latest application installer to download it for local installation (via scripted install or in a gold image) or deployment to target machines (e.g. Intune or ConfigMgr)

Evergreen helps to automate software deployments. These could be:

* Gold image creation with Hashicorp Packer - images can be created with the latest version of a set of applications
* Import applications into the Microsoft Deployment Toolkit, Configuration Manager or [Microsoft Intune](https://github.com/aaronparker/packagefactory) - stay current with the latest versions of applications
* Validating or auditing a Windows image or machine for installed application versions
* Create a [library of application installers](https://stealthpuppy.com/apptracker) - by regularly running Evergreen functions, you can retrieve and download the current version of an application and store it for later use
* Submitting manifests to `Winget` or `Chocolatey` or similar - Evergreen can return an object with a version number and download URL that can be used to construct manifests for the most recent versions

There are several community and commercial solutions that manage application deployment and updates already. This module isn't intended to compete against those, and Evergreen isn't intended to be a fully featured package manager for Windows. Evergreen can be complementary to 3rd party solutions

## Functions

Primary functions in Evergreen are:

* `Get-EvergreenApp` - returns details of the latest release of an application including the version number and download URL for supported applications. Runs in your environment
* `Save-EvergreenApp` - simplifies downloading application installers returned from `Get-EvergreenApp`
* `Get-EvergreenEndpointFromApi` - returns details of the latest release of an application including the version number and download URL from the Evergreen API
* `Save-EvergreenApp` - simplifies downloading application URLs returned from `Get-EvergreenApp`
* `Find-EvergreenApp` - lists applications supported by the module
* `Test-EvergreenApp` - tests that the URIs returned by `Get-EvergreenApp` are valid
* `New-EvergreenLibrary` - creates a new Evergreen library for downloading and maintaining multiple versions of application installers
Expand Down
8 changes: 6 additions & 2 deletions docs/under.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,26 @@ Evergreen includes the following directory structure:

* `<ModuleBase>/Public` - public functions including `Get-EvergreenApp`, `Find-EvergreenApp` and `Save-EvergreenApp`
* `<ModuleBase>/Apps` - internal per-application functions that contain the logic for retrieving application details. These are often unique for each application
* `<ModuleBase>/Shared` - internal functions used by specific apps to reduce repeated code
* `<ModuleBase>/Manifests` - each application includes a manifest in JSON format that includes application specific details used by the per-application functions. These describe details of the application including URLs used to determine the latest version of the application
* `<ModuleBase>/Private` - internal functions containing reusable code

### Public

The `Public` folder includes all functions exported from Evergreen:

* `ConvertTo-DotNetVersionClass.ps1`
* `Export-EvergreenApp.ps1`
* `Export-EvergreenManifest.ps1`
* `Find-EvergreenApp.ps1`
* `Get-EvergreenApp.ps1`
* `Get-EvergreenAppFromApi.ps1`
* `Get-EvergreenAppFromLibrary.ps1`
* `Get-EvergreenEndpointFromApi.ps1`
* `Get-EvergreenLibrary.ps1`
* `Invoke-EvergreenApp.ps1`
* `Invoke-EvergreenLibraryUpdate.ps1`
* `New-EvergreenLibrary.ps1`
* `Save-EvergreenApp.ps1`
* `Start-EvergreenLibraryUpdate.ps1`
* `Test-EvergreenApp.ps1`

### Apps
Expand Down
8 changes: 4 additions & 4 deletions docs/updatelibrary.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Update an Evergreen Library

To update a library, use `Invoke-EvergreenLibraryUpdate` - this function will read the `EvergreenLibrary.json` file and use `Get-EvergreenApp` and `Save-EvergreenApp` to populate the library with the application installers and maintain a manifest of the application version information for later reference.
To update a library, use `Start-EvergreenLibraryUpdate` - this function will read the `EvergreenLibrary.json` file and use `Get-EvergreenApp` and `Save-EvergreenApp` to populate the library with the application installers and maintain a manifest of the application version information for later reference.

Here's an example - `EvergreenLibrary.json` contains the following entry for Microsoft Teams:

Expand Down Expand Up @@ -33,12 +33,12 @@ Each time a new version of Team installer is downloaded, `MicrosoftTeams.json` i

## How to update a library

`Invoke-EvergreenLibraryUpdate` has a single parameter - `-Path`, which should be the path to the Evergreen library:
`Start-EvergreenLibraryUpdate` has a single parameter - `-Path`, which should be the path to the Evergreen library:

```powershell
Invoke-EvergreenLibraryUpdate -Path "\\server\EvergreenLibrary"
Start-EvergreenLibraryUpdate -Path "\\server\EvergreenLibrary"
```

If a path is specified that does not contain `EvergreenLibrary.json` and error will be thrown.

To download new application installers when a new version is detected, `Invoke-EvergreenLibraryUpdate` can be run via a scheduled task or other automation tools. This provides a simple method to update the library and make new application available for install or packaging.
To download new application installers when a new version is detected, `Start-EvergreenLibraryUpdate` can be run via a scheduled task or other automation tools. This provides a simple method to update the library and make new application available for install or packaging.
15 changes: 0 additions & 15 deletions docs/why.md

This file was deleted.

Loading

0 comments on commit f666014

Please sign in to comment.