Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

KeePassUpdater Improvements #1

Open
Chefkeks opened this issue Dec 9, 2020 · 1 comment
Open

KeePassUpdater Improvements #1

Chefkeks opened this issue Dec 9, 2020 · 1 comment
Assignees
Labels
enhancement New feature or request

Comments

@Chefkeks
Copy link

Chefkeks commented Dec 9, 2020

Hey there,

thanks for that nice little KeePass + Plugins Powershell Update script - almost what I was looking for. Customized it a bit to fit all needs as I have several KeePass installations / portable versions flying around on my pc for several purposes (work, private, sports club, etc.) and with different needed plugins as well. Summarized:

  • Added a variable to specify whether the portable version is used or the full installed version
  • Changed C:\temp to simply use $env:temp
  • Moved registry settings to HKCU (so no admin right required as for HKLM)
  • Storing the path of the Keepass + Plugin name in the registry (e.g. when using different Keepass configuration on different folders / drives, so all plugins of all keepass installations get updated)
  • Added some basic outputs to tell non-techie users what is going on 😅
  • Getting the current KeePass version right from keepass.exe file info (productversion)

To make it a fully portable solution a shift from registry as storage location of the plugin versions to a text or local database file inside the portable keepass folder would be necessary - so that you can carry it on an external flash drive to another computer without loosing the version info. As registry is fine for me, I won't further improve it in that way, just mentioning it.

Anyway, wanted to share an example of my improvements for Keepass update itself and a single plugin - feel free to implement some or all my improvements.

Michael 🍪✌️

function Format-KeePass {
    param(
        [Parameter(Mandatory = $true, ValueFromPipeLine = $true)]
        [String]$update_information
    )

    # Save delimiter
    $delimiter = $update_information[0]

    # Split data on new line
    $split = $update_information.split([System.Environment]::NewLine)
    if($delimiter.length -gt 1) {
        $delimiter = $split[0][0]
    }

    $formated = @{}
    # Loop each line in data
    foreach($plugin in $split) {
        # Do not parse first and last line
        if(![bool]$plugin.StartsWith($delimiter)) {
            # Save plugin name and version
            $formated[$plugin.split($delimiter)[0]] = $plugin.split($delimiter)[1]
        }
    }

    return $formated
}

function Update-Plugin {
    param(
        [Parameter(Mandatory = $true)]
        [String]$update_uri,
        [Parameter(Mandatory = $true)]
        [String]$plugin_name,
        [Parameter(Mandatory = $true)]
        [String]$author,
        [Parameter(Mandatory = $true)]
        [String]$repo,
        [Parameter(Mandatory = $true)]
        [String]$keepass_dir,
        [String]$reg_path = 'HKCU:\SOFTWARE\KeePassPluginUpdater'
    )
    # Output
    Write-Output ""
    Write-Output "Plugin: $plugin_name"

    # Plugin dir
    $plugin_dir = "$keepass_dir\plugins"

    # Get plugin version data
    $plugin_version_data = Invoke-RestMethod -Uri $update_uri | Format-KeePass

    # Test if registry key exists
    if(-not (Test-Path $reg_path)) {
        # Create key
        New-Item -Path $reg_path -ItemType Directory
    }

    # Test if registry value exists
    if(-not [bool](Get-ItemProperty -Path $reg_path -Name "$keepass_dir\$plugin_name" -ErrorAction SilentlyContinue)) {
        # Create value
        Write-Output "Plugin added to the list!"
        New-ItemProperty -Path $reg_path -Name "$keepass_dir\$plugin_name" -Value 0 -PropertyType 'String' | Out-Null
    }

    # Get value and latest version
    $plugin_installed = Get-ItemPropertyValue -Path $reg_path -Name "$keepass_dir\$plugin_name"
    $plugin_available = $plugin_version_data[$plugin_name] | Out-String

    # Output
    Write-Output "Plugin version installed: $plugin_installed"
    Write-Output "Plugin version available: $plugin_available"

    # Compare value to latest version
    if($plugin_version_data[$plugin_name] -ne $plugin_installed) {
        # Get latest release from Github
        Write-Output "Getting latest plugin release info..."
        $release = Invoke-RestMethod "https://api.github.com/repos/$author/$repo/releases/latest"

        # Extract filename keep it the same
        $filename = $release.assets.browser_download_url -replace '.+\/(\w+\.plgx)', '$1'

        # Delete old file
        if(Test-Path "$plugin_dir\$filename") {
            Write-Output "Deleting old plugin file now..."
            Remove-Item -Path "$plugin_dir\$filename"
        }

        # Download plugin file and save it in keepass folder
        Write-Output "Downloading latest plugin file..."
        Invoke-WebRequest -Uri $release.assets.browser_download_url -OutFile "$plugin_dir\$filename"

        # Update value in versions file
        Set-ItemProperty -Path $reg_path -Name "$keepass_dir\$plugin_name" -Value $plugin_version_data[$plugin_name]
    }
}

function Is-Portable-Used {
    param(
        [Parameter(Mandatory = $true)]
        [String]$portable
    )
    # Portable Keepass
    if($portable -eq $true) {
        $keepass_dir = $PSScriptRoot

    # Installed Keepass
    } else {
        $keepass_dir = "${env:ProgramFiles(x86)}\KeePass Password Safe 2"
    }

    return $keepass_dir
}
# Output
Write-Output "Keepass Updater started!"
Write-Output ""

# Portable?
$portable = $true

# Portable or installed version
$keepass_dir = Is-Portable-Used $portable
Write-Output "Keepass Directory: $keepass_dir"

# Get Keepass version installed and avalable
$keepass_exe = "$keepass_dir\KeePass.exe"
$installed = (Get-ItemProperty $keepass_exe).VersionInfo.ProductVersion -replace '.0',''
$latest = (Invoke-RestMethod -Uri 'https://www.dominik-reichl.de/update/version2x.txt.gz' | Format-KeePass)['KeePass']

# Output
Write-Output "Keepass Version installed: $installed"
Write-Output "Keepass Version available: $latest"
Write-Output "Closing Keepass now..."
Write-Output ""

# Stop KeePass
Start-Process -FilePath $keepass_exe -ArgumentList '--exit-all'

if($installed -lt $latest) {
    # Use users temp folder
    $keepass_tmp = $env:TEMP

    # Portable Keepass
    if($portable -eq $true) {
        # Download
        Write-Output "Downloading Keepass Portable $latest"
        Invoke-WebRequest -Uri "https://sourceforge.net/projects/keepass/files/KeePass%202.x/$latest/KeePass-$latest.zip/download" -UserAgent [Microsoft.PowerShell.Commands.PSUserAgent]::FireFox -OutFile "$keepass_tmp\KeePass-$latest.zip"

        # Extract
        Write-Output "Extracting Keepass Portable $latest now..."
        Expand-Archive -LiteralPath "$keepass_tmp\KeePass-$latest.zip" -DestinationPath $keepass_dir -Force

        # Delete download
        Remove-Item -Path "$keepass_tmp\KeePass-$latest.zip"

    # Installed Keepass
    } else {
        # Download
        Write-Output "Downloading Keepass Installer $latest"
        Invoke-WebRequest -Uri "https://sourceforge.net/projects/keepass/files/KeePass%202.x/$latest/KeePass-$latest-Setup.exe/download" -UserAgent [Microsoft.PowerShell.Commands.PSUserAgent]::FireFox -OutFile "$keepass_tmp\KeePass-$latest.exe"
        
        # Install
        Write-Output "Installing Keepass $latest now..."
        Start-Process -FilePath "$keepass_tmp\KeePass-$latest.exe" -ArgumentList '/SILENT' -Wait

        # Delete download
        Remove-Item -Path "$keepass_tmp\KeePass-$latest.exe"
    }

    # Verify Keepass update
    $updated = (Get-ItemProperty $keepass_exe).VersionInfo.ProductVersion -replace '.0',''
    if ($updated -eq $latest) {
        Write-Output "Successfully updated Keepass to $latest!"
    } else {
        # Save foreground color
        $fc = $host.UI.RawUI.ForegroundColor

        # Set new color
        $host.UI.RawUI.ForegroundColor = 'red'

        # Output
        Write-Output "Error! Something went wrong updating Keepass!"

        # Restore the original color
        $host.UI.RawUI.ForegroundColor = $fc
    }
}

# Plugin updates
Write-Output "Checking for plugin updates now..."

$parameters = @{
    update_uri  = 'https://raw.githubusercontent.com/rookiestyle/keepassotp/master/version.info'
    plugin_name = 'KeePassOTP'
    author      = 'Rookiestyle'
    repo        = 'KeePassOTP'
    keepass_dir = $keepass_dir
}

Update-Plugin @parameters

# Output
Write-Output ""
Write-Output "Keepass Updater finished!"
Write-Output ""

# Start KeePass again
Read-Host -Prompt "Press Enter to start Keepass"
Start-Process -FilePath $keepass_exe
@ecspresso ecspresso self-assigned this Dec 15, 2020
@ecspresso ecspresso added the enhancement New feature or request label Dec 15, 2020
@ecspresso
Copy link
Owner

ecspresso commented Dec 15, 2020

Thanks for this, I haven't had the time to look into it yet but I will try to take the time soon.

To make it a fully portable solution a shift from registry as storage location of the plugin versions to a text or local database file inside the portable keepass folder would be necessary - so that you can carry it on an external flash drive to another computer without loosing the version info.

Should be possible to implement a switch of some kind or do a fallback, look for a file first and registry second.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants