Viewing entries tagged
games

PSElvUI, PowerShell ElvUI Updater Module

PSElvUI, PowerShell ElvUI Updater Module

What's it do?

This post is mostly for the World of Warcraft nerds out there. /raises hand
This module allows you to:

  • Check / Update ElvUI if there is a newer version

  • Install ElvUI if it is not already installed

  • Simply check if there is a new version, but do nothing else

Why? Isn't there already a tool for this?

There is a tool provided by the fine folks that created the AddOn, and it works great. I wanted a way to possible automate it (maybe a scheduled task on boot), and a fast way to check/update without having to login/launch anything other than PowerShell (which I happen to already have up most of the time anyway).

How can I install it?

Currently this is only working on Windows, with Mac support coming soon.

You can install the module from the PowerShell Gallery by using (as admin):

Install-Module PSElvUI

For more detailed instructions, check out the README.md here.

install.PNG

Using the module

Using the module is simple!

Check for update/don’t install:

Invoke-ElvUICheck -OnlyCheck -Verbose
checkonly.PNG

Check/Update if there is an update:

Invoke-ElvUICheck -Verbose
update.PNG

Install if it doesn’t exist:

Invoke-ElvUICheck -InstallIfDoesntExist -Verbose
install2.PNG

And that’s it! Leave a comment if you have any suggestions or ideas.

I gotta tissue if you have an issue, but also feel free to let me know what doesn’t work for you here.

Deep Dive

This module was also a way for me to get some Pester tests written. You can check out the code, as well as the tests written via the GitHub repo for this module.

Output for Invoke-Pester in the folder for this module:

pester.PNG

Get-WowInstallPath.tests.ps1

This file contains some very basic tests. It calls the functions and verifies that the paths returned exist via Pester’s exist function.

InModuleScope PSElvUi {

    describe 'Get-WowInstallPath' {

        $wowInfo = Get-WowInstallPath

        it 'Returns WoW Install Path' {

            $wowInfo.WoWInstallPath | Should Exist

        }

        it 'Finds addons folder in path' {

            $wowInfo.AddonsFolder | Should Exist

        }
    }
}

Get-WowInstallPath
This function uses the Windows registry to get the WoW install path. Mac support will do something different when it is added. Here is the code for now:

function Get-WoWInstallPath {
    [cmdletbinding()]
    param(

    )

    Write-Verbose "Attempting to find WoW install path..."

    try {

        $wowInstallPath = (Get-Item 'hklm:\SOFTWARE\WOW6432Node\Blizzard Entertainment\World of Warcraft').GetValue('InstallPath')
        $addonsFolder   = "$($wowInstallPath)Interface\AddOns" 

        $wowInstallInfo = [PSCustomObject]@{

            AddonsFolder   = $addonsFolder
            WowInstallPath = $wowInstallPath

        }

        return $wowInstallInfo
        
    }

    catch {

        $errorMessage = $_.Exception.Message 
        throw "Error determining WoW Install Path/ElvUi Version -> [$errorMessage]!"
        break

    }
}

It returns both the install path, and the addons folder location.

Finding the version number of ElvUI

Remote (Get-RemoteElvUiVersion)

The remote code check utilizes Invoke-WebRequest to get the version number. This method can fail when the website gets updated. There is no public API for this, so for now this is the method that works.

function Get-RemoteElvUiVersion {
    [cmdletbinding()]
    param(

    )
    
    try {
        
        $baseUrl      = 'https://www.tukui.org'
        $downloadPage = "$baseUrl/download.php?ui=elvui"
        $dlString     = '.+Download ElvUI.+'

        Write-Verbose "Attempting to retrieve ElvUI information from [$downloadPage]..."
        $downloadLink = "$baseUrl$(Invoke-WebRequest -Uri $downloadPage | 
                                    Select-Object -ExpandProperty Links | 
                                    Where-Object {
                                        $_.Outerhtml -match $dlString
                                    }                                   | 
                                    Select-Object -ExpandProperty href)" 
    
        $fileName             = $($downloadLink.Split('/')[4])
        [double]$elvUiVersion = $fileName.Split('-')[1].Replace('.zip','')
    
        $remoteElvInfo = [PSCustomObject]@{
    
            FileName     = $fileName
            Version      = $elvUiVersion
            DownloadLink = $downloadLink
    
        }
    
        return $remoteElvInfo 

    }
    catch {
        $errorMessage = $_.Exception.Message
        throw "Error getting remote ElvUI Information -> [$errorMessage]"
    }
}

Local (Get-LocalElvUiVersion)

The local version check loops through the contents of the ElvUI.toc file and matches on the ‘## Version”’ line. Then some string manipulation is used to grab the version. Error handling is in place to ensure issues are caught if they arise.

function Get-LocalElvUiVersion {
    [cmdletbinding()]
    param(
        [string]
        $addonsFolder
    )

    [double]$localVersion = 0.0

    if ((Test-Path $addonsFolder)) {

        try {

            $toc = Get-Content -Path "$addonsFolder\ElvUI\ElvUI.toc" -ErrorAction Stop

            $toc | ForEach-Object {

                if ($_ -match "## Version:") {
        
                    $localVersion = $_.Split(':')[1].trim()                    

                }
            }

            if ($localVersion -ne 0.0) {

                return $localVersion

            } else {

                throw 'No luck finding version in file'

            }
            

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

            throw "ElvUI addon not found!"

        }
        catch {            

            $errorMessage = $_.Exception.Message
            throw "Error determining ElvUI version -> [$errorMessage]!"

        }
        
    } else {

        throw "Unable to access WoW addon folder [$addonsFolder]!"

    }                
}

If you’ve gotten this far, I appreciate your interest! If you’d like more deep dives into the inner workings, leave a comment and let me know.