text:
@import url('open-iconic/font/css/open-iconic-bootstrap.min.css');

html, body {
    font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
}

a, .btn-link {
    color: #0366d6;
}

.btn-primary {
    color: #fff;
    background-color: #1b6ec2;
    border-color: #1861ac;
}

app {
    position: relative;
    display: flex;
    flex-direction: column;
}

.top-row {
    height: 3.5rem;
    display: flex;
    align-items: center;
}

.main {
    flex: 1;
}

    .main .top-row {
        background-color: #f7f7f7;
        border-bottom: 1px solid #d6d5d5;
        justify-content: flex-end;
    }

        .main .top-row > a, .main .top-row .btn-link {
            white-space: nowrap;
            margin-left: 1.5rem;
        }

.main .top-row a:first-child {
    overflow: hidden;
    text-overflow: ellipsis;
}

.sidebar {
    background-image: linear-gradient(180deg, rgb(5, 39, 103) 0%, #3a0647 70%);
}

    .sidebar .top-row {
        background-color: rgba(0,0,0,0.4);
    }

    .sidebar .navbar-brand {
        font-size: 1.1rem;
    }

    .sidebar .oi {
        width: 2rem;
        font-size: 1.1rem;
        vertical-align: text-top;
        top: -2px;
    }

    .sidebar .nav-item {
        font-size: 0.9rem;
        padding-bottom: 0.5rem;
    }

        .sidebar .nav-item:first-of-type {
            padding-top: 1rem;
        }

        .sidebar .nav-item:last-of-type {
            padding-bottom: 1rem;
        }

        .sidebar .nav-item a {
            color: #d7d7d7;
            border-radius: 4px;
            height: 3rem;
            display: flex;
            align-items: center;
            line-height: 3rem;
        }

            .sidebar .nav-item a.active {
                background-color: rgba(255,255,255,0.25);
                color: white;
            }

            .sidebar .nav-item a:hover {
                background-color: rgba(255,255,255,0.1);
                color: white;
            }

.content {
    padding-top: 1.1rem;
}

.navbar-toggler {
    background-color: rgba(255, 255, 255, 0.1);
}

.valid.modified:not([type=checkbox]) {
    outline: 1px solid #26b050;
}

.invalid {
    outline: 1px solid red;
}

.validation-message {
    color: red;
}

#blazor-error-ui {
    background: lightyellow;
    bottom: 0;
    box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
    display: none;
    left: 0;
    padding: 0.6rem 1.25rem 0.7rem 1.25rem;
    position: fixed;
    width: 100%;
    z-index: 1000;
}

#blazor-error-ui .dismiss {
    cursor: pointer;
    position: absolute;
    right: 0.75rem;
    top: 0.5rem;
}

@media (max-width: 767.98px) {
    .main .top-row:not(.auth) {
        display: none;
    }

    .main .top-row.auth {
        justify-content: space-between;
    }

    .main .top-row a, .main .top-row .btn-link {
        margin-left: 0;
    }
}

@media (min-width: 768px) {
    app {
        flex-direction: row;
    }

    .sidebar {
        width: 250px;
        height: 100vh;
        position: sticky;
        top: 0;
    }

    .main .top-row {
        position: sticky;
        top: 0;
    }

    .main > div {
        padding-left: 2rem !important;
        padding-right: 1.5rem !important;
    }

    .navbar-toggler {
        display: none;
    }

    .sidebar .collapse {
        /* Never collapse the sidebar for wide screens */
        display: block;
    }
}


text:
[Open Iconic v1.1.1](http://useiconic.com/open)
===========

### Open Iconic is the open source sibling of [Iconic](http://useiconic.com). It is a hyper-legible collection of 223 icons with a tiny footprint—ready to use with Bootstrap and Foundation. [View the collection](http://useiconic.com/open#icons)

## What's in Open Iconic?

* 223 icons designed to be legible down to 8 pixels
* Super-light SVG files - 61.8 for the entire set
* SVG sprite—the modern replacement for icon fonts
* Webfont (EOT, OTF, SVG, TTF, WOFF), PNG and WebP formats
* Webfont stylesheets (including versions for Bootstrap and Foundation) in CSS, LESS, SCSS and Stylus formats
* PNG and WebP raster images in 8px, 16px, 24px, 32px, 48px and 64px.

## Getting Started

#### For code samples and everything else you need to get started with Open Iconic, check out our [Icons](http://useiconic.com/open#icons) and [Reference](http://useiconic.com/open#reference) sections.

### General Usage

#### Using Open Iconic's SVGs

We like SVGs and we think they're the way to display icons on the web. Since Open Iconic are just basic SVGs, we suggest you display them like you would any other image (don't forget the `alt` attribute).

```
<img src="/open-iconic/svg/icon-name.svg" alt="icon name">
```

#### Using Open Iconic's SVG Sprite

Open Iconic also comes in a SVG sprite which allows you to display all the icons in the set with a single request. It's like an icon font, without being a hack.

Adding an icon from an SVG sprite is a little different than what you're used to, but it's still a piece of cake. *Tip: To make your icons easily style able, we suggest adding a general class to the* `<svg>` *tag and a unique class name for each different icon in the* `<use>` *tag.*

```
<svg class="icon">
  <use xlink:href="open-iconic.svg#account-login" class="icon-account-login"></use>
</svg>
```

Sizing icons only needs basic CSS. All the icons are in a square format, so just set the `<svg>` tag with equal width and height dimensions.

```
.icon {
  width: 16px;
  height: 16px;
}
```

Coloring icons is even easier. All you need to do is set the `fill` rule on the `<use>` tag.

```
.icon-account-login {
  fill: #f00;
}
```

To learn more about SVG Sprites, read [Chris Coyier's guide](http://css-tricks.com/svg-sprites-use-better-icon-fonts/).

#### Using Open Iconic's Icon Font...

##### …with Bootstrap

You can find our Bootstrap stylesheets in `font/css/open-iconic-bootstrap.{css, less, scss, styl}`

```
<link href="/open-iconic/font/css/open-iconic-bootstrap.css" rel="stylesheet">
```

```
<span class="oi oi-icon-name" title="icon name" aria-hidden="true"></span>
```

##### …with Foundation

You can find our Foundation stylesheets in `font/css/open-iconic-foundation.{css, less, scss, styl}`

```
<link href="/open-iconic/font/css/open-iconic-foundation.css" rel="stylesheet">
```

```
<span class="fi-icon-name" title="icon name" aria-hidden="true"></span>
```

##### …on its own

You can find our default stylesheets in `font/css/open-iconic.{css, less, scss, styl}`

```
<link href="/open-iconic/font/css/open-iconic.css" rel="stylesheet">
```

```
<span class="oi" data-glyph="icon-name" title="icon name" aria-hidden="true"></span>
```

## License

### Icons

All code (including SVG markup) is under the [MIT License](http://opensource.org/licenses/MIT).

### Fonts

All fonts are under the [SIL Licensed](http://scripts.sil.org/cms/scripts/page.php?item_id=OFL_web).

repo_name: Swimburger/BlazorGitHubPagesDemo

repo_language: HTML

mime_type: text/html


summary: Freezing

summary: Bracing

summary: Freezing

summary: Balmy

summary: Chilly


text:
@page "/"

Hello, world!

Welcome to your new app.

<SurveyPrompt Title="How is Blazor working for you?" />


text:
@page "/counter"

Counter

Current count: @currentCount

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>

@code {
    private int currentCount = 0;

    private void IncrementCount()
    {
        currentCount++;
    }
}


text:
@page "/fetchdata"
@inject HttpClient Http

Weather forecast

This component demonstrates fetching data from the server.

@if (forecasts == null)
{

Loading...

}
else
{

                Date
                Temp. (C)
                Temp. (F)
                Summary

            @foreach (var forecast in forecasts)
            {

                    @forecast.Date.ToShortDateString()
                    @forecast.TemperatureC
                    @forecast.TemperatureF
                    @forecast.Summary

            }

}

@code {
    private WeatherForecast[] forecasts;

    protected override async Task OnInitializedAsync()
    {
        forecasts = await Http.GetFromJsonAsync<WeatherForecast[]>("sample-data/weather.json");
    }

    public class WeatherForecast
    {
        public DateTime Date { get; set; }

        public int TemperatureC { get; set; }

        public string Summary { get; set; }

        public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
    }
}


text:
  This repo is sponsored by GuidedHacking.com!

# [The Ultimate Online Game Hacking Resource](https://github.com/dsasmblr/hacking-online-games/)
**A curated list of tutorials/resources for hacking online games!**

From dissecting game clients to cracking network packet encryption, this is a go-to reference for those interested in the topic of hacking online games. I'll be updating this list whenever I run across excellent resources, so be sure to Watch/Star it! If you know of an excellent resource that isn't yet on the list, feel free to submit it for consideration via creating an issue or pull request for this repository, or [email it to me](mailto:dsasmblr@gmail.com).

### General Information

Title/Link | Description
---- | ----
[EFF FAQ on Reverse Engineering Legalities](https://www.eff.org/issues/coders/reverse-engineering-faq) | This FAQ details information that may help reverse engineers reduce their legal risk. *Use this information as a guide, not actual legal advice.*
[Cheating in Online Games: Overview of Approaches and Consequences](https://en.wikipedia.org/wiki/Cheating_in_online_games) | This Wikipedia page offers a good 10,000-foot view of the landscape of hacking online games.

### Blog Posts, Articles, and Presentations

Title/Link | Description
---- | ----
[Hack.lu 2017: (Workshop) Reverse Engineering a MMORPG](https://www.slideshare.net/AntoninBeaujeant/reverse-engineering-a-mmorpg) | This workshop covers the basics of reverse engineering a (M)MORPG. The target is [Pwn Adventure 3](http://www.pwnadventure.com/), an intentionally-vulnerable MMORPG developed by [Vector35](https://vector35.com/).
[Hack the Vote 2016 CTF "The Wall" Solution](https://zerosum0x0.blogspot.com/2016/11/hack-vote-wall-solution.html) | A write-up for a 2016 CTF challenge involving the multiplayer, open source Minecraft clone, Minetest.
[Reverse Engineering Online Games - Dragomon Hunter](http://0xbaadf00dsec.blogspot.com/2016/01/reverse-engineering-online-games.html) | An in-depth tutorial showing how to reverse engineer online games via the game *Dragomon Hunter*.
[Hacking/Exploiting/Cheating in Online Games (PDF)](https://zdresearch.com/wp-content/uploads/2013/04/Exploiting-Online-Games.pdf) | A presentation from 2013 that delves deeply into hacking online games, from defining terminology to providing code examples of specific hacks.
[Hacking Online Games](https://www2.cs.arizona.edu/~collberg/Teaching/466-566/2012/Resources/presentations/2012/topic4-final/slides.pdf) | A presentation from 2012 discussing various aspects of hacking online games.
[For 20 Years, This Man Has Survived Entirely by Hacking Online Games](https://motherboard.vice.com/en_us/article/59p7qd/this-man-has-survived-by-hacking-mmo-online-games) | A hacker says he turned finding and exploiting flaws in popular MMO video games into a lucrative, full-time, job.
[Hackers in Multiplayer Games](https://www.reddit.com/r/gamedev/comments/3ykg77/hackers_in_multiplayer_games/?st=j6p8fdyy&sh=61b63df4) | A Reddit post discussing hacking in multiplayer games.
[Reverse Engineering Network Protocols](https://www.reddit.com/r/ReverseEngineering/comments/yru6p/reverse_engineering_network_protocols/c5yijpt/?st=j6p93sze&sh=c88f98eb) | A very helpful comment from a Reddit post inquiring about reversing network protocols.
[Deciphering MMORPG Protocol Encoding](https://stackoverflow.com/questions/539812/deciphering-mmorpg-protocol-encoding) | An informative discussion from a question on Stack Overflow.
[Reverse Engineering of a Packet Encryption Function of a Game](https://reverseengineering.stackexchange.com/questions/8816/reverse-engineering-of-a-packet-encryption-function-of-a-game) | An informative discussion from a question on StackExchange.
[Fuzzing Online Games](https://www.elie.net/static/files/fuzzing-online-games/fuzzing-online-games-slides.pdf) | This is the slide deck used for the DEFCON 20 talk linked in the videos section below. [Click here](https://www.elie.net/talk/fuzzing-online-games) for the main presentation page.
[Kartograph (Game Hacking Tool)](https://www.elie.net/static/files/kartograph/kartograph-slides.pdf) | This is the slide deck used for the DEFCON 18 talk linked in the videos section below. [Click here](https://www.elie.net/talk/kartograph) for the main presentation page, and [click here](https://www.elie.net/static/files/openconflict-preventing-real-time-map-hacks-in-online-games/openconflict-preventing-real-time-map-hacks-in-online-games-slides.pdf) for an extended version of this slide deck [[Back-up Link](http://crypto.stanford.edu/~dabo/pubs/papers/onlinegames.pdf)].
[Adding Multiplayer Functionality to Torchlight (A Single-Player, Closed-Source Game)](https://github.com/dsasmblr/hacking-online-games/blob/master/resources/Extending_a_Closed_-_Source_Game_with_Multiplayer.pdf) | Torchlight is chosen as a real-world target application for adding multiplayer functionality to the otherwise single-player, closed-source game.
[Exploiting Game Engines for Fun and Profit](http://revuln.com/files/Ferrante_Auriemma_Exploiting_Game_Engines.pdf) | This slide deck shows you methods to exploit game engines, effictively discovering attack vectors that will work across multiple games using the same engine.
[How to Hack an MMO](https://www.raphkoster.com/2008/04/17/how-to-hack-an-mmo/) | This is an old article, but a good cursory overview of some of what's involved in attacking an MMO game client.
[Introduction to Server Side Emulation](https://github.com/dsasmblr/hacking-online-games/blob/master/resources/Introduction%20to%20Server%20Side%20Emulation.pdf) | An old but still relevant document for those interested in building their own emulated server (useful for things like reintroducing multiplayer functionality into a dead game).
[Reversing Path of Exile's Protocol](https://www.reddit.com/r/REGames/comments/8j8fc2/reversing_path_of_exiles_protocol/) | A three-part series of blog posts detailing one individual's approach to reverse engineering Path of Exile's network protocol).

### Videos

Title/Link | Description
---- | ----
[How to Hack Local Values in Browser-Based Games with Cheat Engine](https://www.youtube.com/watch?v=f_axmYpG1Lk) | This video teaches you how to find and change local values (which might appear as server-based values) in browser-based games.
[Reverse-Engineering a Proprietary Game Server with Erlang](https://www.youtube.com/watch?v=DumXgoFrMdU) | This talk details advantages Erlang has over other languages for reverse engineering protocols and analyzing client files. A live demo showcasing some of these tools and techniques is also given.
[DEF CON 16: Gaming - The Next Overlooked Security Hole](https://www.youtube.com/watch?v=pqWmFkMFzaU) | This talk discusses the growing number of attack vectors presenting themselves in the form of games, from engines to mods to middleware and more.
[DEF CON 17: Fragging Game Servers](https://www.youtube.com/watch?v=bRM4J-LphUw) | From hardware interaction to network protocols, this talk presents the inner workings of the Source Dedicated Server (used for games like *Left 4 Dead* and *Team Fortress 2*). Also discussed are some of the weaknesses in these game engines, as well as ways they're exploited in the wild.
[DEF CON 17: Subverting the World Of Warcraft API](https://www.youtube.com/watch?v=EnmoI2dRwX4) | This talk discusses MMO hacks related to the World of Warcraft API.
[DEF CON 18: Securing MMOs - A Security Professional's View from the Inside](https://www.youtube.com/watch?v=9IGvIexJSFU) | Gold farmers. Cheaters. Beleaguered programmers. All ingredients in a recipe for an unstable, fun-sapping game. This talk takes a look at the security problems plaguing the MMO industry and how modern engineers are taking the fight to cheaters and hackers in MMOs.
[DEF CON 18: Kartograph - Applying Reverse Engineering Techniques to Map Hacking](https://www.youtube.com/watch?v=WDNY4DMx8Jc) | Using games like Civilization IV, Age of Empires III, and Anno as targets, this talk teaches memory forensic techniques you can use to hack online games. Be sure to watch the accompanying [Kartograph demo video](https://www.youtube.com/watch?v=mFprkIAeKgM).
[DEF CON 19: Hacking MMORPGs for Fun and Mostly Profit](https://www.youtube.com/watch?v=hABj_mrP-no) | This talk presents a pragmatic view of both threats and defenses in relation to hacking online games.
[DEF CON 20: Fuzzing Online Games](https://www.youtube.com/watch?v=r0UQ6bpKOX0) | This talk discusses interesting techniques you can consider using to fuzz online games.
[DEF CON 23: Shall We Play A Game](https://www.youtube.com/watch?v=XxyRDkmNMHg) | This talk shows how playing on custom game servers and community-created maps could easily lead to exploitive code execution on our machines that bypass mitigation techniques. Targets include CryEngine 3, Dota 2, Garry's Mod, ARMA3 and Digital Combat Simulator.
[DEF CON 25 - Twenty Years of MMORPG Hacking: Better Graphics, Same Exploits](https://media.defcon.org/DEF%20CON%2025/DEF%20CON%2025%20video%20and%20slides/DEF%20CON%2025%20-%20Manfred%20-%20Twenty%20Years%20of%20MMORPG%20Hacking-%20Better%20Graphics%20and%20Same%20Exploits.mp4) | This presentation, presented by Manfred, technically analyzes some of the virtual economy-devastating, low-hanging-fruit exploits that are common in nearly every MMORPG released to date.
[Motherboard Livestream Archive: Researcher Cracks Elder Scrolls Online, Dark Age of Camelot, and Wildstar](https://www.youtube.com/watch?v=iYTCBPUn98c) | Adrian Bednarek, better known as "Manfred", demonstrates the MMORPG hacks he wanted to show but couldn't during his DEF CON 25 presentation. This is a rare glimpse into the tools, thoughts, and approaches of a professional online game hacker!
[Black Hat Europe 2014 - Next Level Cheating and Leveling Up Mitigations](https://www.youtube.com/watch?v=bsYxcpz3w8A) | This presentation outlines two practical attacks against one of the most popular anti-cheat engines and demonstrates the implications of a successful attack against anti-cheat software.
[Cyber Necromancy - Reverse Engineering Dead Protocols](https://media.ccc.de/v/31c3_-_5956_-_en_-_saal_2_-_201412281400_-_cyber_necromancy_-_joseph_tartaro_-_matthew_halchyshak) | This presentation talks about bringing a multiplayer game whose servers have shut down, back to life. The game is Metal Gear Online on the PS2 and PS3.
[32C3 - How Hackers Grind an MMORPG: By Taking it Apart!](https://www.youtube.com/watch?v=9pCb0vIp_kg) | In this presentation, Runes of Magic, a long-dead MMORPG, is used to demonstrate how to reverse engineer network protocols.
[ARMA 3 - Reverse Engineering on IDA Pro & Reclass 2015](https://www.youtube.com/watch?v=dIBdJUaOuWE) | A 45-minute tutorial demonstrating how to hack ARMA 3 using IDA Pro and ReClass.
[Let's Play/Hack - Pwn Adventure 3: Pwnie Island](https://www.youtube.com/watch?v=RDZnlcnmPUA&list=PLhixgUqwRTjzzBeFSHXrw9DnQtssdAwgG) | A video series of 21 parts on hacking the intentionally vulnerable MMORPG [Pwn Adventure 3](http://www.pwnadventure.com/).

### Podcasts/Audio

Title/Link | Description
---- | ----
[Darknet Diaries Ep. 7: Manfred Part 1: Hacking Online Video Games for Fun](https://darknetdiaries.com/episode/7/) | "Manfred" has privately been hacking online games for the past 20 years. In this episode, he tells stories of some of the unbelievable ways he's hacked games--all in the name of fun.
[Darknet Diaries Ep. 8: Manfred Part 2: Hacking Online Video Games for Profit](https://darknetdiaries.com/episode/8/) | "Manfred" found a way to turn his passion for video games and reverse engineering into a full time business. He exploited video games and sold virtual goods and currency for real money. This was his full time job. In this episode, he explains exactly how he did this.

### Books

Title/Link | Description
---- | ----
[Game Hacking](https://www.nostarch.com/gamehacking) | *Game Hacking* shows programmers how to dissect computer games and create bots.
[Attacking Network Protocols](https://www.nostarch.com/networkprotocols) | *Attacking Network Protocols* is a deep-dive into network vulnerability discovery.
[Practical Packet Analysis, 3rd Edition](https://www.nostarch.com/packetanalysis3) | *Practical Packet Analysis, 3rd Ed.* teaches you how to use Wireshark for packet capture and analysis.
[Exploiting Online Games: Cheating Massively Distributed Systems](https://www.amazon.com/Exploiting-Online-Games-Massively-Distributed/dp/0132271915/) | This book takes a close look at security problems associated with advanced, massively distributed software in relation to video games.

### Online Game Hacking Forums

Title/Link | Description
---- | ----
[Guided Hacking](https://guidedhacking.com/) | Discussion of multiplayer and single-player game hacks and cheats.
[UnKnoWnCheaTs Forum](https://unknowncheats.me/) | Discussion of multiplayer game hacks and cheats.
[MPGH (Multi-Player Game Hacking) Forum](http://www.mpgh.net) | Discussion of multiplayer game hacks and cheats.
[ElitePVPers](https://www.elitepvpers.com/) | Discussion of MMO hacks, bots, cheats, guides and more.
[OwnedCore](http://www.ownedcore.com/) | An MMO gaming community for guides, exploits, trading, hacks, model editing, emulation servers, programs, bots and more.

### Open Source and Safe-to-Hack Multiplayer Games

Title/Link | Description
---- | ----
[Pwn Adventure 2](http://ghostintheshellcode.com/#pwnadventure2) | A custom 3D MMOFPS based on the Unity game engine. The game includes several quests that are only solvable by modifying the game client.
[Pwn Adventure 3: Pwnie Island](http://pwnadventure.com/) | A first-person, open-world MMORPG developed specifically to be hacked! You might also be interested in [Pwn Adventure 2](http://ghostintheshellcode.com/#pwnadventure2), which is Unity-based.
[Minetest](http://www.minetest.net/) | An open source, multiplayer voxel-based game and game engine. (A Minecraft clone, basically.)
[Xonotic](http://www.xonotic.org/) | An open source, arena-style multiplayer FPS.
[Nexuiz](http://www.alientrap.com/games/nexuiz/) | The open source, multiplayer FPS game Xonotic is based on.
[AssaultCube](https://assault.cubers.net/) | An open source, multiplayer, FPS.
[List of Open Source Games](https://en.wikipedia.org/wiki/List_of_open-source_video_games) | A large list on Wikipedia of open source games, both single-player and multiplayer.

repo_name: dsasmblr/hacking-online-games


text:
# Nevergreen

## About

Nevergreen is a Powershell module that returns the latest version and download links for various Windows applications.

It can be used as an alternative to the excellent [Evergreen](https://github.com/aaronparker/Evergreen) module, for apps that project does not support, or where it might not return the results you want.

Evergreen relies on API queries to obtain its data, and HTML scraping is not welcome. This is the reason Nevergreen was born, a place to accept all the Evergreen rejects! Please note this method is inherently more prone to breaking when websites are changed, hence the name!

## Supported apps

- 7-Zip (Evergreen URLs return HTML files at present and version is not the latest)
- 8x8 Work
- Adobe/Harman AIR
- Adobe Creative Cloud
- Adobe Acrobat Reader / Pro
  - MSP update patches only
  - Evergreen does not always report the latest optional releases, whereas this implementation should.
- Advanced Installer
- Advanced IP Scanner
- Advanced Port Scanner
- Anaconda
- Apple iTunes
- AutoIt
- Cisco Webex
- Cisco Webex Access Anywhere
- Cisco Webex Support Manager
- Citrix ShareFile
- Druide Antidote
- Eclipse Temeru Runtime (AKA AdoptOpenJDK Hotspot)
- FileOpen Plugin
- Fujifilm Pixel Shift Combiner
- Fujifilm Raw File Converter EX
- Fujifilm X Acquire
- Fujifilm X Raw Studio
- Fujifilm X Webcam
- Google Drive
- Google Earth Pro
- IBM Semeru Runtime (AKA AdoptOpenJDK OpenJ9)
- IGEL Universal Management Suite
- Jabra Direct
- Komodo Labs NEWT Professional
- Komodo Labs Slitheris
- Lenovo Commercial Vantage
- LibreOffice / LibreOfficeHelp
- Logitech Camera Setings
- LSoft Active Disk Image Lite
- LSoft Active Boot Disk
- Microsoft Azure CLI
- Microsoft Azure Information Protection UL Client
- Microsoft OpenJDK
- Microsoft Power BI Desktop
- Microsoft Power BI Report Builder
- Microsoft SSMS
  - This is already in Evergreen but has a known issue against it where the feed is providing the build version rather than the release version most know it by.
- Microsoft Sysinternals tools (all suites and individual tools)
- Microsoft Windows ADK
- Mimecast for Outlook
- Miniconda
- nmap
- Npcap
- Opera
- OpenVPN Community
- OpenVPN Connect
- Philippe Jounin Tftpd64
- PingIdentity PingID
- Python
- QGIS
- Radio Detection CAT Manager
- Redstor Backup Pro Storage Platform Console
- RIA eID
- TMurgent AppVDefConGroups
- TMurgent AppVManage
- TMurgent AppVManifestEditor
- TMurgent PsfTooling
- TMurgent PullApps
- TMurgent TMEdit
- TMurgent TMEditX
- Zebra Card Studio
- Zoom VDI
  - This is already in Evergreen but the VDI downloads just return the version as 'Latest'

The [Apps folder in the main branch](https://github.com/DanGough/Nevergreen/tree/main/Nevergreen/Apps) will always show the apps supported in the latest release.

Also, you can check the [latest commits to the Apps folder in the dev branch](https://github.com/DanGough/Nevergreen/commits/dev/Nevergreen/Apps) to see what's being worked on.

## Bugs

Because these apps rely on HTML scraping, they are prone to breakage when the websites are changed. If you encounter an issue, please file a report under the [Issues](https://github.com/DanGough/Nevergreen/issues) tab.

Fix contributions are also welcomed - fork the repository, create the fix in a new branch in your copy, then create a pull request for me to review. If you're not familiar with Git, just post the fixed code directly within the issue.

## Requests

If you have a request to add an application to Nevergreen, please abide by the following:

- If the app has a queryable API feed to obtain the latest version, it is better suited for inclusion in [Evergreen](https://github.com/aaronparker/Evergreen). It can be hard to find these API feeds, but if for example the app in question is hosted on Github, Evergreen has built-in functions for getting those apps easily.

- Please check the [New Apps](https://github.com/DanGough/Nevergreen/projects/1) area under the [Projects](https://github.com/DanGough/Nevergreen/projects) tab to see if the app is already on the to-do list.

- If it is not, you are welcome to add a request via the [Issues](https://github.com/DanGough/Nevergreen/issues) tab. Please include any helpful information such as the URLs for the download page and release notes if possible.

## Supported Powershell Versions

This has been tested with Powershell 5.1 and 7.1.3, and the module manifests lists the minimum supported version as 5.1. It may work on 3.0, but it has never been tested.

## Installation

### Powershell Gallery

Simply install directly from the [Powershell Gallery](https://www.powershellgallery.com/packages/Nevergreen) by running the following command:

```powershell
Install-Module -Name Nevergreen
```

To update:
```powershell
Update-Module -Name Nevergreen
```

### Manual Installation

Download the latest Main branch, either by downloading the zip file directly from Github, or by installing [Git](https://git-scm.com/downloads) and typing:

```
git clone https://github.com/DanGough/Nevergreen.git
```

If you downloaded and extracted a zip file, you may need to unblock the files first:
```powershell
Get-ChildItem -Path <path> -Recurse | Unblock-File
```

Then from within the Nevergreen folder, run the following command to temporarily import the module into your session:

```powershell
Import-Module .\Nevergreen\Nevergreen.psd1
```

You can also copy it to one of the folders listed under `$env:PSModulePath` to make it available in all future sessions without having to import it.

## Usage

List all supported apps:
```powershell
Find-NevergreenApp
```

List all Adobe and Microsoft apps (accepts arrays and uses a RegEx match):
```powershell
Find-NevergreenApp -Name Adobe,Microsoft
```

Get version and download links for Microsoft Power BI Desktop (all platforms):
```powershell
Get-NevergreenApp -Name MicrosoftPowerBIDesktop
```

Get version and download links for Microsoft Power BI Desktop (64-bit only):
```powershell
Get-NevergreenApp -Name MicrosoftPowerBIDesktop | Where-Object {$_.Architecture -eq 'x64'}
```

Combine both commands to get all results!
```powershell
Find-NevergreenApp | Get-NevergreenApp
```

repo_name: DanGough/Nevergreen

repo_language: PowerShell

mime_type: text/plain


text:
{
    // When enabled, will trim trailing whitespace when you save a file.
    "files.trimTrailingWhitespace": true
}


text:
// Available variables which can be used inside of strings.
// ${workspaceRoot}: the root folder of the team
// ${file}: the current opened file
// ${relativeFile}: the current opened file relative to workspaceRoot
// ${fileBasename}: the current opened file's basename
// ${fileDirname}: the current opened file's dirname
// ${fileExtname}: the current opened file's extension
// ${cwd}: the current working directory of the spawned process
{
    // See https://go.microsoft.com/fwlink/?LinkId=733558
    // for the documentation about the tasks.json format
	"version": "2.0.0",

    // Start PowerShell
    "windows": {
        "command": "${env:windir}/System32/WindowsPowerShell/v1.0/powershell.exe",
        //"command": "${env:ProgramFiles}/PowerShell/6.0.0/powershell.exe",
        "args": [ "-NoProfile", "-ExecutionPolicy", "Bypass" ]
    },
    "linux": {
        "command": "/usr/bin/powershell",
        "args": [ "-NoProfile" ]
    },
    "osx": {
        "command": "/usr/local/bin/powershell",
        "args": [ "-NoProfile" ]
    },

    // Associate with test task runner
    "tasks": [
        {
            "taskName": "Test",
            "suppressTaskName": true,
            "isTestCommand": true,
            "args": [
                "Write-Host 'Invoking Pester...'; $ProgressPreference = 'SilentlyContinue'; Invoke-Pester -Script test -PesterOption @{IncludeVSCodeMarker=$true};",
                "Invoke-Command { Write-Host 'Completed Test task in task runner.' }"
            ],
            "problemMatcher": "$pester"
        }
	]
}


text:
$PSModulePath = [System.IO.Path]::Combine((Split-Path -Path $PSScriptRoot -Parent), 'Nevergreen')
$ModuleManifestPath = [System.IO.Path]::Combine($PSModulePath, 'Nevergreen.psd1')

Describe 'Module Manifest Tests' {
    It 'Passes Test-ModuleManifest' {
        Test-ModuleManifest -Path $ModuleManifestPath | Should -Not -BeNullOrEmpty
        $? | Should -Be $true
    }
}


text:
. "$PSScriptRoot\ImportFunctions.ps1"
Start-Transcript -Path "$env:temp\Nevergreen.log" -Force
Clear-Host
Write-Host "PowerShell version: $($PSVersionTable.PSVersion)"
Find-NevergreenApp | Get-NevergreenApp
Stop-Transcript


text:
# For quickly dot-sourcing all functions into current session for testing

$Public = @(Get-ChildItem -Path ([System.IO.Path]::Combine($PSScriptRoot, '..\Nevergreen\Public', '*.ps1')))
$Private = @(Get-ChildItem -Path ([System.IO.Path]::Combine($PSScriptRoot, '..\Nevergreen\Private', '*.ps1')) -ErrorAction Ignore)

ForEach ($Import in @($Public + $Private)) {
    Try {
        . $Import.FullName
    }
    Catch {
        Write-Error -Message "Failed to import function $($Import.FullName): $_"
    }
}


text:
$Public = @(Get-ChildItem -Path ([System.IO.Path]::Combine($PSScriptRoot, 'Public', '*.ps1')))
$Private = @(Get-ChildItem -Path ([System.IO.Path]::Combine($PSScriptRoot, 'Private', '*.ps1')) -ErrorAction Ignore)

ForEach ($Import in @($Public + $Private)) {
    Try {
        . $Import.FullName
    }
    Catch {
        Write-Error -Message "Failed to import function $($Import.FullName): $_"
    }
}

Export-ModuleMember -Function $Public.Basename


text:
# Module manifest for module 'Nevergreen'
# Generated by: Dan Gough
# Last updated: 10/08/2023

@{

# Script module or binary module file associated with this manifest.
RootModule = 'Nevergreen.psm1'

# Version number of this module.
ModuleVersion = '2308.1'

# Supported PSEditions
CompatiblePSEditions = @('Desktop', 'Core')

# ID used to uniquely identify this module
GUID = '499e0a34-0e61-493d-9818-7507317e7536'

# Author of this module
Author = 'Dan Gough'

# Company or vendor of this module
CompanyName = 'Dan Gough'

# Copyright statement for this module
Copyright = '(c) Dan Gough. All rights reserved.'

# Description of the functionality provided by this module
Description = 'This module is an alternative to Evergreen, and allows you to find the latest version and download URL for various Windows apps. Evergreen uses API queries to obtain its data whereas this module is more focussed on web scraping. This is more prone to breaking when websites are changed, hence the name!'

# Minimum version of the PowerShell engine required by this module
PowerShellVersion = '5.1'

# Name of the PowerShell host required by this module
# PowerShellHostName = ''

# Minimum version of the PowerShell host required by this module
# PowerShellHostVersion = ''

# Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only.
# DotNetFrameworkVersion = ''

# Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only.
# ClrVersion = ''

# Processor architecture (None, X86, Amd64) required by this module
# ProcessorArchitecture = ''

# Modules that must be imported into the global environment prior to importing this module
# RequiredModules = @()

# Assemblies that must be loaded prior to importing this module
# RequiredAssemblies = @()

# Script files (.ps1) that are run in the caller's environment prior to importing this module.
# ScriptsToProcess = @()

# Type files (.ps1xml) to be loaded when importing this module
# TypesToProcess = @()

# Format files (.ps1xml) to be loaded when importing this module
# FormatsToProcess = @()

# Modules to import as nested modules of the module specified in RootModule/ModuleToProcess
# NestedModules = @()

# Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export.
FunctionsToExport = @('Find-NevergreenApp', 'Get-NevergreenApp')

# Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export.
CmdletsToExport = @()

# Variables to export from this module
VariablesToExport = @()

# Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export.
AliasesToExport = @()

# DSC resources to export from this module
DscResourcesToExport = @()

# List of all modules packaged with this module
# ModuleList = @()

# List of all files packaged with this module
# FileList = @()

# Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell.
PrivateData = @{

    PSData = @{

        # Tags applied to this module. These help with module discovery in online galleries.
        Tags = @('Evergreen')

        # A URL to the license for this module.
        LicenseUri = 'https://github.com/DanGough/Nevergreen/blob/main/LICENSE'

        # A URL to the main website for this project.
        ProjectUri = 'https://github.com/DanGough/Nevergreen'

        # A URL to an icon representing this module.
        # IconUri = ''

        # ReleaseNotes of this module
        ReleaseNotes = 'https://github.com/DanGough/Nevergreen/releases'

        # Prerelease string of this module
        # Prerelease = ''

        # Flag to indicate whether the module requires explicit user acceptance for install/update/save
        # RequireLicenseAcceptance = $false

        # External dependent modules of this module
        # ExternalModuleDependencies = @()

    } # End of PSData hashtable

} # End of PrivateData hashtable

# HelpInfo URI of this module
# HelpInfoURI = ''

# Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix.
# DefaultCommandPrefix = ''

}


text:
$Version = Get-Version -Uri 'https://www.radiodetection.com/en-gb/resources/software-downloads/cat4-manager' -Pattern 'Version: ((?:\d+\.)+\d+)'

$URL32 = Get-Link -Uri 'https://www.radiodetection.com/en-gb/resources/software-downloads/cat4-manager' -MatchProperty href -Pattern '\.zip'

New-NevergreenApp -Name 'Radio Detection CAT Manager' -Version $Version -Uri $URL32 -Architecture 'x86' -Type 'Zip'


text:
$URL32 = Get-Link -Uri 'https://www.advanced-port-scanner.com' -MatchProperty href -Pattern 'Advanced_Port_Scanner.+\.exe'
$Version = $URL32 | Get-Version

New-NevergreenApp -Name 'Advanced Port Scanner' -Version $Version -Uri $URL32 -Architecture 'x86' -Type 'Exe'


text:
$URL32 = Get-Link -Uri 'https://www.advanced-ip-scanner.com/download' -MatchProperty href -Pattern 'Advanced_IP_Scanner.+\.exe'
$Version = $URL32 | Get-Version

New-NevergreenApp -Name 'Advanced IP Scanner' -Version $Version -Uri $URL32 -Architecture 'x86' -Type 'Exe'


text:
$Apps = @(
    @{Name = 'K-Lite Codec Pack'; Channel ='Basic'; Architecture = 'Multi'; Type = 'Exe'; Uri = 'https://www.codecguide.com/download_k-lite_codec_pack_basic.htm' }
    @{Name = 'K-Lite Codec Pack'; Channel ='Standard'; Architecture = 'Multi'; Type = 'Exe'; Uri = 'https://www.codecguide.com/download_k-lite_codec_pack_standard.htm' }
    @{Name = 'K-Lite Codec Pack'; Channel ='Full'; Architecture = 'Multi'; Type = 'Exe'; Uri = 'https://www.codecguide.com/download_k-lite_codec_pack_full.htm' }
    @{Name = 'K-Lite Codec Pack'; Channel ='Mega'; Architecture = 'Multi'; Type = 'Exe'; Uri = 'https://www.codecguide.com/download_k-lite_codec_pack_mega.htm' }
)

foreach ($App in $Apps) {
    try {
        $Version = Get-Version -Uri $App.Uri -Pattern 'Version ((?:\d+\.)+\d+)'
        $URL = Get-Link -Uri $App.Uri -MatchProperty href -Pattern "\.$($App.Type)$"
        New-NevergreenApp -Name $App.Name -Version $Version -Uri $URL -Channel $App.Channel -Architecture $App.Architecture -Type $App.Type
    }
    catch {
        Write-Error "$($MyInvocation.MyCommand): Error querying '$($App.Uri)': $($_.Exception.Message)"
    }
}


text:
$Version = Get-Version -Uri 'https://openvpn.net/vpn-server-resources/openvpn-connect-for-windows-change-log/' -Pattern 'Release notes for ((?:\d+\.)+\d+)'

$Releases = @(
    @{Architecture = 'x86'; Type = 'Msi'; Pattern = 'x86\.msi$'}
    @{Architecture = 'x64'; Type = 'Msi'; Pattern = 'windows\.msi$'}
)

foreach ($Release in $Releases) {
        $URL = Get-Link -Uri 'https://openvpn.net/client-connect-vpn-for-windows/' -MatchProperty href -Pattern $Release.Pattern
        New-NevergreenApp -Name 'OpenVPNConnect' -Version $Version -Uri $URL -Architecture $Release.Architecture -Type $Release.Type
}


text:
$URL = Get-Link -Uri 'https://www.anaconda.com/products/individual' -MatchProperty href -Pattern '\.exe$'
$Version = $URL | Get-Version
New-NevergreenApp -Name 'Anaconda' -Version $Version -Uri $URL -Architecture 'x64' -Type 'exe'


text:
try {

    $URL = (Get-Link -Uri 'https://www.tmurgent.com/APPV/en/buy/tmeditx/tmeditx-download' -MatchProperty href -Pattern '\.msix$' -PrefixDomain | Resolve-Uri).Uri

    $Version = $URL | Get-Version

    New-NevergreenApp -Name 'TMurgent TMEditX' -Version $Version -Uri $URL -Architecture 'x86' -Type 'MSIX'

}
catch {
    Write-Error "$($MyInvocation.MyCommand): $($_.Exception.Message)"
}


text:
try {
    $ScriptURL = Get-Version -Uri 'https://support.lenovo.com/gb/en/solutions/hf003321-lenovo-vantage-for-enterprise' -Pattern '(/gb/en/api/v4/contents/cdn/\S+\.js)'
    $Version = Get-Version -Uri "https://support.lenovo.com$ScriptURL" -Pattern 'Version ((?:\d+\.)+\d+)'

    $URL32 = Get-Version -Uri "https://support.lenovo.com$ScriptURL" -Pattern 'href=\\"(https://.+LenovoCommercialVantage.+zip)'

    New-NevergreenApp -Name 'Lenovo Commercial Vantage' -Version $Version -Uri $URL32 -Architecture 'x86' -Type 'Zip'
}
catch {
    Write-Error "$($MyInvocation.MyCommand): $($_.Exception.Message)"
}


text:
$DownloadPageURL = ((Invoke-RestMethod -Uri 'https://support.logi.com/api/v2/help_center/en-gb/articles.json?label_names=webcontent=productdownload,websoftware=9bf6fc93-8e0b-11e9-a62b-cb4c7fb3c2e2,webos=windows-Windows-10' -DisableKeepAlive).articles | Where-Object title -EQ 'Camera Settings').html_url

$URL32 = Get-Link -Uri $DownloadPageURL -MatchProperty href -Pattern 'LogiCameraSettings.+\.exe'
$Version = $URL32 | Get-Version

New-NevergreenApp -Name 'Logitech Camera Settings' -Version $Version -Uri $URL32 -Architecture 'x86' -Type 'Exe'


text:
try {

    $Version = Get-Version -Uri 'https://fujifilm-x.com/global/support/download/software/pixel-shift-combiner/' -Pattern 'Windows Version: (?:Ver\.)?((?:\d+\.)+\d+)'

    $URL = Get-Link -Uri 'https://fujifilm-x.com/global/support/download/software/pixel-shift-combiner/' -MatchProperty href -Pattern '\.exe$'

    New-NevergreenApp -Name 'Fujifilm Pixel Shift Combiner' -Version $Version -Uri $URL -Architecture 'x64' -Type 'Exe'

}
catch {
    Write-Error "$($MyInvocation.MyCommand): $($_.Exception.Message)"
}


text:
$URL32 = (Resolve-Uri -Uri 'https://aka.ms/installazurecliwindows').Uri
$Version = $URL32 | Get-Version

New-NevergreenApp -Name 'Microsoft AzureCLI' -Version $Version -Uri $URL32 -Architecture 'x86' -Type 'Msi'


text:
$RetryCount = 3

for ($i = 0; $i -lt $RetryCount; $i++) {
    try {
        $Version = ((Invoke-WebRequest 'https://welcome.webex.com/sc3300/supportcenter/site/siteabout.do?siteurl=welcome' -DisableKeepAlive -UseBasicParsing -ErrorAction Stop).Content | Select-String -Pattern '(?:\d+\.)+(?:\d+)' -AllMatches).Matches.Groups.Value | Select-Object -Skip 1 -First 1
        $URL32 = Get-Link -Uri 'https://welcome.webex.com/sc3300/supportcenter/site/downloads.do?siteurl=welcome' -MatchProperty href -Pattern 'webexsc\.msi$'
        New-NevergreenApp -Name 'Cisco Webex Support Manager' -Version $Version -Uri $URL32 -Architecture 'x86' -Type 'Msi'
        break
    }
    catch {
        Write-Warning "Attempt $($i+1) failed, retrying..."
    }
}


text:
$Version = Get-Version -Uri 'https://www.autoitscript.com/site/autoit/downloads' -Pattern 'v((?:\d+\.)+\d+)'

$URL32 = (Get-Link -Uri 'https://www.autoitscript.com/site/autoit/downloads' -MatchProperty href -Pattern 'autoit-v.+-setup\.zip' -PrefixDomain | Resolve-Uri).Uri.Replace('.zip','.exe')

New-NevergreenApp -Name 'AutoIt' -Version $Version -Uri $URL32 -Architecture 'x86' -Type 'Exe'


text:
$Releases = @(
    @{Architecture = 'Multi'; Type = 'exe'; Pattern = '\.exe$' }
    @{Architecture = 'x64'; Type = 'msi'; Pattern = '64\.msi$' }
)

foreach ($Release in $Releases) {
    try {
        $URL = Get-Link -Uri 'https://plugin.fileopen.com/' -MatchProperty href -Pattern $Release.Pattern -PrefixDomain -ErrorAction Stop
        $Version = Get-Link -Uri 'https://plugin.fileopen.com/' -MatchProperty href -Pattern $Release.Pattern -ReturnProperty outerHTML -ErrorAction Stop | Get-Version -Pattern '\[(\d+(?:\.\d+)*)\]'
        New-NevergreenApp -Name 'FileOpen Plugin' -Version $Version -Uri $URL -Architecture $Release.Architecture -Type $Release.Type
    }
    catch {
        Write-Error "$($MyInvocation.MyCommand): $($_.Exception.Message)"
    }
}


text:
$Version = Get-Version -Uri 'https://www.microsoft.com/download/details.aspx?id=58494' -Pattern 'Version:<.+?>((?:\d+\.)+\d+)'
$URL32 = Get-Link -Uri 'https://www.microsoft.com/en-us/download/confirmation.aspx?id=58494' -MatchProperty href -Pattern 'PBIDesktopSetup\.exe$'
$URL64 = Get-Link -Uri 'https://www.microsoft.com/en-us/download/confirmation.aspx?id=58494' -MatchProperty href -Pattern 'PBIDesktopSetup_x64\.exe$'

New-NevergreenApp -Name 'Microsoft Power BI Desktop' -Version $Version -Uri $URL32 -Architecture 'x86' -Type 'Exe'
New-NevergreenApp -Name 'Microsoft Power BI Desktop' -Version $Version -Uri $URL64 -Architecture 'x64' -Type 'Exe'


text:
$URL = Get-Link -Uri 'https://support.8x8.com/cloud-phone-service/voice/work-desktop/download-8x8-work-for-desktop' -MatchProperty href -Pattern '\.msi'

$Version = $URL | Get-Version -Pattern '((?:\d+\.)+\d+)'

New-NevergreenApp -Name '8x8 Work' -Version $Version -Uri $URL -Architecture 'x64' -Type 'msi'


text:
try {

    $Version = Get-Link -Uri 'https://www.adobe.com/uk/solutions/ebook/digital-editions/download.html' -Headers @{"accept-language"="en-GB,en;q=0.9,en-US;q=0.8"} -MatchProperty href -Pattern '\.exe$' -ReturnProperty outerHTML | Get-Version -Pattern '>((?:\d+\.)+\d+)'

    $URL = Get-Link -Uri 'https://www.adobe.com/uk/solutions/ebook/digital-editions/download.html' -Headers @{"accept-language"="en-GB,en;q=0.9,en-US;q=0.8"} -MatchProperty href -Pattern '\.exe$'

    New-NevergreenApp -Name 'Adobe Digital Editions' -Version $Version -Uri $URL -Architecture 'x86' -Type 'Exe'

}
catch {
    Write-Error "$($MyInvocation.MyCommand): $($_.Exception.Message)"
}


text:
# Getting intermittent certificate errors from this URL. -SkipCertificateCheck on Invoke-WebRequest resolves it but that is PS7 only.
# Have seen up to 31 retries needed, so a 50 retry loop implemented!

$RetryCount = 50

for ($i = 0; $i -lt $RetryCount; $i++) {
    try {
        $Version = Get-Version -Uri 'https://www.jabra.com/Support/release-notes/release-note-jabra-direct' -Pattern '((?:\d+\.)+\d+)<br>' -ErrorAction Stop
        $URL = Get-Link -Uri 'https://www.jabra.com/software-and-services/jabra-direct' -MatchProperty href -Pattern '/Jabra.+\.exe$' -ErrorAction Stop
        New-NevergreenApp -Name 'Jabra Direct' -Version $Version -Uri $URL -Architecture 'Multi' -Type 'exe'
        return
    }
    catch {
        Write-Verbose "Attempt $($i+1) failed, retrying... $_"
    }
}
Write-Error $error[0]


text:
$DownloadPage = (Invoke-WebRequest -Uri 'https://developer.ibm.com/languages/java/semeru-runtimes/downloads' -DisableKeepAlive).Content

if ($DownloadPage -match 'let sourceDataJson = ([^;]+);') {
    $Downloads = (ConvertFrom-Json $matches[1]).Downloads | Where-Object os -EQ 'Windows'
}

foreach ($Download in $Downloads) {
    $Version = $Download.name | Get-Version
    New-NevergreenApp -Name "IBM Semeru Runtime JDK" -Version $Version -Uri $Download.jdk.opt1.downloadlink -Architecture $Download.arch -Type (Get-Culture).TextInfo.ToTitleCase($Download.jdk.opt1.displayName)
    New-NevergreenApp -Name "IBM Semeru Runtime JDK" -Version $Version -Uri $Download.jdk.opt2.downloadlink -Architecture $Download.arch -Type (Get-Culture).TextInfo.ToTitleCase($Download.jdk.opt2.displayName)
    New-NevergreenApp -Name "IBM Semeru Runtime JRE" -Version $Version -Uri $Download.jre.opt1.downloadlink -Architecture $Download.arch -Type (Get-Culture).TextInfo.ToTitleCase($Download.jre.opt1.displayName)
    New-NevergreenApp -Name "IBM Semeru Runtime JRE" -Version $Version -Uri $Download.jre.opt2.downloadlink -Architecture $Download.arch -Type (Get-Culture).TextInfo.ToTitleCase($Download.jre.opt2.displayName)
}


text:
$Apps = @(
    @{Name = 'Antidote'; Architecture = 'x86'; Type = 'Msp'; Pattern = 'Diff_Antidote_10_C_(?:\d+\.)+(?:\d+)\.msp$' }
    @{Name = 'Antidote French Module'; Architecture = 'x86'; Type = 'Msp'; Pattern = 'Diff_Antidote_10_Module_F_(?:\d+\.)+(?:\d+)\.msp$' }
    @{Name = 'Antidote English Module'; Architecture = 'x86'; Type = 'Msp'; Pattern = 'Diff_Antidote_10_Module_E_(?:\d+\.)+(?:\d+)\.msp$' }
    @{Name = 'Connectix'; Architecture = 'x86'; Type = 'Msp'; Pattern = 'Diff_Connectix_10_C_(?:\d+\.)+(?:\d+)\.msp$' }
)

foreach ($App in $Apps) {
    try {
        $URL = Get-Link -Uri 'https://www.antidote.info/fr/assistance/mises-a-jour/installation/antidote-10/windows' -MatchProperty href -Pattern $App.Pattern
        $Version = $URL  | Get-Version
        New-NevergreenApp -Name $App.Name -Version $Version -Uri $URL -Architecture $App.Architecture -Type $App.Type
    }
    catch {
        Write-Error "$($MyInvocation.MyCommand): $($_.Exception.Message)"
    }
}

    try {
        $URL = 'https://telechargement.druide.com/telecharger/Reseau/antidote_10/GestionnaireMultiposte_Antidote10.exe'
        New-NevergreenApp -Name 'Multi-User Manager' -Version $Version -Uri $URL -Architecture 'x86' -Type 'Exe'
    }
    catch {
        Write-Error "$($MyInvocation.MyCommand): $($_.Exception.Message)"
    }


text:
$Version = Get-Version -Uri 'https://www.komodolabs.com/product-downloads' -Pattern 'Slitheris Network Discovery v((?:\d+\.)+\d+)'

$URL32 = Get-Link -Uri 'https://www.komodolabs.com/product-downloads' -MatchProperty href -Pattern 'slitheris_installer\.exe$' -PrefixDomain

New-NevergreenApp -Name 'Komodo Labs Slitheris' -Version $Version -Uri $URL32 -Architecture 'x86' -Type 'Exe'


text:
$URL = Get-Link -Uri 'https://nmap.org/npcap/' -MatchProperty href -Pattern 'npcap-(?:\d+\.)+\d+\.exe$' -PrefixParent

$Version = $URL | Get-Version

New-NevergreenApp -Name 'Npcap' -Version $Version -Uri $URL -Architecture 'Multi' -Type 'Exe'


text:
try {

    $URL = (Get-Link -Uri 'https://www.tmurgent.com/APPV/en/resources/AppV_Manage/221-appv-manage-introduction' -MatchProperty href -Pattern '\.zip$' -PrefixDomain | Resolve-Uri).Uri

    $Version = $URL | Get-Version

    New-NevergreenApp -Name 'TMurgent AppVManage' -Version $Version -Uri $URL -Architecture 'x86' -Type 'Zip'

}
catch {
    Write-Error "$($MyInvocation.MyCommand): $($_.Exception.Message)"
}


text:
try {

    $URL = (Get-Link -Uri 'https://www.tmurgent.com/APPV/en/resources/tools-downloads/tools-downloads-appv5/89-tools/app-v-5-tools/159-appv-defcongroups' -MatchProperty href -Pattern '\.zip$' -PrefixDomain | Resolve-Uri).Uri

    $Version = Get-Version -Uri 'https://www.tmurgent.com/APPV/en/resources/tools-downloads/tools-downloads-appv5/89-tools/app-v-5-tools/159-appv-defcongroups' -Pattern '<td>((?:\d+\.)+\d+)'

    New-NevergreenApp -Name 'TMurgent AppVDefConGroups' -Version $Version -Uri $URL -Architecture 'x86' -Type 'Zip'

}
catch {
    Write-Error "$($MyInvocation.MyCommand): $($_.Exception.Message)"
}


text:
$VDILinks = (Invoke-WebRequest -Uri 'https://support.zoom.us/hc/en-us/articles/4415057249549' -UseBasicParsing -UserAgent 'Microsoft URL Control - 6.01.9782').Links

$Apps = @(
    @{Name = 'Zoom VDI Client'; Architecture = 'x86'; Type = 'Msi'; Pattern = 'ZoomInstallerVDI.+?msi$' }
    @{Name = 'Zoom VDI Client'; Architecture = 'x64'; Type = 'Msi'; Pattern = 'ZoomInstallerVDI.+?msi\?archType=x64$' }
    @{Name = 'Zoom Citrix Plugin'; Architecture = 'x86'; Type = 'Msi'; Pattern = 'ZoomCitrixHDXMediaPlugin\.msi$' }
    @{Name = 'Zoom VDI Universal Plugin'; Architecture = 'x86'; Type = 'Msi'; Pattern = 'ZoomVDIUniversalPlugin.+?msi$' }
    @{Name = 'Zoom VDI Universal Plugin'; Architecture = 'x64'; Type = 'Msi'; Pattern = 'ZoomVDIUniversalPlugin.+?msi\?archType=x64$' }
)

foreach ($App in $Apps) {
    $URL = $VDILinks | Where-Object href -Match $App.Pattern | Select-Object -ExpandProperty href -First 1
    $Version = $URL | Get-Version

    if ($URL -and $Version) {
        New-NevergreenApp -Name $App.Name -Version $Version -Uri $URL -Architecture $App.Architecture -Type $App.Type
    }
    else {
        Write-Warning -Message "Unable to retrieve details for $($App.Name)"
    }
}


text:
$Version = Get-Version -Uri 'https://docs.microsoft.com/en-us/azure/information-protection/rms-client/unifiedlabelingclient-version-release-history' -Pattern '>Version\s((?:\d+\.)+\d+)'
$URLMsi = Get-Link -Uri 'https://www.microsoft.com/en-us/download/confirmation.aspx?id=53018' -MatchProperty href -Pattern '_UL\.msi'
$URLExe = Get-Link -Uri 'https://www.microsoft.com/en-us/download/confirmation.aspx?id=53018' -MatchProperty href -Pattern '_UL\.exe'

New-NevergreenApp -Name 'Microsoft Azure Information Protection' -Version $Version -Uri $URLMsi -Architecture 'x86' -Type 'MSI'
New-NevergreenApp -Name 'Microsoft Azure Information Protection' -Version $Version -Uri $URLExe -Architecture 'x86' -Type 'Exe'


text:
try {
    $URL = Get-Link -Uri 'https://www.boot-disk.com/index.html' -MatchProperty href -Pattern 'BootDisk.+\.exe$'
    $Version = Get-Version -Uri 'https://www.boot-disk.com/history.htm' -Pattern '<strong>((?:\d+\.?)+\d+)</strong>'

    New-NevergreenApp -Name 'LSoft Active@ Boot Disk' -Version $Version -Uri $URL -Architecture 'x86' -Type 'Exe'
}
catch {
    Write-Error "$($MyInvocation.MyCommand): $($_.Exception.Message)"
}


text:
$Links = (Invoke-WebRequest 'https://docs.microsoft.com/en-us/windows-hardware/get-started/adk-install' -DisableKeepAlive -UseBasicParsing).Links

$URL = $Links | Where-Object outerHTML -match "Download the Windows ADK" | Select-Object -ExpandProperty href -First 1
if ($URL) {
    New-NevergreenApp -Name 'Microsoft Windows ADK for Windows 11' -Version '22H2' -Uri $URL -Architecture 'x86' -Type 'Exe'
}

$URL = $Links | Where-Object outerHTML -match "ADK for Windows 11" | Select-Object -ExpandProperty href -First 1
if ($URL) {
    New-NevergreenApp -Name 'Microsoft Windows ADK for Windows 11' -Version '21H2' -Uri $URL -Architecture 'x86' -Type 'Exe'
}

$Versions = @('1607','1703','1709','1803','1809','1903','1909','2004')

foreach ($Version in $Versions) {
    $URL = $Links | Where-Object outerHTML -match "ADK for Windows 10, version $Version" | Select-Object -ExpandProperty href -First 1
    if ($URL) {
        New-NevergreenApp -Name 'Microsoft Windows ADK for Windows 10' -Version $Version -Uri $URL -Architecture 'x86' -Type 'Exe'
    }
}


text:
try {

    $URLRuntime = 'https://airsdk.harman.com/assets/downloads/AdobeAIR.exe'
    $ProgressPreference = 'SilentlyContinue'
    Invoke-WebRequest -Uri $URLRuntime -OutFile "$env:TEMP\AdobeAIR.exe"
    $VersionRuntime = (Get-Item -Path "$env:TEMP\AdobeAIR.exe").VersionInfo.FileVersion
    Remove-Item -Path "$env:TEMP\AdobeAIR.exe" -Force

    New-NevergreenApp -Name 'Harman AIR Runtime' -Channel 'Runtime' -Version $VersionRuntime -Uri $URLRuntime -Architecture 'x86' -Type 'Exe'

    $Response = (Invoke-RestMethod -Uri 'https://airsdk.harman.com/api/config-settings/download' -DisableKeepAlive).latestversion
    $VersionSDK = $Response.versionName
    $URLSDK = $Response.links.SDK_AS_WIN | Set-UriPrefix -Prefix 'https://airsdk.harman.com'
    $URLSDKFlex = $Response.links.SDK_FLEX_WIN | Set-UriPrefix -Prefix 'https://airsdk.harman.com'

    New-NevergreenApp -Name 'Harman AIR SDK' -Channel 'SDK ActionScript' -Version $VersionSDK -Uri $URLSDK -Architecture 'x86' -Type 'Zip'
    New-NevergreenApp -Name 'Harman AIR SDK' -Channel 'SDK Flex' -Version $VersionSDK -Uri $URLSDKFlex -Architecture 'x86' -Type 'Zip'

}
catch {
    Write-Error "$($MyInvocation.MyCommand): $($_.Exception.Message)"
}


text:
$URL = Get-Link -Uri 'https://www.advancedinstaller.com/downloading.html' -MatchProperty href -Pattern '\.msi$' -PrefixDomain

$Version = Get-Link -Uri 'https://www.advancedinstaller.com/download.html' -MatchProperty title -Pattern 'Release Notes' | Get-Version

New-NevergreenApp -Name 'Advanced Installer' -Version $Version -Uri $URL -Architecture 'x86' -Type 'Msi'


text:
$BaseURL = 'https://docs.microsoft.com/en-us/sysinternals/downloads'
$Links = (Invoke-WebRequest -Uri $BaseURL -DisableKeepAlive -UseBasicParsing).Links | Where-Object outerHTML -Match 'data-linktype'

foreach ($Link in $Links) {

    if ($Link.href -match 'SysinternalsSuite.+zip$') {

        $LastModified = (Resolve-Uri -Uri $Link.href).LastModified
        $Version = @($LastModified.Year,$LastModified.Month,$LastModified.Day) -join '.'

        if ($Link.href -match 'SysinternalsSuite\.zip$') {
            New-NevergreenApp -Name 'Microsoft Sysinternals Suite' -Version $Version -Uri $Link.href -Type 'Zip' -Architecture 'Multi' -Platform 'Windows'
        }
        elseif ($Link.href -match 'SysinternalsSuite-Nano\.zip$') {
            New-NevergreenApp -Name 'Microsoft Sysinternals Suite' -Version $Version -Uri $Link.href -Type 'Zip' -Architecture 'x64' -Platform 'Nano Server'
        }
        elseif ($Link.href -match 'SysinternalsSuite-ARM64\.zip$') {
            New-NevergreenApp -Name 'Microsoft Sysinternals Suite' -Version $Version -Uri $Link.href -Type 'Zip' -Architecture 'ARM64' -Platform 'Windows'
        }

    }
    elseif ($Link.href -match 'pstools') {

        $DownloadPageURL = $Link.href | Set-UriPrefix -Prefix $BaseURL
        $URL = Get-Link -Uri $DownloadPageURL -MatchProperty href -Pattern '\.zip$'
        $LastModified = (Resolve-Uri -Uri $URL).LastModified
        $Version = @($LastModified.Year,$LastModified.Month,$LastModified.Day) -join '.'

        New-NevergreenApp -Name 'Microsoft Sysinternals PsTools Suite' -Version $Version -Uri $URL -Type 'Zip' -Architecture 'Multi' -Platform 'Windows'

    }
    elseif ($Link.outerHTML -match '(.+)') {

        $Name = "Microsoft Sysinternals $($Matches[2])"
        $DownloadPageURL = $Matches[1] | Set-UriPrefix -Prefix $BaseURL
        $URL = Get-Link -Uri $DownloadPageURL -MatchProperty href -Pattern '\.zip$'
        $Version = Get-Version -Uri $DownloadPageURL -Pattern ' v((?:\d+\.)+\d+)'

        New-NevergreenApp -Name $Name -Version $Version -Uri $URL -Type 'Zip' -Architecture 'Multi' -Platform 'Windows'

    }
}


text:
try {

    $URL = (Get-Link -Uri 'https://www.tmurgent.com/APPV/en/resources/AVME/349-avme-introduction' -MatchProperty href -Pattern '\.zip$' -PrefixDomain | Resolve-Uri).Uri

    $Version = $URL | Get-Version

    New-NevergreenApp -Name 'TMurgent AppVManifestEditor' -Version $Version -Uri $URL -Architecture 'x86' -Type 'Zip'

}
catch {
    Write-Error "$($MyInvocation.MyCommand): $($_.Exception.Message)"
}


text:
$MajorVersions = @(8,11,16,17,18,19,20)
$ImageTypes = @('JDK', 'JRE')
$Architectures = @('x32','x64')

foreach ($MajorVersion in $MajorVersions) {

    $ReleasesURL = "https://api.adoptium.net/v3/assets/latest/$MajorVersion/hotspot?release=latest&jvm_impl=hotspot&vendor=adoptium&"

    try {

        $Releases = Invoke-RestMethod -Uri $ReleasesURL -DisableKeepAlive -ErrorAction Stop

        foreach ($ImageType in $ImageTypes) {
            foreach ($Architecture in $Architectures) {

                $Release = $Releases | Where-Object { $_.binary.os -eq 'Windows' -and $_.binary.heap_size -eq 'Normal' -and $_.binary.image_type -eq $ImageType -and $_.binary.architecture -eq $Architecture }

                if ($Release) {
                    if ($Release.Count -gt 1) {
                        Write-Warning "Unexpected multiple releases returned for Eclipse Temeru Runtime $MajorVersion $ImageType $Architecture"
                    }

                    if ($Architecture -eq 'x32') {
                        $Architecture = 'x86'
                    }

                    $Release | ForEach-Object {
                        $Version = ($_.version.openjdk_version.Replace('_','.').Replace('+','.') -Replace '-[a-z]','.') -Replace '^1\.8\.','8.'
                        New-NevergreenApp -Name "Adoptium Temurin $ImageType" -Version $Version -Uri $_.binary.installer.link -Architecture $Architecture -Type 'Msi'
                        New-NevergreenApp -Name "Adoptium Temurin $ImageType" -Version $Version -Uri $_.binary.package.link -Architecture $Architecture -Type 'Zip'
                    }
                }

            }
        }
    }
    catch {
        Write-Error "$($MyInvocation.MyCommand): Error querying REST API $($ReleasesURL): $($_.Exception.Message)"
    }
}


text:
try {
    $Response = (Invoke-RestMethod -Uri 'https://update.googleapis.com/service/update2' -Method Post -DisableKeepAlive -Body '<?xml version="1.0" encoding="UTF-8"?><request protocol="3.0" updaterversion="1.3.36.82"><app appid="{6BBAE539-2232-434A-A4E5-9A33560C6283}"><updatecheck/></app></request>').response
    $Version = $Response.app.updatecheck.manifest.version
    $URL = @($Response.app.updatecheck.urls.url.codebase)[-1] + $Response.app.updatecheck.manifest.packages.package.name
    $SHA256 = $Response.app.updatecheck.manifest.packages.package.hash_sha256

    New-NevergreenApp -Name 'Google Drive' -Version $Version -Uri $URL -Architecture 'Multi' -Type 'Exe' -SHA256 $SHA256
}
catch {
    Write-Error "$($MyInvocation.MyCommand): $($_.Exception.Message)"
}


text:
$Apps = @(
    @{Name = '7zip'; Architecture = 'x64'; Type = 'Exe'; Pattern = '7z\d+\-x64\.exe' }
    @{Name = '7zip'; Architecture = 'x86'; Type = 'Exe'; Pattern = '7z\d+\.exe' }
    @{Name = '7zip'; Architecture = 'ARM64'; Type = 'Exe'; Pattern = '7z\d+\-arm64\.exe' }
    @{Name = '7zip'; Architecture = 'x64'; Type = 'Msi'; Pattern = '7z\d+\-x64\.msi' }
    @{Name = '7zip'; Architecture = 'x86'; Type = 'Msi'; Pattern = '7z\d+\.msi' }
    @{Name = '7zip extra'; Architecture = 'Multi'; Type = '7z'; Pattern = '7z\d+-extra\.7z' }
)

$Version = Get-Version -Uri 'https://www.7-zip.org/download.html' -Pattern "7-Zip ((?:\d+\.)+\d+)"

foreach ($App in $Apps)
{
    try
    {
        $URL = Get-Link -Uri 'https://www.7-zip.org/download.html' -MatchProperty href -Pattern $App.Pattern -PrefixDomain
        New-NevergreenApp -Name $App.Name -Version $Version -Uri $URL -Architecture $App.Architecture -Type $App.Type
    }
    catch
    {
        Write-Error "$($MyInvocation.MyCommand): $($_.Exception.Message)"
    }
}


text:
$Platforms = @(
    @{Architecture = 'x86'; Language = 'Neutral'; Pattern = 'AcroRdrDCUpd\d{8,12}\.msp'}
    @{Architecture = 'x86'; Language = 'Multi'; Pattern = 'AcroRdrDCUpd\d{8,12}_MUI\.msp'}
    @{Architecture = 'x64'; Language = 'Neutral'; Pattern = 'AcroRdrDCx64Upd\d{8,12}\.msp'}
    @{Architecture = 'x64'; Language = 'Multi'; Pattern = 'AcroRdrDCx64Upd\d{8,12}_MUI\.msp'}
)

foreach ($Platform in $Platforms) {

    $ReleaseURL = 'https://www.adobe.com/devnet-docs/acrobatetk/tools/ReleaseNotesDC/index.html'
    $SearchCount = 5

    do {
        $ReleaseURL = Get-Link -Uri $ReleaseURL -Headers @{"accept-language"="en-GB,en;q=0.9,en-US;q=0.8"} -MatchProperty outerHTML -Pattern '>Next' -PrefixParent

        $URL = Get-Link -Uri $ReleaseURL -Headers @{"accept-language"="en-GB,en;q=0.9,en-US;q=0.8"} -MatchProperty href -Pattern $Platform.Pattern
        if ($URL) {
            $Version = ($URL | Get-Version -Pattern '(\d{8,12}).+msp') -replace '(\d{2})(\d{3})(\d+)','$1.$2.$3'
            New-NevergreenApp -Name 'Adobe Acrobat Reader' -Version $Version -Uri $URL -Architecture $Platform.Architecture -Language $Platform.Language -Type 'Msp'
            break
        }

        $SearchCount--
    } until ($SearchCount -eq 0)

    if ($SearchCount -eq 0) {
        Write-Warning "Could not find release for Adobe Acrobat Reader $($Platform.Architecture) $($Platform.Language)"
    }

}


text:
$URL32 = Get-Link -Uri 'https://bitbucket.org/phjounin/tftpd64/wiki/Download%20Tftpd64' -MatchProperty href -Pattern 'tftpd32-.+-setup\.exe'
$URL64 = Get-Link -Uri 'https://bitbucket.org/phjounin/tftpd64/wiki/Download%20Tftpd64' -MatchProperty href -Pattern 'tftpd64-.+-setup\.exe'
$Version32 = $URL32 | Get-Version
$Version64 = $URL64 | Get-Version

New-NevergreenApp -Name 'Philippe Jounin Tftpd64' -Version $Version32 -Uri $URL32 -Architecture 'x86' -Type 'Exe'
New-NevergreenApp -Name 'Philippe Jounin Tftpd64' -Version $Version64 -Uri $URL64 -Architecture 'x64' -Type 'Exe'


text:
$Apps = @(
    @{Architecture = 'x86'; Type = 'Exe'; Pattern = '(?:\d+\.)+\d+\.exe$' }
    @{Architecture = 'x64'; Type = 'Exe'; Pattern = '(?:\d+\.)+\d+-x64\.exe$' }
)

foreach ($App in $Apps) {
    try {
        $URL = Get-Link -Uri 'https://support.google.com/earth/answer/168344' -MatchProperty href -Pattern $App.Pattern
        $Version = $URL | Get-Version
        New-NevergreenApp -Name 'Google Earth Pro' -Version $Version -Uri $URL -Architecture $App.Architecture -Type $App.Type
    }
    catch {
        Write-Error "$($MyInvocation.MyCommand): $($_.Exception.Message)"
    }
}


text:
try {
    $Version = Get-Version -Uri 'https://www.irfanview.com/main_history.htm' -Pattern 'Version ((?:\d+\.)+\d+)'

    $Apps = @(
        @{Name = 'IrfanView'; Architecture = 'x86'; Type = 'Exe'; Uri = 'https://fileforum.com/download/IrfanView/967963863/1'; Pattern = 'iview\d+_setup\.exe$'; Language = 'en' }
        @{Name = 'IrfanView'; Architecture = 'x64'; Type = 'Exe'; Uri = 'https://fileforum.com/download/IrfanView/967963863/1?64bit=1'; Pattern = 'iview\d+_x64_setup\.exe$'; Language = 'en' }
        @{Name = 'IrfanView Plugins'; Architecture = 'x86'; Type = 'Exe'; Uri = 'https://fileforum.com/download/IrfanView-PlugIns/1099412658/1'; Pattern = 'iview\d+_plugins_setup\.exe$'; Language = 'en' }
        @{Name = 'IrfanView Plugins'; Architecture = 'x64'; Type = 'Exe'; Uri = 'https://fileforum.com/download/IrfanView-PlugIns/1099412658/1?64bit=1'; Pattern = 'iview\d+_plugins_x64_setup\.exe$'; Language = 'en' }
        @{Name = 'IrfanView Language'; Architecture = 'x86'; Type = 'Exe'; Uri = 'https://www.irfanview.com/languages.htm'; Pattern = 'irfanview_lang_deutsch\.exe$'; Language = 'de' }
        @{Name = 'IrfanView Language'; Architecture = 'x86'; Type = 'Zip'; Uri = 'https://www.irfanview.com/languages.htm'; Pattern = 'irfanview_lang_deutsch\.zip$'; Language = 'de' }
        @{Name = 'IrfanView Language'; Architecture = 'x86'; Type = 'Exe'; Uri = 'https://www.irfanview.com/languages.htm'; Pattern = 'irfanview_lang_russian\.exe$'; Language = 'ru' }
        @{Name = 'IrfanView Language'; Architecture = 'x86'; Type = 'Zip'; Uri = 'https://www.irfanview.com/languages.htm'; Pattern = 'irfanview_lang_russian\.zip$'; Language = 'ru' }
        @{Name = 'IrfanView Language'; Architecture = 'x86'; Type = 'Exe'; Uri = 'https://www.irfanview.com/languages.htm'; Pattern = 'irfanview_lang_chinese\.exe$'; Language = 'zh' }
        @{Name = 'IrfanView Language'; Architecture = 'x86'; Type = 'Zip'; Uri = 'https://www.irfanview.com/languages.htm'; Pattern = 'irfanview_lang_chinese\.zip$'; Language = 'zh' }
        @{Name = 'IrfanView Language'; Architecture = 'x86'; Type = 'Exe'; Uri = 'https://www.irfanview.com/languages.htm'; Pattern = 'irfanview_lang_spanish\.exe$'; Language = 'es' }
        @{Name = 'IrfanView Language'; Architecture = 'x86'; Type = 'Zip'; Uri = 'https://www.irfanview.com/languages.htm'; Pattern = 'irfanview_lang_spanish\.zip$'; Language = 'es' }
        @{Name = 'IrfanView Language'; Architecture = 'x86'; Type = 'Exe'; Uri = 'https://www.irfanview.com/languages.htm'; Pattern = 'irfanview_lang_portugues-Brasil\.exe$'; Language = 'pt-BR' }
        @{Name = 'IrfanView Language'; Architecture = 'x86'; Type = 'Zip'; Uri = 'https://www.irfanview.com/languages.htm'; Pattern = 'irfanview_lang_portugues-Brasil\.zip$'; Language = 'pt-BR' }
        @{Name = 'IrfanView Language'; Architecture = 'x86'; Type = 'Exe'; Uri = 'https://www.irfanview.com/languages.htm'; Pattern = 'irfanview_lang_japanese\.exe$'; Language = 'ja' }
        @{Name = 'IrfanView Language'; Architecture = 'x86'; Type = 'Zip'; Uri = 'https://www.irfanview.com/languages.htm'; Pattern = 'irfanview_lang_japanese\.zip$'; Language = 'ja' }
        @{Name = 'IrfanView Language'; Architecture = 'x86'; Type = 'Exe'; Uri = 'https://www.irfanview.com/languages.htm'; Pattern = 'irfanview_lang_italian\.exe$'; Language = 'it' }
        @{Name = 'IrfanView Language'; Architecture = 'x86'; Type = 'Zip'; Uri = 'https://www.irfanview.com/languages.htm'; Pattern = 'irfanview_lang_italian\.zip$'; Language = 'it' }
        @{Name = 'IrfanView Language'; Architecture = 'x86'; Type = 'Exe'; Uri = 'https://www.irfanview.com/languages.htm'; Pattern = 'irfanview_lang_nederlands\.exe$'; Language = 'nl-NL' }
        @{Name = 'IrfanView Language'; Architecture = 'x86'; Type = 'Zip'; Uri = 'https://www.irfanview.com/languages.htm'; Pattern = 'irfanview_lang_nederlands\.zip$'; Language = 'nl-NL' }
        @{Name = 'IrfanView Language'; Architecture = 'x86'; Type = 'Exe'; Uri = 'https://www.irfanview.com/languages.htm'; Pattern = 'irfanview_lang_polski\.exe$'; Language = 'pl' }
        @{Name = 'IrfanView Language'; Architecture = 'x86'; Type = 'Zip'; Uri = 'https://www.irfanview.com/languages.htm'; Pattern = 'irfanview_lang_polski\.zip$'; Language = 'pl' }
        @{Name = 'IrfanView Language'; Architecture = 'x86'; Type = 'Exe'; Uri = 'https://www.irfanview.com/languages.htm'; Pattern = 'irfanview_lang_portuguese\.exe$'; Language = 'pt-PT' }
        @{Name = 'IrfanView Language'; Architecture = 'x86'; Type = 'Zip'; Uri = 'https://www.irfanview.com/languages.htm'; Pattern = 'irfanview_lang_portuguese\.zip$'; Language = 'pt-PT' }
        @{Name = 'IrfanView Language'; Architecture = 'x86'; Type = 'Exe'; Uri = 'https://www.irfanview.com/languages.htm'; Pattern = 'irfanview_lang_ukrainian\.exe$'; Language = 'uk' }
        @{Name = 'IrfanView Language'; Architecture = 'x86'; Type = 'Zip'; Uri = 'https://www.irfanview.com/languages.htm'; Pattern = 'irfanview_lang_ukrainian\.zip$'; Language = 'uk' }
        @{Name = 'IrfanView Language'; Architecture = 'x86'; Type = 'Exe'; Uri = 'https://www.irfanview.com/languages.htm'; Pattern = 'irfanview_lang_finnish\.exe$'; Language = 'fi' }
        @{Name = 'IrfanView Language'; Architecture = 'x86'; Type = 'Zip'; Uri = 'https://www.irfanview.com/languages.htm'; Pattern = 'irfanview_lang_finnish\.zip$'; Language = 'fi' }
        @{Name = 'IrfanView Language'; Architecture = 'x86'; Type = 'Exe'; Uri = 'https://www.irfanview.com/languages.htm'; Pattern = 'irfanview_lang_hungarian\.exe$'; Language = 'hu' }
        @{Name = 'IrfanView Language'; Architecture = 'x86'; Type = 'Zip'; Uri = 'https://www.irfanview.com/languages.htm'; Pattern = 'irfanview_lang_hungarian\.zip$'; Language = 'hu' }
        @{Name = 'IrfanView Language'; Architecture = 'x86'; Type = 'Exe'; Uri = 'https://www.irfanview.com/languages.htm'; Pattern = 'irfanview_lang_czech\.exe$'; Language = 'cs' }
        @{Name = 'IrfanView Language'; Architecture = 'x86'; Type = 'Zip'; Uri = 'https://www.irfanview.com/languages.htm'; Pattern = 'irfanview_lang_czech\.zip$'; Language = 'cs' }
        @{Name = 'IrfanView Language'; Architecture = 'x86'; Type = 'Exe'; Uri = 'https://www.irfanview.com/languages.htm'; Pattern = 'irfanview_lang_french\.exe$'; Language = 'fr' }
        @{Name = 'IrfanView Language'; Architecture = 'x86'; Type = 'Zip'; Uri = 'https://www.irfanview.com/languages.htm'; Pattern = 'irfanview_lang_french\.zip$'; Language = 'fr' }
        @{Name = 'IrfanView Language'; Architecture = 'x86'; Type = 'Exe'; Uri = 'https://www.irfanview.com/languages.htm'; Pattern = 'irfanview_lang_slovak\.exe$'; Language = 'sk' }
        @{Name = 'IrfanView Language'; Architecture = 'x86'; Type = 'Zip'; Uri = 'https://www.irfanview.com/languages.htm'; Pattern = 'irfanview_lang_slovak\.zip$'; Language = 'sk' }
        @{Name = 'IrfanView Language'; Architecture = 'x86'; Type = 'Exe'; Uri = 'https://www.irfanview.com/languages.htm'; Pattern = 'irfanview_lang_arabic\.exe$'; Language = 'ar' }
        @{Name = 'IrfanView Language'; Architecture = 'x86'; Type = 'Zip'; Uri = 'https://www.irfanview.com/languages.htm'; Pattern = 'irfanview_lang_arabic\.zip$'; Language = 'ar' }
        @{Name = 'IrfanView Language'; Architecture = 'x86'; Type = 'Exe'; Uri = 'https://www.irfanview.com/languages.htm'; Pattern = 'irfanview_lang_estonian\.exe$'; Language = 'et' }
        @{Name = 'IrfanView Language'; Architecture = 'x86'; Type = 'Zip'; Uri = 'https://www.irfanview.com/languages.htm'; Pattern = 'irfanview_lang_estonian\.exe$'; Language = 'et' }
        @{Name = 'IrfanView Language'; Architecture = 'x86'; Type = 'Exe'; Uri = 'https://www.irfanview.com/languages.htm'; Pattern = 'irfanview_lang_slovenscina\.zip$'; Language = 'sl' }
        @{Name = 'IrfanView Language'; Architecture = 'x86'; Type = 'Zip'; Uri = 'https://www.irfanview.com/languages.htm'; Pattern = 'irfanview_lang_slovenscina\.exe$'; Language = 'sl' }
        @{Name = 'IrfanView Language'; Architecture = 'x86'; Type = 'Exe'; Uri = 'https://www.irfanview.com/languages.htm'; Pattern = 'irfanview_lang_romanian\.zip$'; Language = 'ro' }
        @{Name = 'IrfanView Language'; Architecture = 'x86'; Type = 'Zip'; Uri = 'https://www.irfanview.com/languages.htm'; Pattern = 'irfanview_lang_romanian\.exe$'; Language = 'ro' }
        @{Name = 'IrfanView Language'; Architecture = 'x86'; Type = 'Exe'; Uri = 'https://www.irfanview.com/languages.htm'; Pattern = 'irfanview_lang_turkish\.zip$'; Language = 'tr' }
        @{Name = 'IrfanView Language'; Architecture = 'x86'; Type = 'Zip'; Uri = 'https://www.irfanview.com/languages.htm'; Pattern = 'irfanview_lang_turkish\.exe$'; Language = 'tr' }
        @{Name = 'IrfanView Language'; Architecture = 'x86'; Type = 'Exe'; Uri = 'https://www.irfanview.com/languages.htm'; Pattern = 'irfanview_lang_lithuanian\.exe$'; Language = 'lt' }
        @{Name = 'IrfanView Language'; Architecture = 'x86'; Type = 'Zip'; Uri = 'https://www.irfanview.com/languages.htm'; Pattern = 'irfanview_lang_lithuanian\.zip$'; Language = 'lt' }
        @{Name = 'IrfanView Language'; Architecture = 'x86'; Type = 'Exe'; Uri = 'https://www.irfanview.com/languages.htm'; Pattern = 'irfanview_lang_swedish\.exe$'; Language = 'sv' }
        @{Name = 'IrfanView Language'; Architecture = 'x86'; Type = 'Zip'; Uri = 'https://www.irfanview.com/languages.htm'; Pattern = 'irfanview_lang_swedish\.zip$'; Language = 'sv' }
        @{Name = 'IrfanView Language'; Architecture = 'x86'; Type = 'Exe'; Uri = 'https://www.irfanview.com/languages.htm'; Pattern = 'irfanview_lang_hebrew\.exe$'; Language = 'he' }
        @{Name = 'IrfanView Language'; Architecture = 'x86'; Type = 'Zip'; Uri = 'https://www.irfanview.com/languages.htm'; Pattern = 'irfanview_lang_hebrew\.zip$'; Language = 'he' }
        @{Name = 'IrfanView Language'; Architecture = 'x86'; Type = 'Exe'; Uri = 'https://www.irfanview.com/languages.htm'; Pattern = 'irfanview_lang_bulgarian\.exe$'; Language = 'bg' }
        @{Name = 'IrfanView Language'; Architecture = 'x86'; Type = 'Zip'; Uri = 'https://www.irfanview.com/languages.htm'; Pattern = 'irfanview_lang_bulgarian\.zip$'; Language = 'bg' }
        @{Name = 'IrfanView Language'; Architecture = 'x86'; Type = 'Exe'; Uri = 'https://www.irfanview.com/languages.htm'; Pattern = 'irfanview_lang_catalan\.exe$'; Language = 'ca' }
        @{Name = 'IrfanView Language'; Architecture = 'x86'; Type = 'Zip'; Uri = 'https://www.irfanview.com/languages.htm'; Pattern = 'irfanview_lang_catalan\.zip$'; Language = 'ca' }
        @{Name = 'IrfanView Language'; Architecture = 'x86'; Type = 'Exe'; Uri = 'https://www.irfanview.com/languages.htm'; Pattern = 'irfanview_lang_korean\.exe$'; Language = 'ko' }
        @{Name = 'IrfanView Language'; Architecture = 'x86'; Type = 'Zip'; Uri = 'https://www.irfanview.com/languages.htm'; Pattern = 'irfanview_lang_korean\.zip$'; Language = 'ko' }
        @{Name = 'IrfanView Language'; Architecture = 'x86'; Type = 'Exe'; Uri = 'https://www.irfanview.com/languages.htm'; Pattern = 'irfanview_lang_english_gb\.exe$'; Language = 'en-GB' }
        @{Name = 'IrfanView Language'; Architecture = 'x86'; Type = 'Zip'; Uri = 'https://www.irfanview.com/languages.htm'; Pattern = 'irfanview_lang_english_gb\.zip$'; Language = 'en-GB' }
        @{Name = 'IrfanView Language'; Architecture = 'x86'; Type = 'Exe'; Uri = 'https://www.irfanview.com/languages.htm'; Pattern = 'irfanview_lang_dansk\.exe$'; Language = 'da' }
        @{Name = 'IrfanView Language'; Architecture = 'x86'; Type = 'Zip'; Uri = 'https://www.irfanview.com/languages.htm'; Pattern = 'irfanview_lang_dansk\.zip$'; Language = 'da' }
        @{Name = 'IrfanView Language'; Architecture = 'x86'; Type = 'Exe'; Uri = 'https://www.irfanview.com/languages.htm'; Pattern = 'irfanview_lang_latvian\.exe$'; Language = 'lv' }
        @{Name = 'IrfanView Language'; Architecture = 'x86'; Type = 'Zip'; Uri = 'https://www.irfanview.com/languages.htm'; Pattern = 'irfanview_lang_latvian\.zip$'; Language = 'lv' }
        @{Name = 'IrfanView Language'; Architecture = 'x86'; Type = 'Exe'; Uri = 'https://www.irfanview.com/languages.htm'; Pattern = 'irfanview_lang_uzbek\.exe$'; Language = 'uz' }
        @{Name = 'IrfanView Language'; Architecture = 'x86'; Type = 'Zip'; Uri = 'https://www.irfanview.com/languages.htm'; Pattern = 'irfanview_lang_uzbek\.zip$'; Language = 'uz' }
    )

    foreach ($App in $Apps) {
        try {
            $URL = Get-Link -Uri $App.Uri -MatchProperty href -Pattern $App.Pattern
            New-NevergreenApp -Name $App.Name -Version $Version -Uri $URL -Architecture $App.Architecture -Type $App.Type -Language $App.Language
        }
        catch {
        }
    }

}
catch {
    Write-Error "$($MyInvocation.MyCommand): Error querying 'https://www.irfanview.com/main_history.htm': $($_.Exception.Message)"
}


text:
try {

    $URL = (Get-Link -Uri 'https://www.tmurgent.com/APPV/en/buy/tmedit/tmedit-download' -MatchProperty href -Pattern '\.zip$' -PrefixDomain | Resolve-Uri).Uri

    $Version = $URL | Get-Version

    New-NevergreenApp -Name 'TMurgent TMEdit' -Version $Version -Uri $URL -Architecture 'x86' -Type 'Zip'

}
catch {
    Write-Error "$($MyInvocation.MyCommand): $($_.Exception.Message)"
}


text:
$Branches = @('Fresh','Still')
$Architectures = @('x86_64','x86')
$Language = 'en-GB'

foreach ($Branch in $Branches) {

    try {
        $Version = Get-Version -Uri 'https://www.libreoffice.org/download/release-notes' -Pattern "LibreOffice ((?:\d+\.)+\d+)[^<]+$Branch" -ErrorAction Stop
    }
    catch {
        Write-Error "$($MyInvocation.MyCommand): $($_.Exception.Message)"
        break
    }

    foreach ($Architecture in $Architectures) {

        try {
            $DownloadPage = Get-Link -Uri "https://www.libreoffice.org/download/download-libreoffice/?type=win-$Architecture&version=$Version&lang=$Language" -MatchProperty href -Pattern "$Version[^`"]+$($Architecture.Substring($Architecture.Length-2,2))\.msi$" -ErrorAction Stop
            $URL = (Get-Link -Uri $DownloadPage -MatchProperty href -Pattern "$Version[^`"]+$($Architecture.Substring($Architecture.Length-2,2))\.msi$" -ErrorAction Stop) -replace '^//','https://'
            New-NevergreenApp -Name 'LibreOffice' -Version $Version -Uri $URL -Architecture $Architecture.Replace('86_','') -Type 'msi' -Channel $Branch -Language 'Multi'
        }
        catch {
            Write-Error "$($MyInvocation.MyCommand): $($_.Exception.Message)"
        }
    }
}


text:
$URL = Get-Link -Uri 'https://nmap.org/download.html' -MatchProperty href -Pattern 'nmap-(?:\d+\.)+\d+-setup\.exe$'
$Version = $URL | Get-Version

New-NevergreenApp -Name 'Nmap' -Version $Version -Uri $URL -Architecture 'x86' -Type 'Exe'


text:
try {

    #Get hashes of all releases
    $FileNames = @{}
    ((Invoke-Webrequest -Uri 'https://raw.githubusercontent.com/conda/conda-docs/master/docs/source/miniconda_hashes.rst' -DisableKeepAlive -UseBasicParsing).Content |
    Select-String -Pattern '(Miniconda\S+\.exe).+(\w{64})' -AllMatches).Matches | ForEach-Object {
        $FileNames.Add($_.Groups[2].Value, $_.Groups[1].Value)
    }

    #Get all links from main download page, swap URLs with 'latest' in filename for the proper versioned name via hash matching and extract properties from filename
    ((Invoke-Webrequest -Uri 'https://raw.githubusercontent.com/conda/conda-docs/master/docs/source/miniconda.rst' -DisableKeepAlive -UseBasicParsing).Content |
    Select-String -Pattern '(http\S+(Miniconda\d)-\S+-Windows-(x86(?:_64)?)\.exe).+(\w{64})' -AllMatches).Matches | ForEach-Object {

        $URL = $_.Groups[1].Value
        $Name = $_.Groups[2].Value

        $Architecture = $_.Groups[3].Value
        if ($Architecture -eq 'x86_64') {
            $Architecture = 'x64'
        }

        $Hash = $_.Groups[4].Value

        if ($URL -match 'latest' -and $Hash -in $FileNames.Keys) {
            $URL = $URL -replace '[^/]+$',$FileNames[$Hash]
        }

        $Version = $URL | Get-Version

        if ($URL -match 'py(\d+)') {
            $Channel = "Python $($matches[1].Insert(1,'.'))"
        }

        if (Resolve-Uri $URL) {
            New-NevergreenApp -Name $Name -Channel $Channel -Architecture $Architecture -Type 'Exe' -Version $Version -Uri $URL -SHA256 $Hash
        }

    }
}
catch {
    Write-Error "$($MyInvocation.MyCommand): $($_.Exception.Message)"
}


text:
$Platforms = @(
    @{Architecture = 'x86'; Language = 'Neutral'; Pattern = 'AcrobatDCUpd\d{8,12}\.msp'}
    @{Architecture = 'x64'; Language = 'Neutral'; Pattern = 'AcrobatDCx64Upd\d{8,12}\.msp'}
)

foreach ($Platform in $Platforms) {

    $ReleaseURL = 'https://www.adobe.com/devnet-docs/acrobatetk/tools/ReleaseNotesDC/index.html'
    $SearchCount = 5

    do {
        $ReleaseURL = Get-Link -Uri $ReleaseURL -Headers @{"accept-language"="en-GB,en;q=0.9,en-US;q=0.8"} -MatchProperty outerHTML -Pattern '>Next' -PrefixParent

        $URL = Get-Link -Uri $ReleaseURL -Headers @{"accept-language"="en-GB,en;q=0.9,en-US;q=0.8"} -MatchProperty href -Pattern $Platform.Pattern
        if ($URL) {
            $Version = ($URL | Get-Version -Pattern '(\d{8,12}).+msp') -replace '(\d{2})(\d{3})(\d+)','$1.$2.$3'
            New-NevergreenApp -Name 'Adobe Acrobat' -Version $Version -Uri $URL -Architecture $Platform.Architecture -Language $Platform.Language -Type 'Msp'
            break
        }

        $SearchCount--
    } until ($SearchCount -eq 0)

    if ($SearchCount -eq 0) {
        Write-Warning "Could not find release for Adobe Acrobat $($Platform.Architecture) $($Platform.Language)"
    }

}


text:
# MSIX links on site out of date
try {

    $URL = Get-Link -Uri 'https://www.tmurgent.com/APPV/en/resources/tools-downloads/msix-tools/128-msix-tools/557-psftoolingv48' -MatchProperty href -Pattern '\.msix$' -PrefixDomain -ErrorAction Stop

    $Version = $URL | Get-Version

    New-NevergreenApp -Name 'TMurgent PsfTooling' -Version $Version -Uri $URL -Architecture 'x86' -Type 'MSIX'

}
catch {
    Write-Error "$($MyInvocation.MyCommand): $($_.Exception.Message)"
}


text:
$URL64 = Get-Link -Uri 'https://www.igel.com/software-downloads/workspace-edition/' -MatchProperty 'data-filename' -Pattern 'setup-igel-ums-windows.+\.exe' -ReturnProperty 'data-filename'
$Version = $URL64 | Get-Version

New-NevergreenApp -Name 'IGEL Universal Management Suite' -Version $Version -Uri $URL64 -Architecture 'x64' -Type 'Exe'


text:
try {

    $Version = Get-Version -Uri 'https://www.citrix.com/downloads/sharefile/clients-and-plug-ins/citrix-files-for-windows.html' -Pattern 'ShareFile for Windows v((?:\d+\.)+\d+)'

    $URLMsi = Get-Link -Uri 'https://www.citrix.com/downloads/sharefile/clients-and-plug-ins/citrix-files-for-windows.html' -MatchProperty outerHTML -Pattern '\.msi' -ReturnProperty outerHTML
    if ($URLMsi -match 'rel="(//.+\.msi[^"]+)') {
        $URLMsi = "https:" + $Matches[1]
        New-NevergreenApp -Name 'Citrix Files' -Version $Version -Uri $URLMsi -Architecture 'x64' -Type 'Msi'
    }

    $URLExe = Get-Link -Uri 'https://www.citrix.com/downloads/sharefile/clients-and-plug-ins/citrix-files-for-windows.html' -MatchProperty outerHTML -Pattern '\.exe' -ReturnProperty outerHTML
    if ($URLExe -match 'rel="(//.+\.exe[^"]+)') {
        $URLExe = "https:" + $Matches[1]
        New-NevergreenApp -Name 'Citrix Files' -Version $Version -Uri $URLExe -Architecture 'Multi' -Type 'Exe'
    }

}
catch {
    Write-Error "$($MyInvocation.MyCommand): $($_.Exception.Message)"
}


text:
try {

    $Version = Get-Version -Uri 'https://fujifilm-x.com/en-gb/support/download/software/raw-file-converter-ex-powered-by-silkypix/' -Pattern 'Windows Version: (?:Ver\.)?((?:\d+\.)+\d+)'

    $URL = Get-Link -Uri 'https://fujifilm-x.com/en-gb/support/download/software/raw-file-converter-ex-powered-by-silkypix/' -MatchProperty href -Pattern '\.exe$'

    New-NevergreenApp -Name 'Fujifilm Raw File Converter EX 3.0' -Version $Version -Uri $URL -Architecture 'x86' -Type 'Exe'

}
catch {
    Write-Error "$($MyInvocation.MyCommand): $($_.Exception.Message)"
}


text:
$URL32 = (Resolve-Uri -Uri 'https://cardstudio.zebra.com/download').Uri

$Version = $URL32 | Get-Version

New-NevergreenApp -Name 'Zebra Card Studio' -Version $Version -Uri $URL32 -Architecture 'x86' -Type 'Exe'


text:
$DownloadPageURL = Get-Link -Uri 'https://support.redstor.com/hc/en-gb/sections/200458081-Downloads' -MatchProperty href -Pattern 'Downloads-Redstor-Pro' -PrefixDomain

$URL32 = Get-Link -Uri $DownloadPageURL -MatchProperty href -Pattern 'RedstorBackupPro-SP-Console'

$Version = $URL32 | Get-Version -Pattern '((?:\d+\.)+\d+)\.exe$'

New-NevergreenApp -Name 'Redstor Backup Pro Storage Platform Console' -Version $Version -Uri $URL32 -Architecture 'x86' -Type 'Exe'


text:
$URL32,$URL64,$URLARM64 = Get-Link -Uri 'https://helpx.adobe.com/ca/download-install/kb/creative-cloud-desktop-app-download.html' -MatchProperty href -Pattern 'win32','win64','winarm64'
$Version32,$Version64,$VersionARM64 = $URL32,$URL64,$URLARM64 | Get-Version -Pattern 'ACCCx((?:\d+_)+\d+)\.zip$' -ReplaceWithDot

New-NevergreenApp -Name 'Adobe Creative Cloud' -Version $Version32 -Uri $URL32 -Architecture 'x86' -Type 'Zip'
New-NevergreenApp -Name 'Adobe Creative Cloud' -Version $Version64 -Uri $URL64 -Architecture 'x64' -Type 'Zip'
New-NevergreenApp -Name 'Adobe Creative Cloud' -Version $VersionARM64 -Uri $URLARM64 -Architecture 'ARM64' -Type 'Zip'


text:
$Version = Get-Version -Uri 'https://help.webex.com/en-us/article/mqkve8/Webex-App-%7C-Release-notes' -Pattern 'Windows[^\d]+((?:\d+\.)+(?:\d+))'

$URL32 = Get-Link -Uri 'https://help.webex.com/en-us/article/nw5p67g/Webex-App-%7C-Installation-and-automatic-upgrade' -MatchProperty href -Pattern 'Webex_x86\.msi'
$URL64 = Get-Link -Uri 'https://help.webex.com/en-us/article/nw5p67g/Webex-App-%7C-Installation-and-automatic-upgrade' -MatchProperty href -Pattern 'Webex\.msi'

New-NevergreenApp -Name 'Cisco Webex' -Version $Version -Uri $URL32 -Architecture 'x86' -Type 'Msi'
New-NevergreenApp -Name 'Cisco Webex' -Version $Version -Uri $URL64 -Architecture 'x64' -Type 'Msi'


text:
$Response = Invoke-WebRequest -Uri 'https://www.qgis.org/en/site/forusers/download.html' -DisableKeepAlive -UseBasicParsing

$URL64 = $Response.Links | Where-Object href -Like '*.msi' | Select-Object -First 1 -ExpandProperty href
$Version64 = $URL64 | Get-Version

$URL64LTR = $Response.Links | Where-Object href -Like '*.msi' | Select-Object -First 1 -Skip 1 -ExpandProperty href
$Version64LTR = $URL64LTR | Get-Version

New-NevergreenApp -Name 'QGIS' -Version $Version64 -Uri $URL64 -Architecture 'x64' -Channel 'Latest' -Type 'Msi'
New-NevergreenApp -Name 'QGIS' -Version $Version64LTR -Uri $URL64LTR -Architecture 'x64' -Channel 'LTR' -Type 'Msi'


text:
$RetryCount = 3

for ($i = 0; $i -lt $RetryCount; $i++) {
    try {
        $Version = ((Invoke-WebRequest 'https://welcome.webex.com/svc3300/svccomponents/support/siteAbout.do?serviceID=9&siteurl=welcome' -DisableKeepAlive -UseBasicParsing -ErrorAction Stop).Content | Select-String -Pattern '(?:\d+\.)+(?:\d+)' -AllMatches).Matches.Groups.Value | Select-Object -Skip 1 -First 1
        $URL32 = "https://welcome.webex.com/client/T33L/aainstall.msi"
        New-NevergreenApp -Name 'Cisco Webex Access Anyhwere' -Version $Version -Uri $URL32 -Architecture 'x86' -Type 'Msi'
        break
    }
    catch {
        Write-Warning "Attempt $($i+1) failed, retrying... $_"
    }
}


text:
$SupportedVersions = @('3.10','3.11')

$Suffixes = @{x86 = '.exe'; x64 = '-amd64.exe'; ARM64 = '-arm64.exe'}

foreach ($SupportedVersion in $SupportedVersions) {

    foreach ($Platform in $Suffixes.keys) {

        $URL = Get-Link -Uri 'https://www.python.org/downloads/windows/' -MatchProperty href -Pattern "python-($([RegEx]::Escape($SupportedVersion))\.\d+)$([RegEx]::Escape($Suffixes[$Platform]))$"
        if ($URL) {
            $Version = $URL | Get-Version
            New-NevergreenApp -Name "Python $SupportedVersion" -Version $Version -Uri $URL -Architecture $Platform -Type 'Exe'
        }
    }

}


text:
try {

    #API that iTunes queries is only returning a 3-part version number, other sources below use 4 parts but are not direct from Apple. Monitor next update to see which is best.
    $Version = Get-Version -Uri 'https://s.mzstatic.com/version' -Pattern '<key>iTunesWindowsVersion</key>\s+<string>((?:\d+\.)+\d+)</string>'

    #$Version = ((Invoke-WebRequest -Uri 'https://en.wikipedia.org/wiki/History_of_iTunes' -DisableKeepAlive -UseBasicParsing).Content | Select-String -Pattern '
((?:\d+\.)+\d+)\s
\s	' -AllMatches)[-1].Matches[-1].Groups[1].Value
    #$Version = (Invoke-RestMethod -Uri 'https://community.chocolatey.org/api/v2/Packages()?$filter=(tolower(Id)%20eq%20''itunes'')%20and%20IsLatestVersion' -DisableKeepAlive).Properties.Version

    $URL64 = 'https://www.apple.com/itunes/download/win64'
    $URL32 = 'https://www.apple.com/itunes/download/win32'

    New-NevergreenApp -Name 'Apple iTunes' -Version $Version -Uri $URL64 -Architecture 'x64' -Type 'Exe'
    New-NevergreenApp -Name 'Apple iTunes' -Version $Version -Uri $URL32 -Architecture 'x86' -Type 'Exe'
}
catch {
    Write-Error "$($MyInvocation.MyCommand): $($_.Exception.Message)"
}


text:
try {

    $Version = Get-Version -Uri 'https://fujifilm-x.com/en-gb/support/download/software/x-webcam/' -Pattern 'Windows Version: (?:Ver\.)?((?:\d+\.)+\d+)'

    $URL = Get-Link -Uri 'https://fujifilm-x.com/en-gb/support/download/software/x-webcam/' -MatchProperty href -Pattern '\.zip$'

    New-NevergreenApp -Name 'Fujifilm X Webcam' -Version $Version -Uri $URL -Architecture 'x64' -Type 'Zip'

}
catch {
    Write-Error "$($MyInvocation.MyCommand): $($_.Exception.Message)"
}


text:
$Architectures = @('x64','i386')

foreach ($Architecture in $Architectures) {
    try {

        $Response = Invoke-WebRequest -Uri "https://download.opera.com/download/get/?partner=www&opsys=Windows&download_url=&arch=$Architecture" -UseBasicParsing

        if ($IsCoreCLR) {
            $Redirect = $Response.BaseResponse.RequestMessage.RequestUri.AbsoluteUri
        }
        else {
            $Redirect = $Response.BaseResponse.ResponseUri.AbsoluteUri
        }

        if ($Redirect -match 'id%3D(\d+)') {
            $URL = (Resolve-Uri -Uri "https://download.opera.com/download/get/?id=$($matches[1])&nothanks=yes").Uri
            $Version = $URL | Get-Version
            if ($Architecture -eq 'i386') { $Architecture = 'x86'}
            New-NevergreenApp -Name 'Opera' -Version $Version -Uri $URL -Architecture $Architecture -Type 'Exe'
        }

    }
    catch {
        Write-Error "$($MyInvocation.MyCommand): $($_.Exception.Message)"
    }
}


text:
try {
    $URL = Get-Link -Uri 'https://www.disk-image.com/download.htm' -MatchProperty href -Pattern 'Free\S+\.exe$' -PrefixDomain
    $Version = Get-Version -Uri 'https://www.disk-image.com/history.htm' -Pattern '((?:\d+\.)+\d+)</b>'

    New-NevergreenApp -Name 'LSoft Active@ Disk Image Lite' -Version $Version -Uri $URL -Architecture 'x86' -Type 'Exe'
}
catch {
    Write-Error "$($MyInvocation.MyCommand): $($_.Exception.Message)"
}


text:
try {

    $Version = Get-Version -Uri 'https://fujifilm-x.com/en-gb/support/download/software/x-acquire/' -Pattern 'Windows Version: (?:Ver\.)?((?:\d+\.)+\d+)'

    $URL = Get-Link -Uri 'https://fujifilm-x.com/en-gb/support/download/software/x-acquire/' -MatchProperty href -Pattern '\.exe$'

    New-NevergreenApp -Name 'Fujifilm X Acquire' -Version $Version -Uri $URL -Architecture 'x86' -Type 'Exe'

}
catch {
    Write-Error "$($MyInvocation.MyCommand): $($_.Exception.Message)"
}


text:
$Response = Invoke-WebRequest 'https://community.mimecast.com/s/mimecast-for-outlook' -UseBasicParsing -UserAgent 'Googlebot/2.1 (+http://www.google.com/bot.html)'

$URL32 = ($Response.Links | Where-Object class -EQ 'cta-btn')[0].href.Replace('&','&')
$URL64 = ($Response.Links | Where-Object class -EQ 'cta-btn')[1].href.Replace('&','&')

$Version = $Response.Content | Get-Version -Pattern 'Build\s((?:\d+\.)+\d+)<'

New-NevergreenApp -Name 'Mimecast for Outlook' -Version $Version -Uri $URL32 -Architecture 'x86' -Type 'Zip'
New-NevergreenApp -Name 'Mimecast for Outlook' -Version $Version -Uri $URL64 -Architecture 'x64' -Type 'Zip'


text:
$Branches = @('Fresh','Still')
$Architectures = @('x86_64','x86')
$Languages = (Invoke-WebRequest -Uri 'https://www.libreoffice.org/download/download/?lang=pick' -DisableKeepAlive).Links | Where-Object href -Match 'lang=' | Select-Object -ExpandProperty href | ForEach-Object { $_ -replace '.+lang=(.+)','$1' } | Sort-Object

foreach ($Branch in $Branches) {

    try {
        $Version = Get-Version -Uri 'https://www.libreoffice.org/download/release-notes' -Pattern "LibreOffice ((?:\d+\.)+\d+)[^<]+$Branch"
    }
    catch {
        Write-Error "$($MyInvocation.MyCommand): $($_.Exception.Message)"
        break
    }

    foreach ($Architecture in $Architectures) {

        foreach ($Language in $Languages) {

            try {
                $URL = Get-Link -Uri "https://www.libreoffice.org/download/download/?type=win-$Architecture&version=$Version&lang=$Language" -MatchProperty href -Pattern "$Version.+$($Architecture.Replace('86_',''))_helppack_$Language\.msi$"

                if ($URL) {
                    New-NevergreenApp -Name 'LibreOffice Offline Help' -Version $Version -Uri $URL -Architecture $Architecture.Replace('86_','') -Type 'MSI' -Channel $Branch -Language $Language
                }
            }
            catch {
                Write-Error "$($MyInvocation.MyCommand): $($_.Exception.Message)"
            }

        }

    }

}


text:
try {

    $Version = Get-Version -Uri 'https://fujifilm-x.com/en-gb/support/download/software/x-raw-studio/' -Pattern 'Windows Version: (?:Ver\.)?((?:\d+\.)+\d+)'

    $URL = Get-Link -Uri 'https://fujifilm-x.com/en-gb/support/download/software/x-raw-studio/' -MatchProperty href -Pattern '\.exe$'

    New-NevergreenApp -Name 'Fujifilm X Raw Studio' -Version $Version -Uri $URL -Architecture 'x64' -Type 'Exe'

}
catch {
    Write-Error "$($MyInvocation.MyCommand): $($_.Exception.Message)"
}


text:
$Releases = @(
    @{Architecture = 'x64'; Type = 'msi'; Pattern = 'microsoft-jdk-11.+x64\.msi$'}
    @{Architecture = 'x64'; Type = 'zip'; Pattern = 'microsoft-jdk-11.+x64\.zip$'}
    @{Architecture = 'ARM64'; Type = 'msi'; Pattern = 'microsoft-jdk-11.+aarch64\.msi$'}
    @{Architecture = 'ARM64'; Type = 'zip'; Pattern = 'microsoft-jdk-11.+aarch64\.zip$'}
    @{Architecture = 'x64'; Type = 'msi'; Pattern = 'microsoft-jdk-17.+x64\.msi$'}
    @{Architecture = 'x64'; Type = 'zip'; Pattern = 'microsoft-jdk-17.+x64\.zip$'}
    @{Architecture = 'ARM64'; Type = 'msi'; Pattern = 'microsoft-jdk-17.+aarch64\.msi$'}
    @{Architecture = 'ARM64'; Type = 'zip'; Pattern = 'microsoft-jdk-17.+aarch64\.zip$'}
)

foreach ($Release in $Releases) {
    try {
        $URL = Get-Link -Uri 'https://docs.microsoft.com/en-gb/java/openjdk/download' -MatchProperty href -Pattern $Release.Pattern -ErrorAction Stop
        $Version = $URL | Get-Version
        New-NevergreenApp -Name 'Microsoft OpenJDK' -Version $Version -Uri $URL -Architecture $Release.Architecture -Type $Release.Type
    }
    catch {
        Write-Error "$($MyInvocation.MyCommand): $($_.Exception.Message)"
    }
}


text:
$Version = Get-Version -Uri 'https://www.komodolabs.com/product-downloads' -Pattern 'NEWT Professional v((?:\d+\.)+\d+)'

$URL32 = Get-Link -Uri 'https://www.komodolabs.com/product-downloads' -MatchProperty href -Pattern 'newtpro\.exe$' -PrefixDomain

New-NevergreenApp -Name 'Komodo Labs NEWT Pro' -Version $Version -Uri $URL32 -Architecture 'x86' -Type 'Exe'


text:
$URL64 = 'https://aka.ms/ssmsfullsetup'

$Version = Get-Version -Uri 'https://docs.microsoft.com/en-us/sql/ssms/download-sql-server-management-studio-ssms' -Pattern 'Release number: ((?:\d+\.)+\d+)'

New-NevergreenApp -Name 'Microsoft SSMS' -Version $Version -Uri $URL64 -Architecture 'x64' -Type 'Exe'


text:
$Version = Get-Version -Uri 'https://openvpn.net/community-downloads/' -Pattern 'OpenVPN ((?:\d+\.)+\d+\S*)'

$Releases = @(
    @{Architecture = 'x86'; Type = 'Msi'; Pattern = 'x86\.msi$'}
    @{Architecture = 'x64'; Type = 'Msi'; Pattern = 'amd64\.msi$'}
    @{Architecture = 'ARM64'; Type = 'Msi'; Pattern = 'arm64\.msi$'}
)

foreach ($Release in $Releases) {
        $URL = Get-Link -Uri 'https://openvpn.net/community-downloads/' -MatchProperty href -Pattern $Release.Pattern
        New-NevergreenApp -Name 'OpenVPNCommunity' -Version $Version -Uri $URL -Architecture $Release.Architecture -Type $Release.Type
}


text:
$Version = Get-Version -Uri 'https://www.microsoft.com/en-us/download/details.aspx?id=58158' -Pattern 'Version:<.+?>((?:\d+\.)+\d+)' #'Version:\s+</div><p>((?:\d+\.)+\d+)'
$URL32 = Get-Link -Uri 'https://www.microsoft.com/en-us/download/confirmation.aspx?id=58158' -MatchProperty href -Pattern '\.msi$'

New-NevergreenApp -Name 'Microsoft Power BI Report Builder' -Version $Version -Uri $URL32 -Architecture 'x86' -Type 'Msi'


text:
try {

    $URL = (Get-Link -Uri 'https://www.tmurgent.com/APPV/en/resources/tools-downloads/msix-tools/127-pullapps/511-pullapps-installation' -MatchProperty href -Pattern '\.zip$' -PrefixDomain | Resolve-Uri).Uri

    $Version = $URL | Get-Version

    New-NevergreenApp -Name 'TMurgent PullApps' -Version $Version -Uri $URL -Architecture 'x86' -Type 'Zip'

}
catch {
    Write-Error "$($MyInvocation.MyCommand): $($_.Exception.Message)"
}


text:
$Response = Invoke-RestMethod 'https://docs.pingidentity.com/api/khub/maps/v6hqiVhowIDI52XNglkuRw/pages' -DisableKeepAlive
$Version = (($Response.paginatedToc | Where-Object title -eq 'Release Notes').children | Where-Object title -eq 'PingID desktop app release notes').children[0].title | Get-Version

$URL = Get-Link -Uri 'https://www.pingidentity.com/en/resources/downloads/pingid.html' -MatchProperty outerHTML -Pattern 'download for windows'

New-NevergreenApp -Name 'PingID' -Version $Version -Uri $URL -Architecture 'x86' -Type 'Exe'


text:
try {

    $URL = Get-Link -Uri 'https://www.id.ee/en/article/install-id-software/' -MatchProperty href -Pattern '\.exe$'
    $Version = $URL | Get-Version

    New-NevergreenApp -Name 'RIA eID' -Version $Version -Uri $URL -Architecture 'Multi' -Type 'Exe'

}
catch {
    Write-Error "$($MyInvocation.MyCommand): $($_.Exception.Message)"
}


text:
$Version = Get-Version -Uri 'https://www.poly.com/gb/en/support/downloads-apps/hub-desktop' -Pattern 'Version ((?:\d+\.)+\d+)'

$URL32 = Get-Link -Uri 'https://www.poly.com/gb/en/support/downloads-apps/hub-desktop' -MatchProperty href -Pattern 'PlantronicsHubInstaller\.exe$' -PrefixDomain

New-NevergreenApp -Name 'Plantronics Hub' -Version $Version -Uri $URL32 -Architecture 'x86' -Type 'Exe'