diff --git a/.github/.powershell-psscriptanalyzer.psd1 b/.github/.powershell-psscriptanalyzer.psd1 index 6128b5c..84269ea 100644 --- a/.github/.powershell-psscriptanalyzer.psd1 +++ b/.github/.powershell-psscriptanalyzer.psd1 @@ -11,6 +11,10 @@ 'PSPossibleIncorrectComparisonWithNull', 'PSAvoidTrailingWhitespace', 'PSUseApprovedVerbs', - 'PSAvoidUsingWMICmdlet' + 'PSAvoidUsingWMICmdlet', + 'PSReviewUnusedParameter', + 'PSUseDeclaredVarsMoreThanAssignment', + 'PSUseShouldProcessForStateChangingFunctions', + 'PSUseDeclaredVarsMoreThanAssignments' ) } \ No newline at end of file diff --git a/.github/workflows/dependabot.yml b/.github/dependabot.yml similarity index 100% rename from .github/workflows/dependabot.yml rename to .github/dependabot.yml diff --git a/.github/workflows/CloseInactiveIssues.yml b/.github/workflows/CloseInactiveIssues.yml index 315c9e9..daad263 100644 --- a/.github/workflows/CloseInactiveIssues.yml +++ b/.github/workflows/CloseInactiveIssues.yml @@ -1,8 +1,11 @@ +--- name: Close inactive issues on: schedule: - cron: "30 1 * * *" +permissions: read-all + jobs: close-issues: runs-on: ubuntu-latest @@ -10,7 +13,7 @@ jobs: issues: write pull-requests: write steps: - - uses: actions/stale@v4 + - uses: actions/stale@v8 with: days-before-issue-stale: 30 days-before-issue-close: 14 diff --git a/.github/workflows/WAU-AutoCreatePreVersion.yml b/.github/workflows/WAU-AutoCreatePreVersion.yml new file mode 100644 index 0000000..953e187 --- /dev/null +++ b/.github/workflows/WAU-AutoCreatePreVersion.yml @@ -0,0 +1,102 @@ +--- +name: WAU - Auto Create Pre-Release Version + +on: + schedule: + - cron: "0 0 * * *" + +permissions: + contents: write + +jobs: + check_merged: + name: Compare latest merge and tag + runs-on: ubuntu-latest + outputs: + should_run: ${{ steps.should_run.outputs.SHOULD_RUN }} + steps: + - name: Checkout code + uses: actions/checkout@v3 + with: + fetch-depth: 0 + - name: Check if latest merged is older than latest tag + id: should_run + run: | + echo "Latest tag:" + git log --tags --pretty="%ci - %h - %s %d" -n 1 + LATEST_TAG_DATE=$(git log --tags -n 1 --pretty="%ct") + echo $LATEST_TAG_DATE + + echo "Latest merge:" + git log --merges --pretty="%ci - %h - %s %d" -n 1 + LATEST_MERGE_DATE=$(git log --merges -n 1 --pretty="%ct") + echo $LATEST_MERGE_DATE + + if [[ $LATEST_MERGE_DATE -gt $LATEST_TAG_DATE ]]; then + echo "Latest tag is older than latest merge. Nightly will be created." + echo "SHOULD_RUN=true" >> $GITHUB_OUTPUT + else + echo "Latest merge is not older than latest tag. No new release needed." + echo "SHOULD_RUN=false" >> $GITHUB_OUTPUT + fi + + build: + name: Create Release Asset + needs: [check_merged] + if: ${{ needs.check_merged.outputs.should_run == 'true' }} + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v3 + with: + lfs: "true" + fetch-depth: 0 + + - name: Auto Increment Semver Action + uses: MCKanpolat/auto-semver-action@1.0.9 + id: versioning + with: + releaseType: prerelease + incrementPerCommit: false + github_token: ${{ secrets.GITHUB_TOKEN }} + + - name: Next Release Number + id: WAU_version + run: | + echo "Next Release version: ${{ steps.versioning.outputs.version }}" + + - name: Overwrite Version.txt file + uses: DamianReeves/write-file-action@v1.2 + with: + path: Winget-AutoUpdate/Version.txt + write-mode: overwrite + contents: ${{ steps.versioning.outputs.version }} + + - name: Commit & Push + uses: actions-js/push@v1.4 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + branch: main + force: true + message: "Changed version to ${{ steps.versioning.outputs.version }}" + + - name: Build project + run: | + zip -r WAU Winget-AutoUpdate/* + zip -r WAU Winget-AutoUpdate-Install.ps1 + zip -r WAU excluded_apps.txt + zip -r WAU install.bat + zip -r WAU uninstall.bat + + - name: Create release + uses: "ncipollo/release-action@v1" + id: release + with: + tag: "v${{ steps.versioning.outputs.version }}" + prerelease: true + generateReleaseNotes: true + name: "v${{ steps.versioning.outputs.version }} [Nightly Build]" + artifacts: "WAU.zip" + + - name: URL to release + run: echo "Release -> ${{ steps.release.outputs.html_url }}" diff --git a/.github/workflows/WAU-CreateNewVersion.yml b/.github/workflows/WAU-CreateNewVersion.yml new file mode 100644 index 0000000..bf7dbd1 --- /dev/null +++ b/.github/workflows/WAU-CreateNewVersion.yml @@ -0,0 +1,71 @@ +--- +name: WAU - Create New Version + +on: + workflow_dispatch: + inputs: + version: + type: choice + default: "Patch" + description: Select next release type + options: + - Patch + - Minor + - Major + required: true + pre-release: + type: boolean + description: Set as Pre-release version + +permissions: + contents: write + +jobs: + build: + name: Create Release Asset + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v3 + with: + lfs: "true" + + - name: Auto Increment Semver Action + uses: MCKanpolat/auto-semver-action@1.0.9 + id: versioning + with: + releaseType: ${{ github.event.inputs.version }} + incrementPerCommit: false + github_token: ${{ secrets.GITHUB_TOKEN }} + + - name: Overwrite Version.txt file + uses: DamianReeves/write-file-action@v1.2 + with: + path: Winget-AutoUpdate/Version.txt + write-mode: overwrite + contents: "${{ steps.versioning.outputs.version }}" + + - name: Commit & Push + uses: actions-js/push@v1.4 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + branch: main + force: true + message: "Changed version to ${{ steps.versioning.outputs.version }}" + + - name: Build project + run: | + zip -r WAU Winget-AutoUpdate/* + zip -r WAU Winget-AutoUpdate-Install.ps1 + zip -r WAU excluded_apps.txt + zip -r WAU install.bat + zip -r WAU uninstall.bat + + - name: Create release + uses: "ncipollo/release-action@v1" + with: + tag: "v${{ steps.versioning.outputs.version }}" + prerelease: ${{ github.event.inputs.pre-release }} + generateReleaseNotes: true + name: "v${{ steps.versioning.outputs.version }}" + artifacts: "WAU.zip" diff --git a/.github/workflows/mega-linter.yml b/.github/workflows/mega-linter.yml index d5d6cc0..d3ae61f 100644 --- a/.github/workflows/mega-linter.yml +++ b/.github/workflows/mega-linter.yml @@ -5,7 +5,7 @@ name: MegaLinter on: # Trigger mega-linter at every push. Action will also be visible from Pull Requests to main - push: # Comment this line to trigger action only on pull-requests (not recommended if you don't pay for GH Actions) + #push: # Comment this line to trigger action only on pull-requests (not recommended if you don't pay for GH Actions) pull_request: branches: [master, main] @@ -41,16 +41,16 @@ jobs: id: ml # You can override MegaLinter flavor used to have faster performances # More info at https://megalinter.github.io/flavors/ - uses: megalinter/megalinter@v6 + uses: oxsecurity/megalinter@v6 env: # All available variables are described in documentation # https://megalinter.github.io/configuration/ - VALIDATE_ALL_CODEBASE: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }} # Validates all source when push on main, else just the git diff with main. Override with true if you always want to lint all sources + VALIDATE_ALL_CODEBASE: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }} # Validates all source when push on main, else just the git diff with main. Override with true if you always want to lint all sources GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} SPELL_CSPELL_CONFIG_FILE: .github/cspell.json POWERSHELL_POWERSHELL_CONFIG_FILE: .github/.powershell-psscriptanalyzer.psd1 - DISABLE_ERRORS_LINTERS: REPOSITORY_DEVSKIM,SPELL_CSPELL,SPELL_PROSELINT,COPYPASTE_JSCPD,MARKDOWN_MARKDOWN_LINK_CHECK - FILTER_REGEX_EXCLUDE: (.github/workflows/) + DISABLE_ERRORS_LINTERS: REPOSITORY_DEVSKIM,REPOSITORY_CHECKOV,REPOSITORY_GIT_DIFF,SPELL_CSPELL,SPELL_PROSELINT,COPYPASTE_JSCPD,MARKDOWN_MARKDOWN_LINK_CHECK + FILTER_REGEX_EXCLUDE: (workflows/) # Upload MegaLinter artifacts - name: Archive production artifacts @@ -67,7 +67,7 @@ jobs: - name: Create Pull Request with applied fixes id: cpr if: steps.ml.outputs.has_updated_sources == 1 && (env.APPLY_FIXES_EVENT == 'all' || env.APPLY_FIXES_EVENT == github.event_name) && env.APPLY_FIXES_MODE == 'pull_request' && (github.event_name == 'push' || github.event.pull_request.head.repo.full_name == github.repository) && !contains(github.event.head_commit.message, 'skip fix') - uses: peter-evans/create-pull-request@v4 + uses: peter-evans/create-pull-request@v5 with: token: ${{ secrets.GITHUB_TOKEN }} commit-message: "[MegaLinter] Apply linters automatic fixes" diff --git a/.github/workflows/powershell-tests.yaml b/.github/workflows/powershell-tests.yaml new file mode 100644 index 0000000..4936854 --- /dev/null +++ b/.github/workflows/powershell-tests.yaml @@ -0,0 +1,58 @@ +--- +name: WAU Powershell Test Runs + +# yamllint disable-line rule:truthy +on: + pull_request: + branches: [master, main] + workflow_dispatch: + +permissions: + contents: read + pull-requests: read + +jobs: + powershell-tests: + name: Pester test and PSScriptAnalyzer + runs-on: windows-latest + steps: + - name: Check out repository code + uses: actions/checkout@v3 + - name: Perform a Pester test for the WAU installation + shell: powershell + run: | + $command = New-PesterContainer -Path Winget-AutoUpdate-Install.ps1 -Data @{ Silent = $true } + Invoke-Pester -PassThru -Container $command -ErrorAction Continue + - name: Perform a Pester test for WAU run + shell: powershell + run: | + $command = New-PesterContainer -Path C:\ProgramData\Winget-AutoUpdate\user-run.ps1 + Invoke-Pester -PassThru -Container $command -ErrorAction Continue + #- name: Read WAU Log + # id: package + # uses: juliangruber/read-file-action@v1 + # with: + # path: 'C:\ProgramData\Winget-AutoUpdate\Logs\updates.log' + #- name: Display WAU Log + # run: type "${{ steps.package.outputs.content }}" + - name: Install PSScriptAnalyzer module from PSGallery + shell: powershell + run: | + Set-PSRepository PSGallery -InstallationPolicy Trusted + Install-Module PSScriptAnalyzer -ErrorAction Stop + - name: Lint with PSScriptAnalyzer + shell: powershell + run: | + Invoke-ScriptAnalyzer -Path *.ps1 -Recurse -Outvariable issues + $errors = $issues.Where({$_.Severity -eq 'Error'}) + $warnings = $issues.Where({$_.Severity -eq 'Warning'}) + if ($($errors.Count) -gt 0) { + $ErrorAction = "Stop" + } else { + $ErrorAction = "Continue" + } + if ($errors) { + Write-Error "There were $($errors.Count) errors and $($warnings.Count) warnings total." -ErrorAction $ErrorAction + } else { + Write-Output "There were $($errors.Count) errors and $($warnings.Count) warnings total." + } diff --git a/Policies/WAU.admx b/Policies/WAU.admx index 146524e..3106d8b 100644 --- a/Policies/WAU.admx +++ b/Policies/WAU.admx @@ -1,12 +1,13 @@ - + - + + @@ -99,6 +100,13 @@ + + + + + + + diff --git a/Policies/en-US/WAU.adml b/Policies/en-US/WAU.adml index c9545de..e9d1f05 100644 --- a/Policies/en-US/WAU.adml +++ b/Policies/en-US/WAU.adml @@ -1,11 +1,12 @@ - + WinGet-AutoUpdate WinGet-AutoUpdate GPO Management Winget-AutoUpdate Winget-AutoUpdate version 1.16.0 or later + Winget-AutoUpdate version 1.16.5 or later Activate WAU GPO Management This policy setting is an overriding toggle for GPO Management of Winget-AutoUpdate. Bypass Black/White list for User @@ -43,10 +44,16 @@ If this policy is disabled or not configured, the default is No. If "Application GPO Blacklist/Whitelist" is set in this GPO the Path can be: GPO If this policy is disabled or not configured, the default ListPath is used (WAU InstallLocation). - Get Mods from external Path (URL/UNC/Local) - If this policy is enabled, you can set a (URL/UNC/Local) Path to external mods other than the default. + Get Mods from external Path (URL/UNC/Local/AzureBlob) + If this policy is enabled, you can set a (URL/UNC/Local/AzureBlob) Path to external mods other than the default. -If this policy is disabled or not configured, the default ModsPath is used (WAU InstallLocation). +If this policy is disabled or not configured, the default ModsPath is used (WAU InstallLocation). + +Note: When set to 'AzureBlob', ensure you also configure 'Set Azure Blob URL with SAS token'. + Set Azure Blob URL with SAS Token + If this policy is enabled, you can set an Azure Storage Blob URL with SAS token for use with the 'Mods' feature. The URL must include the SAS token and have 'read' and 'list' permissions. + +If this policy is disabled or not configured, the value is blank and Azure Blob storage will NOT work. Notification Level If this policy is enabled, you can configure the Notification Level: 1. Full (Default) @@ -148,8 +155,13 @@ If this policy is disabled or not configured, the default size is used. - + + + + + + diff --git a/README.md b/README.md index 39c476a..aa7073e 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ This project uses the Winget tool to daily update apps (with system context) and ![image](https://user-images.githubusercontent.com/96626929/150645599-9460def4-0818-4fe9-819c-dd7081ff8447.png) ## Intallation -Just [download latest release (source code)](https://github.com/Romanitho/Winget-AutoUpdate/releases), unzip, run "install.bat" as admin to install by default. +Just [download latest release (WAU.zip)](https://github.com/Romanitho/Winget-AutoUpdate/releases/latest/download/WAU.zip), unzip, run "install.bat" as admin to install by default. ## Configurations ### Keep some apps out of Winget-AutoUpdate @@ -29,7 +29,8 @@ By default, scripts and components will be placed in ProgramData location (insid From version 1.9.0 (on new installations) WAU runs everyday at 6AM. You can now configure the frequency with `-UpdatesInterval` option (Daily, BiDaily, Weekly, BiWeekly or Monthly). You can also add `-UpdatesAtLogon` parameter to run at user logon and keep this option activated like previous versions (recommanded). ### Log location -You can find logs in install location, in logs folder. +You can find logs in install location, in logs folder. +If **Intune Management Extension** is installed, a **SymLink** (WAU-updates.log) is created under **C:\ProgramData\Microsoft\IntuneManagementExtension\Logs** ### "Unknown" App version As explained in this [post](https://github.com/microsoft/winget-cli/issues/1255), Winget cannot detect the current version of some installed apps. We decided to skip managing these apps with WAU to avoid retries each time WAU runs: @@ -96,12 +97,15 @@ Disable Winget-AutoUpdate update checking. By default, WAU auto updates if new v Use White List instead of Black List. This setting will not create the "excluded_apps.txt" but "included_apps.txt". **-ListPath** -Get Black/White List from external Path (**URL/UNC/GPO/Local**) - download/copy to Winget-AutoUpdate installation location if external list is newer. +Get Black/White List from external Path (**URL/UNC/Local/GPO**) - download/copy to Winget-AutoUpdate installation location if external list is newer. +**PATH** must end with a Directory, not a File... +...if the external Path is an **URL** and the web host doesn't respond with a date/time header for the file (i.e **GitHub**) then the file is always downloaded! + If `-ListPath` is set to **GPO** the Black/White List can be managed from within the GPO itself under **Application GPO Blacklist**/**Application GPO Whitelist**. Thanks to [Weatherlights](https://github.com/Weatherlights) in [#256 (reply in thread)](https://github.com/Romanitho/Winget-AutoUpdate/discussions/256#discussioncomment-4710599)! **-ModsPath** -Get Mods from external Path (**URL/UNC/Local**) - download/copy to `mods` in Winget-AutoUpdate installation location if external mods are newer. +Get Mods from external Path (**URL/UNC/Local/AzureBlob**) - download/copy to `mods` in Winget-AutoUpdate installation location if external mods are newer. For **URL**: This requires a site directory with **Directory Listing Enabled** and no index page overriding the listing of files (or an index page with href listing of all the **Mods** to be downloaded): ``` @@ -118,6 +122,11 @@ Validated on **IIS/Apache**. - The extension **.ps1** must be added as **MIME Types** (text/powershell-script) otherwise it's displayed in the listing but can't be opened - Files with special characters in the filename can't be opened by default from an IIS server - config must be administrated: **Enable Allow double escaping** in '**Request Filtering**' +For **AzureBlob**: This requires the parameter **-AzureBlobURL** to be set with an appropriate Azure Blob Storage URL including the SAS token. See **-AzureBlobURL** for more information. + +**-AzureBlobURL** +Used in conjunction with the **-ModsPath** parameter to provide the Azure Storage Blob URL with SAS token. The SAS token must, at a minimum, have 'Read' and 'List' permissions. It is recommended to set the permisions at the container level and rotate the SAS token on a regular basis. Ensure the container reflects the same structure as found under the initial `mods` folder. (From version 1.16.4). + **-InstallUserContext** Install WAU with system and **user** context executions (From version 1.15.3). diff --git a/Winget-AutoUpdate-Install.ps1 b/Winget-AutoUpdate-Install.ps1 index f46041b..7baece4 100644 --- a/Winget-AutoUpdate-Install.ps1 +++ b/Winget-AutoUpdate-Install.ps1 @@ -4,7 +4,7 @@ Configure Winget to daily update installed apps. .DESCRIPTION Install powershell scripts and scheduled task to daily run Winget upgrade and notify connected users. -Possible to exclude apps from auto-update +Posibility to exclude apps from auto-update https://github.com/Romanitho/Winget-AutoUpdate .PARAMETER Silent @@ -29,10 +29,13 @@ Disable Winget-AutoUpdate update checking. By default, WAU auto update if new ve Use White List instead of Black List. This setting will not create the "exclude_apps.txt" but "include_apps.txt" .PARAMETER ListPath -Get Black/White List from Path (URL/UNC/Local) +Get Black/White List from Path (URL/UNC/GPO/Local) .PARAMETER ModsPath -Get mods from Path (URL/UNC/Local) +Get mods from Path (URL/UNC/Local/AzureBlob) + +.PARAMETER AzureBlobURL +Set the Azure Storage Blob URL including the SAS token. The token requires at a minimum 'Read' and 'List' permissions. It is recommended to set this at the container level .PARAMETER Uninstall Remove scheduled tasks and scripts. @@ -93,6 +96,7 @@ param( [Parameter(Mandatory = $False)] [Alias('Path')] [String] $WingetUpdatePath = "$env:ProgramData\Winget-AutoUpdate", [Parameter(Mandatory = $False)] [Alias('List')] [String] $ListPath, [Parameter(Mandatory = $False)] [Alias('Mods')] [String] $ModsPath, + [Parameter(Mandatory = $False)] [Alias('AzureBlobURL')] [String] $AzureBlobSASURL, [Parameter(Mandatory = $False)] [Switch] $DoNotUpdate = $false, [Parameter(Mandatory = $False)] [Switch] $DisableWAUAutoUpdate = $false, [Parameter(Mandatory = $False)] [Switch] $RunOnMetered = $false, @@ -107,13 +111,10 @@ param( [Parameter(Mandatory = $False)] [DateTime] $UpdatesAtTime = ("06am"), [Parameter(Mandatory = $False)] [Switch] $BypassListForUsers = $false, [Parameter(Mandatory = $False)] [Switch] $InstallUserContext = $false, - [Parameter(Mandatory = $False)] [ValidateRange(0,99)] [int32] $MaxLogFiles = 3, + [Parameter(Mandatory = $False)] [ValidateRange(0, 99)] [int32] $MaxLogFiles = 3, [Parameter(Mandatory = $False)] [int64] $MaxLogSize = 1048576 # in bytes, default is 1048576 = 1 MB ) -<# APP INFO #> - -$WAUVersion = "1.15.3" <# FUNCTIONS #> @@ -158,7 +159,7 @@ function Install-Prerequisites { $SourceURL = "https://aka.ms/vs/17/release/VC_redist.$OSArch.exe" $Installer = $WingetUpdatePath + "\VC_redist.$OSArch.exe" $ProgressPreference = 'SilentlyContinue' - Invoke-WebRequest $SourceURL -OutFile (New-Item -Path $Installer -Force) + Invoke-WebRequest $SourceURL -UseBasicParsing -OutFile (New-Item -Path $Installer -Force) Write-host "-> Installing VC_redist.$OSArch.exe..." Start-Process -FilePath $Installer -Args "/quiet /norestart" -Wait Remove-Item $Installer -ErrorAction Ignore @@ -344,8 +345,6 @@ function Install-WingetAutoUpdate { New-ItemProperty $regPath -Name QuietUninstallString -Value "powershell.exe -noprofile -executionpolicy bypass -file `"$WingetUpdatePath\WAU-Uninstall.ps1`"" -Force | Out-Null New-ItemProperty $regPath -Name NoModify -Value 1 -Force | Out-Null New-ItemProperty $regPath -Name NoRepair -Value 1 -Force | Out-Null - New-ItemProperty $regPath -Name VersionMajor -Value ([version]$WAUVersion).Major -Force | Out-Null - New-ItemProperty $regPath -Name VersionMinor -Value ([version]$WAUVersion).Minor -Force | Out-Null New-ItemProperty $regPath -Name Publisher -Value "Romanitho" -Force | Out-Null New-ItemProperty $regPath -Name URLInfoAbout -Value "https://github.com/Romanitho/Winget-AutoUpdate" -Force | Out-Null New-ItemProperty $regPath -Name WAU_NotificationLevel -Value $NotificationLevel -Force | Out-Null @@ -368,21 +367,29 @@ function Install-WingetAutoUpdate { if ($ModsPath) { New-ItemProperty $regPath -Name WAU_ModsPath -Value $ModsPath -Force | Out-Null } + if ($AzureBlobSASURL) { + New-ItemProperty $regPath -Name WAU_AzureBlobSASURL -Value $AzureBlobSASURL -Force | Out-Null + } if ($BypassListForUsers) { New-ItemProperty $regPath -Name WAU_BypassListForUsers -Value 1 -PropertyType DWord -Force | Out-Null } - #Set ACL for users on logfile - $LogFile = "$WingetUpdatePath\logs\updates.log" - if (test-path $LogFile) { - $NewAcl = Get-Acl -Path $LogFile - $identity = New-Object System.Security.Principal.SecurityIdentifier S-1-5-11 - $fileSystemRights = "Modify" - $type = "Allow" - $fileSystemAccessRuleArgumentList = $identity, $fileSystemRights, $type - $fileSystemAccessRule = New-Object -TypeName System.Security.AccessControl.FileSystemAccessRule -ArgumentList $fileSystemAccessRuleArgumentList - $NewAcl.SetAccessRule($fileSystemAccessRule) - Set-Acl -Path $LogFile -AclObject $NewAcl + #Log file and symlink initialization + . "$WingetUpdatePath\functions\Start-Init.ps1" + Start-Init + + #Security check + Write-host "`nChecking Mods Directory:" -ForegroundColor Yellow + . "$WingetUpdatePath\functions\Invoke-ModsProtect.ps1" + $Protected = Invoke-ModsProtect "$WingetUpdatePath\mods" + if ($Protected -eq $True) { + Write-Host "The mods directory is now secured!`n" -ForegroundColor Green + } + elseif ($Protected -eq $False) { + Write-Host "The mods directory was already secured!`n" -ForegroundColor Green + } + else { + Write-Host "Error: The mods directory couldn't be verified as secured!`n" -ForegroundColor Red } #Create Shortcuts @@ -425,6 +432,9 @@ function Uninstall-WingetAutoUpdate { if (!$NoClean) { Remove-Item $InstallLocation -Force -Recurse + if (Test-Path "${env:ProgramData}\Microsoft\IntuneManagementExtension\Logs\WAU-updates.log") { + Remove-Item -Path "${env:ProgramData}\Microsoft\IntuneManagementExtension\Logs\WAU-updates.log" -Force -ErrorAction SilentlyContinue | Out-Null + } } else { #Keep critical files @@ -506,6 +516,12 @@ function Add-Shortcut ($Target, $Shortcut, $Arguments, $Icon, $Description) { $Shortcut.Save() } + +<# APP INFO #> + +$WAUVersion = Get-Content "$PSScriptRoot\Winget-AutoUpdate\Version.txt" -ErrorAction SilentlyContinue + + <# MAIN #> #If running as a 32-bit process on an x64 system, re-launch as a 64-bit process @@ -540,5 +556,6 @@ else { Uninstall-WingetAutoUpdate } +Remove-Item "$WingetUpdatePath\Version.txt" -Force Write-host "`nEnd of process." -ForegroundColor Cyan Start-Sleep 3 diff --git a/Winget-AutoUpdate/User-Run.ps1 b/Winget-AutoUpdate/User-Run.ps1 index a8106dc..a3b753c 100644 --- a/Winget-AutoUpdate/User-Run.ps1 +++ b/Winget-AutoUpdate/User-Run.ps1 @@ -55,7 +55,7 @@ if ($Logs) { #Not available yet $Message = $NotifLocale.local.outputs.output[5].message $MessageType = "warning" - Start-NotifTask -Message $Message -MessageType $MessageType + Start-NotifTask -Message $Message -MessageType $MessageType -UserRun } } elseif ($Help) { @@ -79,7 +79,7 @@ else { if (Test-WAUisRunning) { $Message = $NotifLocale.local.outputs.output[8].message $MessageType = "warning" - Start-NotifTask -Message $Message -MessageType $MessageType -Button1Text $Button1Text -Button1Action $OnClickAction -ButtonDismiss + Start-NotifTask -Message $Message -MessageType $MessageType -Button1Text $Button1Text -Button1Action $OnClickAction -ButtonDismiss -UserRun break } #Run scheduled task @@ -87,7 +87,7 @@ else { #Starting check - Send notification $Message = $NotifLocale.local.outputs.output[6].message $MessageType = "info" - Start-NotifTask -Message $Message -MessageType $MessageType -Button1Text $Button1Text -Button1Action $OnClickAction -ButtonDismiss + Start-NotifTask -Message $Message -MessageType $MessageType -Button1Text $Button1Text -Button1Action $OnClickAction -ButtonDismiss -UserRun #Sleep until the task is done While (Test-WAUisRunning) { Start-Sleep 3 @@ -105,12 +105,12 @@ else { $MessageType = "success" $Message = $NotifLocale.local.outputs.output[9].message } - Start-NotifTask -Message $Message -MessageType $MessageType -Button1Text $Button1Text -Button1Action $OnClickAction -ButtonDismiss + Start-NotifTask -Message $Message -MessageType $MessageType -Button1Text $Button1Text -Button1Action $OnClickAction -ButtonDismiss -UserRun } catch { #Check failed - Just send notification $Message = $NotifLocale.local.outputs.output[7].message $MessageType = "error" - Start-NotifTask -Message $Message -MessageType $MessageType -Button1Text $Button1Text -Button1Action $OnClickAction -ButtonDismiss + Start-NotifTask -Message $Message -MessageType $MessageType -Button1Text $Button1Text -Button1Action $OnClickAction -ButtonDismiss -UserRun } } diff --git a/Winget-AutoUpdate/Version.txt b/Winget-AutoUpdate/Version.txt new file mode 100644 index 0000000..250f359 --- /dev/null +++ b/Winget-AutoUpdate/Version.txt @@ -0,0 +1 @@ +1.17.4 \ No newline at end of file diff --git a/Winget-AutoUpdate/WAU-Uninstall.ps1 b/Winget-AutoUpdate/WAU-Uninstall.ps1 index a628626..44209c6 100644 --- a/Winget-AutoUpdate/WAU-Uninstall.ps1 +++ b/Winget-AutoUpdate/WAU-Uninstall.ps1 @@ -3,7 +3,7 @@ Uninstall Winget-AutoUpdate .DESCRIPTION -Uninstall Winget-AutoUpdate (DEFAULT: clean old install) +Uninstalls Winget-AutoUpdate (DEFAULT: clean old install) https://github.com/Romanitho/Winget-AutoUpdate .PARAMETER NoClean diff --git a/Winget-AutoUpdate/Winget-Notify.ps1 b/Winget-AutoUpdate/Winget-Notify.ps1 index d4a90c2..de22ef7 100644 --- a/Winget-AutoUpdate/Winget-Notify.ps1 +++ b/Winget-AutoUpdate/Winget-Notify.ps1 @@ -1,4 +1,4 @@ -#Send Notif Script +#Send Notify Script #get xml notif config $WAUinstalledPath = Get-ItemPropertyValue -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Winget-AutoUpdate\" -Name InstallLocation diff --git a/Winget-AutoUpdate/Winget-Upgrade.ps1 b/Winget-AutoUpdate/Winget-Upgrade.ps1 index f6434e4..3b2e8e0 100644 --- a/Winget-AutoUpdate/Winget-Upgrade.ps1 +++ b/Winget-AutoUpdate/Winget-Upgrade.ps1 @@ -1,6 +1,6 @@ <# LOAD FUNCTIONS #> -#Get Working Dir +#Get the Working Dir $Script:WorkingDir = $PSScriptRoot #Get Functions Get-ChildItem "$WorkingDir\functions" | ForEach-Object { . $_.FullName } @@ -19,17 +19,17 @@ $Script:WAUConfig = Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\Cur #Log running context and more... if ($IsSystem) { - Write-Log "Running in System context" + Write-ToLog "Running in System context" #Get and set Domain/Local Policies (GPO) $ActivateGPOManagement, $ChangedSettings = Get-Policies if ($ActivateGPOManagement) { - Write-Log "Activated WAU GPO Management detected, comparing..." + Write-ToLog "Activated WAU GPO Management detected, comparing..." if ($null -ne $ChangedSettings -and $ChangedSettings -ne 0) { - Write-Log "Changed settings detected and applied" "Yellow" + Write-ToLog "Changed settings detected and applied" "Yellow" } else { - Write-Log "No Changed settings detected" "Yellow" + Write-ToLog "No Changed settings detected" "Yellow" } } @@ -54,7 +54,7 @@ if ($IsSystem) { #LogRotation if System $LogRotate = Invoke-LogRotation $LogFile $MaxLogFiles $MaxLogSize if ($LogRotate -eq $False) { - Write-Log "An Exception occured during Log Rotation..." + Write-ToLog "An Exception occured during Log Rotation..." } #Run post update actions if necessary if run as System @@ -66,12 +66,12 @@ if ($IsSystem) { Add-ScopeMachine $SettingsPath } else { - Write-Log "Running in User context" + Write-ToLog "Running in User context" } #Get Notif Locale function $LocaleDisplayName = Get-NotifLocale -Write-Log "Notification Level: $($WAUConfig.WAU_NotificationLevel). Notification Language: $LocaleDisplayName" "Cyan" +Write-ToLog "Notification Level: $($WAUConfig.WAU_NotificationLevel). Notification Language: $LocaleDisplayName" "Cyan" #Check network connectivity if (Test-Network) { @@ -81,26 +81,26 @@ if (Test-Network) { if ($TestWinget) { #Get Current Version $WAUCurrentVersion = $WAUConfig.DisplayVersion - Write-Log "WAU current version: $WAUCurrentVersion" + Write-ToLog "WAU current version: $WAUCurrentVersion" if ($IsSystem) { #Check if WAU update feature is enabled or not if run as System $WAUDisableAutoUpdate = $WAUConfig.WAU_DisableAutoUpdate #If yes then check WAU update if run as System if ($WAUDisableAutoUpdate -eq 1) { - Write-Log "WAU AutoUpdate is Disabled." "Grey" + Write-ToLog "WAU AutoUpdate is Disabled." "Gray" } else { - Write-Log "WAU AutoUpdate is Enabled." "Green" + Write-ToLog "WAU AutoUpdate is Enabled." "Green" #Get Available Version - $WAUAvailableVersion = Get-WAUAvailableVersion + $Script:WAUAvailableVersion = Get-WAUAvailableVersion #Compare - if ([version]$WAUAvailableVersion -gt [version]$WAUCurrentVersion) { + if ([version]$WAUAvailableVersion.Replace("-", ".") -ne [version]$WAUCurrentVersion.Replace("-", ".")) { #If new version is available, update it - Write-Log "WAU Available version: $WAUAvailableVersion" "Yellow" + Write-ToLog "WAU Available version: $WAUAvailableVersion" "Yellow" Update-WAU } else { - Write-Log "WAU is up to date." "Green" + Write-ToLog "WAU is up to date." "Green" } } @@ -111,25 +111,36 @@ if (Test-Network) { #Get External ListPath if run as System if ($WAUConfig.WAU_ListPath) { - Write-Log "WAU uses External Lists from: $($WAUConfig.WAU_ListPath.TrimEnd(" ", "\", "/"))" - if ($($WAUConfig.WAU_ListPath) -ne "GPO") { - $NewList = Test-ListPath $WAUConfig.WAU_ListPath.TrimEnd(" ", "\", "/") $WAUConfig.WAU_UseWhiteList $WAUConfig.InstallLocation.TrimEnd(" ", "\") + $ListPathClean = $($WAUConfig.WAU_ListPath.TrimEnd(" ", "\", "/")) + Write-ToLog "WAU uses External Lists from: $ListPathClean" + if ($ListPathClean -ne "GPO") { + $NewList = Test-ListPath $ListPathClean $WAUConfig.WAU_UseWhiteList $WAUConfig.InstallLocation.TrimEnd(" ", "\") if ($ReachNoPath) { - Write-Log "Couldn't reach/find/compare/copy from $($WAUConfig.WAU_ListPath.TrimEnd(" ", "\", "/"))..." "Red" + Write-ToLog "Couldn't reach/find/compare/copy from $ListPathClean..." "Red" + if ($ListPathClean -notlike "http*") { + if (Test-Path -Path "$ListPathClean" -PathType Leaf) { + Write-ToLog "PATH must end with a Directory, not a File..." "Red" + } + } + else { + if ($ListPathClean -match "_apps.txt") { + Write-ToLog "PATH must end with a Directory, not a File..." "Red" + } + } $Script:ReachNoPath = $False } if ($NewList) { - Write-Log "Newer List downloaded/copied to local path: $($WAUConfig.InstallLocation.TrimEnd(" ", "\"))" "Yellow" + Write-ToLog "Newer List downloaded/copied to local path: $($WAUConfig.InstallLocation.TrimEnd(" ", "\"))" "Yellow" } else { if ($WAUConfig.WAU_UseWhiteList -and (Test-Path "$WorkingDir\included_apps.txt")) { - Write-Log "List (white) is up to date." "Green" + Write-ToLog "List (white) is up to date." "Green" } elseif (!$WAUConfig.WAU_UseWhiteList -and (Test-Path "$WorkingDir\excluded_apps.txt")) { - Write-Log "List (black) is up to date." "Green" + Write-ToLog "List (black) is up to date." "Green" } else { - Write-Log "Critical: White/Black List doesn't exist, exiting..." "Red" + Write-ToLog "Critical: White/Black List doesn't exist, exiting..." "Red" New-Item "$WorkingDir\logs\error.txt" -Value "White/Black List doesn't exist" -Force Exit 1 } @@ -139,25 +150,31 @@ if (Test-Network) { #Get External ModsPath if run as System if ($WAUConfig.WAU_ModsPath) { - Write-Log "WAU uses External Mods from: $($WAUConfig.WAU_ModsPath.TrimEnd(" ", "\", "/"))" - $NewMods, $DeletedMods = Test-ModsPath $WAUConfig.WAU_ModsPath.TrimEnd(" ", "\", "/") $WAUConfig.InstallLocation.TrimEnd(" ", "\") + $ModsPathClean = $($WAUConfig.WAU_ModsPath.TrimEnd(" ", "\", "/")) + Write-ToLog "WAU uses External Mods from: $ModsPathClean" + if ($WAUConfig.WAU_AzureBlobSASURL) { + $NewMods, $DeletedMods = Test-ModsPath $ModsPathClean $WAUConfig.InstallLocation.TrimEnd(" ", "\") $WAUConfig.WAU_AzureBlobSASURL.TrimEnd(" ") + } + else { + $NewMods, $DeletedMods = Test-ModsPath $ModsPathClean $WAUConfig.InstallLocation.TrimEnd(" ", "\") + } if ($ReachNoPath) { - Write-Log "Couldn't reach/find/compare/copy from $($WAUConfig.WAU_ModsPath.TrimEnd(" ", "\", "/"))..." "Red" + Write-ToLog "Couldn't reach/find/compare/copy from $ModsPathClean..." "Red" $Script:ReachNoPath = $False } if ($NewMods -gt 0) { - Write-Log "$NewMods newer Mods downloaded/copied to local path: $($WAUConfig.InstallLocation.TrimEnd(" ", "\"))\mods" "Yellow" + Write-ToLog "$NewMods newer Mods downloaded/copied to local path: $($WAUConfig.InstallLocation.TrimEnd(" ", "\"))\mods" "Yellow" } else { if (Test-Path "$WorkingDir\mods\*.ps1") { - Write-Log "Mods are up to date." "Green" + Write-ToLog "Mods are up to date." "Green" } else { - Write-Log "No Mods are implemented..." "Yellow" + Write-ToLog "No Mods are implemented..." "Yellow" } } if ($DeletedMods -gt 0) { - Write-Log "$DeletedMods Mods deleted (not externally managed) from local path: $($WAUConfig.InstallLocation.TrimEnd(" ", "\"))\mods" "Red" + Write-ToLog "$DeletedMods Mods deleted (not externally managed) from local path: $($WAUConfig.InstallLocation.TrimEnd(" ", "\"))\mods" "Red" } } } @@ -168,12 +185,12 @@ if (Test-Network) { #Get White or Black list if ($WAUConfig.WAU_UseWhiteList -eq 1) { - Write-Log "WAU uses White List config" + Write-ToLog "WAU uses White List config" $toUpdate = Get-IncludedApps $UseWhiteList = $true } else { - Write-Log "WAU uses Black List config" + Write-ToLog "WAU uses Black List config" $toSkip = Get-ExcludedApps } @@ -182,7 +199,7 @@ if (Test-Network) { if ($UseWhiteList) { $WhiteList = $toUpdate.GetUpperBound(0) if ($null -eq $WhiteList) { - Write-Log "Critical: Whitelist doesn't exist in GPO, exiting..." "Red" + Write-ToLog "Critical: Whitelist doesn't exist in GPO, exiting..." "Red" New-Item "$WorkingDir\logs\error.txt" -Value "Whitelist doesn't exist in GPO" -Force Exit 1 } @@ -191,7 +208,7 @@ if (Test-Network) { else { $BlackList = $toSkip.GetUpperBound(0) if ($null -eq $BlackList) { - Write-Log "Critical: Blacklist doesn't exist in GPO, exiting..." "Red" + Write-ToLog "Critical: Blacklist doesn't exist in GPO, exiting..." "Red" New-Item "$WorkingDir\logs\error.txt" -Value "Blacklist doesn't exist in GPO" -Force Exit 1 } @@ -200,114 +217,114 @@ if (Test-Network) { } #Get outdated Winget packages - Write-Log "Checking application updates on Winget Repository..." "yellow" + Write-ToLog "Checking application updates on Winget Repository..." "yellow" $outdated = Get-WingetOutdatedApps - #If something is wrong with the winget source, exit - if ($outdated -like "Problem:*") { - Write-Log "Critical: An error occured, exiting..." "red" - Write-Log "$outdated" "red" - New-Item "$WorkingDir\logs\error.txt" -Value "$outdated" -Force - Exit 1 + #If something unusual happened + if ($outdated -like "An unusual*") { + Write-ToLog "$outdated" "cyan" + $outdated = $False } - #Log list of app to update - foreach ($app in $outdated) { - #List available updates - $Log = "-> Available update : $($app.Name). Current version : $($app.Version). Available version : $($app.AvailableVersion)." - $Log | Write-host - $Log | out-file -filepath $LogFile -Append - } + #Run only if $outdated is populated! + if ($outdated) { + #Log list of app to update + foreach ($app in $outdated) { + #List available updates + $Log = "-> Available update : $($app.Name). Current version : $($app.Version). Available version : $($app.AvailableVersion)." + $Log | Write-host + $Log | out-file -filepath $LogFile -Append + } #Count good update installations $Script:InstallOK = 0 - #Trick under user context when -BypassListForUsers is used - if ($IsSystem -eq $false -and $WAUConfig.WAU_BypassListForUsers -eq $true) { - Write-Log "Bypass system list in user context is Enabled." - $UseWhiteList = $false - $toSkip = $null - } + #Trick under user context when -BypassListForUsers is used + if ($IsSystem -eq $false -and $WAUConfig.WAU_BypassListForUsers -eq $true) { + Write-ToLog "Bypass system list in user context is Enabled." + $UseWhiteList = $false + $toSkip = $null + } - #If White List - if ($UseWhiteList) { - #For each app, notify and update - foreach ($app in $outdated) { - if (($toUpdate -contains $app.Id) -and $($app.Version) -ne "Unknown") { - Update-App $app - } - #if current app version is unknown - elseif ($($app.Version) -eq "Unknown") { - Write-Log "$($app.Name) : Skipped upgrade because current version is 'Unknown'" "Gray" - } - #if app is in "excluded list" - else { - Write-Log "$($app.Name) : Skipped upgrade because it is not in the included app list" "Gray" + #If White List + if ($UseWhiteList) { + #For each app, notify and update + foreach ($app in $outdated) { + if (($toUpdate -contains $app.Id) -and $($app.Version) -ne "Unknown") { + Update-App $app + } + #if current app version is unknown + elseif ($($app.Version) -eq "Unknown") { + Write-ToLog "$($app.Name) : Skipped upgrade because current version is 'Unknown'" "Gray" + } + #if app is in "excluded list" + else { + Write-ToLog "$($app.Name) : Skipped upgrade because it is not in the included app list" "Gray" + } } } - } - #If Black List or default - else { - #For each app, notify and update - foreach ($app in $outdated) { - if (-not ($toSkip -contains $app.Id) -and $($app.Version) -ne "Unknown") { - Update-App $app - } - #if current app version is unknown - elseif ($($app.Version) -eq "Unknown") { - Write-Log "$($app.Name) : Skipped upgrade because current version is 'Unknown'" "Gray" - } - #if app is in "excluded list" - else { - Write-Log "$($app.Name) : Skipped upgrade because it is in the excluded app list" "Gray" + #If Black List or default + else { + #For each app, notify and update + foreach ($app in $outdated) { + if (-not ($toSkip -contains $app.Id) -and $($app.Version) -ne "Unknown") { + Update-App $app + } + #if current app version is unknown + elseif ($($app.Version) -eq "Unknown") { + Write-ToLog "$($app.Name) : Skipped upgrade because current version is 'Unknown'" "Gray" + } + #if app is in "excluded list" + else { + Write-ToLog "$($app.Name) : Skipped upgrade because it is in the excluded app list" "Gray" + } } } + + if ($InstallOK -gt 0) { + Write-ToLog "$InstallOK apps updated ! No more update." "Green" + } } - if ($InstallOK -gt 0) { - Write-Log "$InstallOK apps updated ! No more update." "Green" - } - if ($InstallOK -eq 0) { - Write-Log "No new update." "Green" + if ($InstallOK -eq 0 -or !$InstallOK) { + Write-ToLog "No new update." "Green" } #Check if any user is logged on if System and run User task (if installed) if ($IsSystem) { #User check routine from: https://stackoverflow.com/questions/23219718/powershell-script-to-see-currently-logged-in-users-domain-and-machine-status $explorerprocesses = @(Get-WmiObject -Query "Select * FROM Win32_Process WHERE Name='explorer.exe'" -ErrorAction SilentlyContinue) - If ($explorerprocesses.Count -eq 0) - { - Write-Log "No explorer process found / Nobody interactively logged on..." + If ($explorerprocesses.Count -eq 0) { + Write-ToLog "No explorer process found / Nobody interactively logged on..." } - Else - { + Else { #Run WAU in user context if the user task exist $UserScheduledTask = Get-ScheduledTask -TaskName "Winget-AutoUpdate-UserContext" -ErrorAction SilentlyContinue if ($UserScheduledTask) { #Get Winget system apps to excape them befor running user context - Write-Log "User logged on, get a list of installed Winget apps in System context..." + Write-ToLog "User logged on, get a list of installed Winget apps in System context..." Get-WingetSystemApps #Run user context scheduled task - Write-Log "Starting WAU in User context" + Write-ToLog "Starting WAU in User context" Start-ScheduledTask $UserScheduledTask.TaskName -ErrorAction SilentlyContinue Exit 0 } - elseif (!$UserScheduledTask){ - Write-Log "User context execution not installed..." + elseif (!$UserScheduledTask) { + Write-ToLog "User context execution not installed..." } } } } else { - Write-Log "Critical: Winget not installed or detected, exiting..." "red" + Write-ToLog "Critical: Winget not installed or detected, exiting..." "red" New-Item "$WorkingDir\logs\error.txt" -Value "Winget not installed or detected" -Force - Write-Log "End of process!" "Cyan" + Write-ToLog "End of process!" "Cyan" Exit 1 } } #End -Write-Log "End of process!" "Cyan" +Write-ToLog "End of process!" "Cyan" Start-Sleep 3 diff --git a/Winget-AutoUpdate/functions/Add-ScopeMachine.ps1 b/Winget-AutoUpdate/functions/Add-ScopeMachine.ps1 index dfdb145..44bb7e4 100644 --- a/Winget-AutoUpdate/functions/Add-ScopeMachine.ps1 +++ b/Winget-AutoUpdate/functions/Add-ScopeMachine.ps1 @@ -1,4 +1,4 @@ -#Function to configure prefered scope option as Machine +#Function to configure the prefered scope option as Machine function Add-ScopeMachine ($SettingsPath) { if (Test-Path $SettingsPath) { diff --git a/Winget-AutoUpdate/functions/Add-Shortcut.ps1 b/Winget-AutoUpdate/functions/Add-Shortcut.ps1 index 3feb396..98b6e77 100644 --- a/Winget-AutoUpdate/functions/Add-Shortcut.ps1 +++ b/Winget-AutoUpdate/functions/Add-Shortcut.ps1 @@ -1,4 +1,4 @@ -#Function for creating shortcuts +#Function to create shortcuts function Add-Shortcut ($Target, $Shortcut, $Arguments, $Icon, $Description) { $WScriptShell = New-Object -ComObject WScript.Shell $Shortcut = $WScriptShell.CreateShortcut($Shortcut) diff --git a/Winget-AutoUpdate/functions/Get-AZCopy.ps1 b/Winget-AutoUpdate/functions/Get-AZCopy.ps1 new file mode 100644 index 0000000..e6f7d54 --- /dev/null +++ b/Winget-AutoUpdate/functions/Get-AZCopy.ps1 @@ -0,0 +1,50 @@ +#Function to get AZCopy, if it doesn't exist and update it, if it does + +Function Get-AZCopy ($WingetUpdatePath) { + + $AZCopyLink = (Invoke-WebRequest -Uri https://aka.ms/downloadazcopy-v10-windows -UseBasicParsing -MaximumRedirection 0 -ErrorAction SilentlyContinue).headers.location + $AZCopyVersionRegex = [regex]::new("(\d+\.\d+\.\d+)") + $AZCopyLatestVersion = $AZCopyVersionRegex.Match($AZCopyLink).Value + + if ($null -eq $AZCopyLatestVersion -or "" -eq $AZCopyLatestVersion) { + $AZCopyLatestVersion = "0.0.0" + } + + if (Test-Path -Path "$WingetUpdatePath\azcopy.exe" -PathType Leaf) { + $AZCopyCurrentVersion = & "$WingetUpdatePath\azcopy.exe" -v + $AZCopyCurrentVersion = $AZCopyVersionRegex.Match($AZCopyCurrentVersion).Value + Write-ToLog "AZCopy version $AZCopyCurrentVersion found" + } + else { + Write-ToLog "AZCopy not already installed" + $AZCopyCurrentVersion = "0.0.0" + } + + if (([version] $AZCopyCurrentVersion) -lt ([version] $AZCopyLatestVersion)) { + Write-ToLog "Installing version $AZCopyLatestVersion of AZCopy" + Invoke-WebRequest -Uri $AZCopyLink -UseBasicParsing -OutFile "$WingetUpdatePath\azcopyv10.zip" + Write-ToLog "Extracting AZCopy zip file" + + Expand-archive -Path "$WingetUpdatePath\azcopyv10.zip" -Destinationpath "$WingetUpdatePath" -Force + + $AZCopyPathSearch = Resolve-Path -path "$WingetUpdatePath\azcopy_*" + + if ($AZCopyPathSearch -is [array]) { + $AZCopyEXEPath = $AZCopyPathSearch[$AZCopyPathSearch.Length - 1] + } + else { + $AZCopyEXEPath = $AZCopyPathSearch + } + + Write-ToLog "Copying 'azcopy.exe' to main folder" + Copy-Item "$AZCopyEXEPath\azcopy.exe" -Destination "$WingetUpdatePath\" + + Write-ToLog "Removing temporary AZCopy files" + Remove-Item -Path $AZCopyEXEPath -Recurse + Remove-Item -Path "$WingetUpdatePath\azcopyv10.zip" + + $AZCopyCurrentVersion = & "$WingetUpdatePath\azcopy.exe" -v + $AZCopyCurrentVersion = $AZCopyVersionRegex.Match($AZCopyCurrentVersion).Value + Write-ToLog "AZCopy version $AZCopyCurrentVersion installed" + } +} \ No newline at end of file diff --git a/Winget-AutoUpdate/functions/Get-AppInfo.ps1 b/Winget-AutoUpdate/functions/Get-AppInfo.ps1 index 62a45f2..747a818 100644 --- a/Winget-AutoUpdate/functions/Get-AppInfo.ps1 +++ b/Winget-AutoUpdate/functions/Get-AppInfo.ps1 @@ -1,4 +1,4 @@ -#Get App Info +#Get the winget App Information Function Get-AppInfo ($AppID) { #Get AppID Info diff --git a/Winget-AutoUpdate/functions/Get-ExcludedApps.ps1 b/Winget-AutoUpdate/functions/Get-ExcludedApps.ps1 index ff6878a..0212e5c 100644 --- a/Winget-AutoUpdate/functions/Get-ExcludedApps.ps1 +++ b/Winget-AutoUpdate/functions/Get-ExcludedApps.ps1 @@ -1,26 +1,26 @@ -#Function to get Black List apps +#Function to get the Block List apps function Get-ExcludedApps { if ($GPOList) { - + if (Test-Path "HKLM:\SOFTWARE\Policies\Romanitho\Winget-AutoUpdate\BlackList") { $Key = 'HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Romanitho\Winget-AutoUpdate\BlackList\' $ValueNames = (Get-Item -Path "HKLM:\SOFTWARE\Policies\Romanitho\Winget-AutoUpdate\BlackList").Property - + foreach ($ValueName in $ValueNames) { $AppIDs = [Microsoft.Win32.Registry]::GetValue($Key, $ValueName, $false) [PSCustomObject]@{ Value = $ValueName - Data = $AppIDs.Trim() + Data = $AppIDs.Trim() } } - + } return $AppIDs - + } elseif (Test-Path "$WorkingDir\excluded_apps.txt") { diff --git a/Winget-AutoUpdate/functions/Get-IncludedApps.ps1 b/Winget-AutoUpdate/functions/Get-IncludedApps.ps1 index c4cb053..ae2a8ad 100644 --- a/Winget-AutoUpdate/functions/Get-IncludedApps.ps1 +++ b/Winget-AutoUpdate/functions/Get-IncludedApps.ps1 @@ -1,4 +1,4 @@ -#Function to get White List apps +#Function to get the allow List apps function Get-IncludedApps { @@ -9,15 +9,15 @@ function Get-IncludedApps { $Key = 'HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Romanitho\Winget-AutoUpdate\WhiteList\' $ValueNames = (Get-Item -Path "HKLM:\SOFTWARE\Policies\Romanitho\Winget-AutoUpdate\WhiteList").Property - + foreach ($ValueName in $ValueNames) { $AppIDs = [Microsoft.Win32.Registry]::GetValue($Key, $ValueName, $false) [PSCustomObject]@{ Value = $ValueName - Data = $AppIDs.Trim() + Data = $AppIDs.Trim() } } - + } return $AppIDs diff --git a/Winget-AutoUpdate/functions/Get-NotifLocale.ps1 b/Winget-AutoUpdate/functions/Get-NotifLocale.ps1 index fb481e7..f0bd3a2 100644 --- a/Winget-AutoUpdate/functions/Get-NotifLocale.ps1 +++ b/Winget-AutoUpdate/functions/Get-NotifLocale.ps1 @@ -1,9 +1,9 @@ -#Function to get locale file for Notification. +#Function to get the locale file for notifications Function Get-NotifLocale { #Get OS locale - $OSLocale = (Get-Culture).Parent + $OSLocale = (Get-UICulture).Parent #Test if OS locale notif file exists $TestOSLocalPath = "$WorkingDir\locale\$($OSLocale.Name).xml" diff --git a/Winget-AutoUpdate/functions/Get-Policies.ps1 b/Winget-AutoUpdate/functions/Get-Policies.ps1 index 007593a..0200341 100644 --- a/Winget-AutoUpdate/functions/Get-Policies.ps1 +++ b/Winget-AutoUpdate/functions/Get-Policies.ps1 @@ -1,4 +1,4 @@ -#Function to get Domain/Local Policies (GPO) +#Function to get the Domain/Local Policies (GPO) Function Get-Policies { #Get WAU Policies and set the Configurations Registry Accordingly @@ -15,7 +15,7 @@ Function Get-Policies { Remove-ItemProperty $regPath -Name WAU_BypassListForUsers -Force -ErrorAction SilentlyContinue | Out-Null $ChangedSettings++ } - + if ($null -ne $($WAUPolicies.WAU_DisableAutoUpdate) -and ($($WAUPolicies.WAU_DisableAutoUpdate) -ne $($WAUConfig.WAU_DisableAutoUpdate))) { New-ItemProperty $regPath -Name WAU_DisableAutoUpdate -Value $($WAUPolicies.WAU_DisableAutoUpdate) -PropertyType DWord -Force | Out-Null $ChangedSettings++ @@ -24,7 +24,7 @@ Function Get-Policies { Remove-ItemProperty $regPath -Name WAU_DisableAutoUpdate -Force -ErrorAction SilentlyContinue | Out-Null $ChangedSettings++ } - + if ($null -ne $($WAUPolicies.WAU_DoNotRunOnMetered) -and ($($WAUPolicies.WAU_DoNotRunOnMetered) -ne $($WAUConfig.WAU_DoNotRunOnMetered))) { New-ItemProperty $regPath -Name WAU_DoNotRunOnMetered -Value $($WAUPolicies.WAU_DoNotRunOnMetered) -PropertyType DWord -Force | Out-Null $ChangedSettings++ @@ -33,7 +33,7 @@ Function Get-Policies { New-ItemProperty $regPath -Name WAU_DoNotRunOnMetered -Value 1 -PropertyType DWord -Force | Out-Null $ChangedSettings++ } - + if ($null -ne $($WAUPolicies.WAU_UpdatePrerelease) -and ($($WAUPolicies.WAU_UpdatePrerelease) -ne $($WAUConfig.WAU_UpdatePrerelease))) { New-ItemProperty $regPath -Name WAU_UpdatePrerelease -Value $($WAUPolicies.WAU_UpdatePrerelease) -PropertyType DWord -Force | Out-Null $ChangedSettings++ @@ -42,7 +42,7 @@ Function Get-Policies { New-ItemProperty $regPath -Name WAU_UpdatePrerelease -Value 0 -PropertyType DWord -Force | Out-Null $ChangedSettings++ } - + if ($null -ne $($WAUPolicies.WAU_UseWhiteList) -and ($($WAUPolicies.WAU_UseWhiteList) -ne $($WAUConfig.WAU_UseWhiteList))) { New-ItemProperty $regPath -Name WAU_UseWhiteList -Value $($WAUPolicies.WAU_UseWhiteList) -PropertyType DWord -Force | Out-Null $ChangedSettings++ @@ -51,7 +51,7 @@ Function Get-Policies { Remove-ItemProperty $regPath -Name WAU_UseWhiteList -Force -ErrorAction SilentlyContinue | Out-Null $ChangedSettings++ } - + if ($null -ne $($WAUPolicies.WAU_ListPath) -and ($($WAUPolicies.WAU_ListPath) -ne $($WAUConfig.WAU_ListPath))) { New-ItemProperty $regPath -Name WAU_ListPath -Value $($WAUPolicies.WAU_ListPath.TrimEnd(" ", "\", "/")) -Force | Out-Null $ChangedSettings++ @@ -60,7 +60,7 @@ Function Get-Policies { Remove-ItemProperty $regPath -Name WAU_ListPath -Force -ErrorAction SilentlyContinue | Out-Null $ChangedSettings++ } - + if ($null -ne $($WAUPolicies.WAU_ModsPath) -and ($($WAUPolicies.WAU_ModsPath) -ne $($WAUConfig.WAU_ModsPath))) { New-ItemProperty $regPath -Name WAU_ModsPath -Value $($WAUPolicies.WAU_ModsPath.TrimEnd(" ", "\", "/")) -Force | Out-Null $ChangedSettings++ @@ -69,6 +69,14 @@ Function Get-Policies { Remove-ItemProperty $regPath -Name WAU_ModsPath -Force -ErrorAction SilentlyContinue | Out-Null $ChangedSettings++ } + if ($null -ne $($WAUPolicies.WAU_AzureBlobSASURL) -and ($($WAUPolicies.WAU_AzureBlobSASURL) -ne $($WAUConfig.WAU_AzureBlobSASURL))) { + New-ItemProperty $regPath -Name WAU_AzureBlobSASURL -Value $($WAUPolicies.WAU_AzureBlobSASURL.TrimEnd(" ", "\", "/")) -Force | Out-Null + $ChangedSettings++ + } + elseif ($null -eq $($WAUPolicies.WAU_AzureBlobSASURL) -and $($WAUConfig.WAU_AzureBlobSASURL)) { + Remove-ItemProperty $regPath -Name WAU_AzureBlobSASURL -Force -ErrorAction SilentlyContinue | Out-Null + $ChangedSettings++ + } if ($null -ne $($WAUPolicies.WAU_NotificationLevel) -and ($($WAUPolicies.WAU_NotificationLevel) -ne $($WAUConfig.WAU_NotificationLevel))) { New-ItemProperty $regPath -Name WAU_NotificationLevel -Value $($WAUPolicies.WAU_NotificationLevel) -Force | Out-Null @@ -87,14 +95,14 @@ Function Get-Policies { $folder = $service.GetFolder('\') $task = $folder.GetTask("Winget-AutoUpdate") $definition = $task.Definition - for($triggerId=1; $triggerId -le $definition.Triggers.Count; $triggerId++){ - if(($definition.Triggers.Item($triggerId).Type -eq "2") -or ($definition.Triggers.Item($triggerId).Type -eq "3")){ - $PreStartBoundary = ($definition.Triggers.Item($triggerId).StartBoundary).Substring(0,11) - $PostStartBoundary = ($definition.Triggers.Item($triggerId).StartBoundary).Substring(19,6) + for ($triggerId = 1; $triggerId -le $definition.Triggers.Count; $triggerId++) { + if (($definition.Triggers.Item($triggerId).Type -eq "2") -or ($definition.Triggers.Item($triggerId).Type -eq "3")) { + $PreStartBoundary = ($definition.Triggers.Item($triggerId).StartBoundary).Substring(0, 11) + $PostStartBoundary = ($definition.Triggers.Item($triggerId).StartBoundary).Substring(19, 6) $Boundary = $PreStartBoundary + $($WAUPolicies.WAU_UpdatesAtTime) + $PostStartBoundary $definition.Triggers.Item($triggerId).StartBoundary = $Boundary break - $triggerId-=1 + $triggerId -= 1 } } $folder.RegisterTaskDefinition($task.Name, $definition, 4, $null, $null, $null) | Out-Null @@ -108,14 +116,14 @@ Function Get-Policies { $folder = $service.GetFolder('\') $task = $folder.GetTask("Winget-AutoUpdate") $definition = $task.Definition - for($triggerId=1; $triggerId -le $definition.Triggers.Count; $triggerId++){ - if(($definition.Triggers.Item($triggerId).Type -eq "2") -or ($definition.Triggers.Item($triggerId).Type -eq "3")){ - $PreStartBoundary = ($definition.Triggers.Item($triggerId).StartBoundary).Substring(0,11) - $PostStartBoundary = ($definition.Triggers.Item($triggerId).StartBoundary).Substring(19,6) + for ($triggerId = 1; $triggerId -le $definition.Triggers.Count; $triggerId++) { + if (($definition.Triggers.Item($triggerId).Type -eq "2") -or ($definition.Triggers.Item($triggerId).Type -eq "3")) { + $PreStartBoundary = ($definition.Triggers.Item($triggerId).StartBoundary).Substring(0, 11) + $PostStartBoundary = ($definition.Triggers.Item($triggerId).StartBoundary).Substring(19, 6) $Boundary = $PreStartBoundary + "06:00:00" + $PostStartBoundary $definition.Triggers.Item($triggerId).StartBoundary = $Boundary break - $triggerId-=1 + $triggerId -= 1 } } $folder.RegisterTaskDefinition($task.Name, $definition, 4, $null, $null, $null) | Out-Null @@ -129,11 +137,11 @@ Function Get-Policies { $folder = $service.GetFolder('\') $task = $folder.GetTask("Winget-AutoUpdate") $definition = $task.Definition - for($triggerId=1; $triggerId -le $definition.Triggers.Count; $triggerId++){ - if(($definition.Triggers.Item($triggerId).Type -eq "2") -or ($definition.Triggers.Item($triggerId).Type -eq "3")){ - $UpdatesAtTime = ($definition.Triggers.Item($triggerId).StartBoundary).Substring(11,8) + for ($triggerId = 1; $triggerId -le $definition.Triggers.Count; $triggerId++) { + if (($definition.Triggers.Item($triggerId).Type -eq "2") -or ($definition.Triggers.Item($triggerId).Type -eq "3")) { + $UpdatesAtTime = ($definition.Triggers.Item($triggerId).StartBoundary).Substring(11, 8) $definition.Triggers.Remove($triggerId) - $triggerId-=1 + $triggerId -= 1 } } $folder.RegisterTaskDefinition($task.Name, $definition, 4, $null, $null, $null) | Out-Null @@ -152,11 +160,11 @@ Function Get-Policies { $definition = $task.Definition $definition.Triggers.Count | Out-Null switch ($($WAUPolicies.WAU_UpdatesInterval)) { - "Daily" {$tasktrigger = New-ScheduledTaskTrigger -Daily -At $($WAUConfig.WAU_UpdatesAtTime); break} - "BiDaily" {$tasktrigger = New-ScheduledTaskTrigger -Daily -At $($WAUConfig.WAU_UpdatesAtTime) -DaysInterval 2; break} - "Weekly" {$tasktrigger = New-ScheduledTaskTrigger -Weekly -At $($WAUConfig.WAU_UpdatesAtTime) -DaysOfWeek 2; break} - "BiWeekly" {$tasktrigger = New-ScheduledTaskTrigger -Weekly -At $($WAUConfig.WAU_UpdatesAtTime) -DaysOfWeek 2 -WeeksInterval 2; break} - "Monthly" {$tasktrigger = New-ScheduledTaskTrigger -Weekly -At $($WAUConfig.WAU_UpdatesAtTime) -DaysOfWeek 2 -WeeksInterval 4; break} + "Daily" { $tasktrigger = New-ScheduledTaskTrigger -Daily -At $($WAUConfig.WAU_UpdatesAtTime); break } + "BiDaily" { $tasktrigger = New-ScheduledTaskTrigger -Daily -At $($WAUConfig.WAU_UpdatesAtTime) -DaysInterval 2; break } + "Weekly" { $tasktrigger = New-ScheduledTaskTrigger -Weekly -At $($WAUConfig.WAU_UpdatesAtTime) -DaysOfWeek 2; break } + "BiWeekly" { $tasktrigger = New-ScheduledTaskTrigger -Weekly -At $($WAUConfig.WAU_UpdatesAtTime) -DaysOfWeek 2 -WeeksInterval 2; break } + "Monthly" { $tasktrigger = New-ScheduledTaskTrigger -Weekly -At $($WAUConfig.WAU_UpdatesAtTime) -DaysOfWeek 2 -WeeksInterval 4; break } } if ($definition.Triggers.Count -gt 0) { $triggers = @() @@ -177,11 +185,11 @@ Function Get-Policies { $folder = $service.GetFolder('\') $task = $folder.GetTask("Winget-AutoUpdate") $definition = $task.Definition - for($triggerId=1; $triggerId -le $definition.Triggers.Count; $triggerId++){ - if(($definition.Triggers.Item($triggerId).Type -eq "2") -or ($definition.Triggers.Item($triggerId).Type -eq "3")){ - $UpdatesAtTime = ($definition.Triggers.Item($triggerId).StartBoundary).Substring(11,8) + for ($triggerId = 1; $triggerId -le $definition.Triggers.Count; $triggerId++) { + if (($definition.Triggers.Item($triggerId).Type -eq "2") -or ($definition.Triggers.Item($triggerId).Type -eq "3")) { + $UpdatesAtTime = ($definition.Triggers.Item($triggerId).StartBoundary).Substring(11, 8) $definition.Triggers.Remove($triggerId) - $triggerId-=1 + $triggerId -= 1 } } $folder.RegisterTaskDefinition($task.Name, $definition, 4, $null, $null, $null) | Out-Null @@ -223,15 +231,17 @@ Function Get-Policies { $folder = $service.GetFolder('\') $task = $folder.GetTask("Winget-AutoUpdate") $definition = $task.Definition - $definition.Triggers.Count | Out-Null - if ($definition.Triggers.Count -gt 0) { + $triggerLogon = $false + foreach ($trigger in $definition.Triggers) { + if ($trigger.Type -eq "9") { + $triggerLogon = $true + break + } + } + if (!$triggerLogon) { $triggers += New-ScheduledTaskTrigger -AtLogon Set-ScheduledTask -TaskName "Winget-AutoUpdate" -Trigger $triggers } - else { - $tasktrigger = New-ScheduledTaskTrigger -AtLogon - Set-ScheduledTask -TaskName "Winget-AutoUpdate" -Trigger $tasktrigger - } } else { New-ItemProperty $regPath -Name WAU_UpdatesAtLogon -Value $($WAUPolicies.WAU_UpdatesAtLogon) -PropertyType DWord -Force | Out-Null @@ -241,10 +251,10 @@ Function Get-Policies { $task = $folder.GetTask("Winget-AutoUpdate") $definition = $task.Definition $definition.Triggers.Count | Out-Null - for($triggerId=1; $triggerId -le $definition.Triggers.Count; $triggerId++){ - if($definition.Triggers.Item($triggerId).Type -eq "9"){ + for ($triggerId = 1; $triggerId -le $definition.Triggers.Count; $triggerId++) { + if ($definition.Triggers.Item($triggerId).Type -eq "9") { $definition.Triggers.Remove($triggerId) - $triggerId-=1 + $triggerId -= 1 } } $folder.RegisterTaskDefinition($task.Name, $definition, 4, $null, $null, $null) | Out-Null @@ -258,10 +268,10 @@ Function Get-Policies { $folder = $service.GetFolder('\') $task = $folder.GetTask("Winget-AutoUpdate") $definition = $task.Definition - for($triggerId=1; $triggerId -le $definition.Triggers.Count; $triggerId++){ - if($definition.Triggers.Item($triggerId).Type -eq "9"){ + for ($triggerId = 1; $triggerId -le $definition.Triggers.Count; $triggerId++) { + if ($definition.Triggers.Item($triggerId).Type -eq "9") { $definition.Triggers.Remove($triggerId) - $triggerId-=1 + $triggerId -= 1 } } $folder.RegisterTaskDefinition($task.Name, $definition, 4, $null, $null, $null) | Out-Null diff --git a/Winget-AutoUpdate/functions/Get-WAUAvailableVersion.ps1 b/Winget-AutoUpdate/functions/Get-WAUAvailableVersion.ps1 index 80c5fd8..c2241ab 100644 --- a/Winget-AutoUpdate/functions/Get-WAUAvailableVersion.ps1 +++ b/Winget-AutoUpdate/functions/Get-WAUAvailableVersion.ps1 @@ -1,4 +1,4 @@ -#Function to get latest WAU available version on Github +#Function to get the latest WAU available version on Github function Get-WAUAvailableVersion { @@ -6,7 +6,7 @@ function Get-WAUAvailableVersion { if ($WAUConfig.WAU_UpdatePrerelease -eq 1) { #Log - Write-log "WAU AutoUpdate Pre-release versions is Enabled" "Cyan" + Write-ToLog "WAU AutoUpdate Pre-release versions is Enabled" "Cyan" #Get latest pre-release info $WAUurl = 'https://api.github.com/repos/Romanitho/Winget-AutoUpdate/releases' @@ -19,6 +19,7 @@ function Get-WAUAvailableVersion { } + #Return version return ((Invoke-WebRequest $WAUurl -UseBasicParsing | ConvertFrom-Json)[0].tag_name).Replace("v", "") } diff --git a/Winget-AutoUpdate/functions/Get-WingetCmd.ps1 b/Winget-AutoUpdate/functions/Get-WingetCmd.ps1 index 0dddf0a..3c4ab6d 100644 --- a/Winget-AutoUpdate/functions/Get-WingetCmd.ps1 +++ b/Winget-AutoUpdate/functions/Get-WingetCmd.ps1 @@ -1,4 +1,4 @@ -#Function to get Winget Command regarding execution context (User, System...) +#Function to get the winget command regarding execution context (User, System...) Function Get-WingetCmd { @@ -21,7 +21,7 @@ Function Get-WingetCmd { $Script:Winget = "$WingetPath\winget.exe" } else { - Write-Log "Winget not installed or detected !" "Red" + Write-ToLog "Winget not installed or detected !" "Red" return $false } @@ -30,7 +30,7 @@ Function Get-WingetCmd { #Log Winget installed version $WingetVer = & $Winget --version - Write-Log "Winget Version: $WingetVer" + Write-ToLog "Winget Version: $WingetVer" return $true diff --git a/Winget-AutoUpdate/functions/Get-WingetOutdatedApps.ps1 b/Winget-AutoUpdate/functions/Get-WingetOutdatedApps.ps1 index ae6aa50..27c10e8 100644 --- a/Winget-AutoUpdate/functions/Get-WingetOutdatedApps.ps1 +++ b/Winget-AutoUpdate/functions/Get-WingetOutdatedApps.ps1 @@ -1,4 +1,4 @@ -#Function to get outdated app list, in formatted array +#Function to get the outdated app list, in formatted array function Get-WingetOutdatedApps { class Software { @@ -13,11 +13,11 @@ function Get-WingetOutdatedApps { #Start Convertion of winget format to an array. Check if "-----" exists (Winget Error Handling) if (!($upgradeResult -match "-----")) { - return "Problem:`n$upgradeResult" + return "An unusual thing happened (maybe all apps are upgraded):`n$upgradeResult" } #Split winget output to lines - $lines = $upgradeResult.Split([Environment]::NewLine) | Where-Object { $_ -and $_ -notmatch "--include-unknown" } + $lines = $upgradeResult.Split([Environment]::NewLine) | Where-Object { $_ } # Find the line that starts with "------" $fl = 0 @@ -38,9 +38,22 @@ function Get-WingetOutdatedApps { # Now cycle in real package and split accordingly $upgradeList = @() - For ($i = $fl + 2; $i -lt $lines.Length - 1; $i++) { + For ($i = $fl + 2; $i -lt $lines.Length; $i++) { $line = $lines[$i] - if ($line) { + if ($line.StartsWith("-----")) { + #Get header line + $fl = $i - 1 + + #Get header titles + $index = $lines[$fl] -split '\s+' + + # Line $fl has the header, we can find char where we find ID and Version + $idStart = $lines[$fl].IndexOf($index[1]) + $versionStart = $lines[$fl].IndexOf($index[2]) + $availableStart = $lines[$fl].IndexOf($index[3]) + } + #(Alphanumeric | Literal . | Alphanumeric) - the only unique thing in common for lines with applications + if ($line -match "\w\.\w") { $software = [Software]::new() $software.Name = $line.Substring(0, $idStart).TrimEnd() $software.Id = $line.Substring($idStart, $versionStart - $idStart).TrimEnd() diff --git a/Winget-AutoUpdate/functions/Get-WingetSystemApps.ps1 b/Winget-AutoUpdate/functions/Get-WingetSystemApps.ps1 index b682f62..8f653ea 100644 --- a/Winget-AutoUpdate/functions/Get-WingetSystemApps.ps1 +++ b/Winget-AutoUpdate/functions/Get-WingetSystemApps.ps1 @@ -1,6 +1,6 @@ function Get-WingetSystemApps { - #Json File where to export system installed apps + #Json File, where to export system installed apps $jsonFile = "$WorkingDir\winget_system_apps.txt" #Get list of installed Winget apps to json file diff --git a/Winget-AutoUpdate/functions/Invoke-LogRotation.ps1 b/Winget-AutoUpdate/functions/Invoke-LogRotation.ps1 index 889de60..82edf17 100644 --- a/Winget-AutoUpdate/functions/Invoke-LogRotation.ps1 +++ b/Winget-AutoUpdate/functions/Invoke-LogRotation.ps1 @@ -1,4 +1,4 @@ -#Function rotate the logs +#Function to rotate the logs function Invoke-LogRotation ($LogFile, $MaxLogFiles, $MaxLogSize) { <# @@ -73,17 +73,17 @@ function Invoke-LogRotation ($LogFile, $MaxLogFiles, $MaxLogSize) { #Log Header $Log = "##################################################`n# CHECK FOR APP UPDATES - $(Get-Date -Format (Get-culture).DateTimeFormat.ShortDatePattern)`n##################################################" $Log | out-file -filepath $LogFile -Append - Write-Log "Running in System context" + Write-ToLog "Running in System context" if ($ActivateGPOManagement) { - Write-Log "Activated WAU GPO Management detected, comparing..." + Write-ToLog "Activated WAU GPO Management detected, comparing..." if ($null -ne $ChangedSettings -and $ChangedSettings -ne 0) { - Write-Log "Changed settings detected and applied" "Yellow" + Write-ToLog "Changed settings detected and applied" "Yellow" } else { - Write-Log "No Changed settings detected" "Yellow" + Write-ToLog "No Changed settings detected" "Yellow" } } - Write-Log "Max Log Size reached: $MaxLogSize bytes - Rotated Logs" + Write-ToLog "Max Log Size reached: $MaxLogSize bytes - Rotated Logs" Return $True } diff --git a/Winget-AutoUpdate/functions/Invoke-ModsProtect.ps1 b/Winget-AutoUpdate/functions/Invoke-ModsProtect.ps1 new file mode 100644 index 0000000..1b56707 --- /dev/null +++ b/Winget-AutoUpdate/functions/Invoke-ModsProtect.ps1 @@ -0,0 +1,65 @@ +#Function to check if the mods directory is secured. +#Security: Mods directory must be protected (Users could create scripts of their own - then they'll run in System Context)! +#Check if Local Users have write rights in Mods directory or not (and take action if necessary): + +function Invoke-ModsProtect ($ModsPath) { + try { + $directory = Get-Item -Path $ModsPath -ErrorAction SilentlyContinue + $acl = Get-Acl -Path $directory.FullName + #Local Users - S-1-5-32-545 + $userSID = New-Object System.Security.Principal.SecurityIdentifier("S-1-5-32-545") + #Translate SID to Locale Name + $ntAccount = $userSID.Translate([System.Security.Principal.NTAccount]) + $userName = $ntAccount.Value + $userRights = [System.Security.AccessControl.FileSystemRights]"Write" + + $hasWriteAccess = $False + + foreach ($access in $acl.Access) { + if ($access.IdentityReference.Value -eq $userName -and $access.FileSystemRights -eq $userRights) { + $hasWriteAccess = $True + break + } + } + + if ($hasWriteAccess) { + #Disable inheritance + $acl.SetAccessRuleProtection($True, $True) + # Remove any existing rules + $acl.Access | ForEach-Object { $acl.RemoveAccessRule($_) } + #SYSTEM Full - S-1-5-18 + $userSID = New-Object System.Security.Principal.SecurityIdentifier("S-1-5-18") + $rule = New-Object System.Security.AccessControl.FileSystemAccessRule($userSID, "FullControl", "ContainerInherit,ObjectInherit", "None", "Allow") + $acl.SetAccessRule($rule) + # Save the updated ACL + Set-Acl -Path $directory.FullName -AclObject $acl + + #Administrators Full - S-1-5-32-544 + $acl = Get-Acl -Path $directory.FullName + $userSID = New-Object System.Security.Principal.SecurityIdentifier("S-1-5-32-544") + $rule = New-Object System.Security.AccessControl.FileSystemAccessRule($userSID, "FullControl", "ContainerInherit,ObjectInherit", "None", "Allow") + $acl.SetAccessRule($rule) + Set-Acl -Path $directory.FullName -AclObject $acl + + #Local Users ReadAndExecute - S-1-5-32-545 S-1-5-11 + $acl = Get-Acl -Path $directory.FullName + $userSID = New-Object System.Security.Principal.SecurityIdentifier("S-1-5-32-545") + $rule = New-Object System.Security.AccessControl.FileSystemAccessRule($userSID, "ReadAndExecute", "ContainerInherit,ObjectInherit", "None", "Allow") + $acl.SetAccessRule($rule) + Set-Acl -Path $directory.FullName -AclObject $acl + + #Authenticated Users ReadAndExecute - S-1-5-11 + $acl = Get-Acl -Path $directory.FullName + $userSID = New-Object System.Security.Principal.SecurityIdentifier("S-1-5-11") + $rule = New-Object System.Security.AccessControl.FileSystemAccessRule($userSID, "ReadAndExecute", "ContainerInherit,ObjectInherit", "None", "Allow") + $acl.SetAccessRule($rule) + Set-Acl -Path $directory.FullName -AclObject $acl + + return $True + } + return $False + } + catch { + return "Error" + } +} \ No newline at end of file diff --git a/Winget-AutoUpdate/functions/Invoke-PostUpdateActions.ps1 b/Winget-AutoUpdate/functions/Invoke-PostUpdateActions.ps1 index 2b7d133..605e10a 100644 --- a/Winget-AutoUpdate/functions/Invoke-PostUpdateActions.ps1 +++ b/Winget-AutoUpdate/functions/Invoke-PostUpdateActions.ps1 @@ -1,9 +1,82 @@ -#Function to make actions post WAU update +#Function to make actions after WAU update function Invoke-PostUpdateActions { #log - Write-Log "Running Post Update actions..." "yellow" + Write-ToLog "Running Post Update actions:" "yellow" + + #Check if Intune Management Extension Logs folder and WAU-updates.log exists, make symlink + if ((Test-Path "${env:ProgramData}\Microsoft\IntuneManagementExtension\Logs") -and !(Test-Path "${env:ProgramData}\Microsoft\IntuneManagementExtension\Logs\WAU-updates.log")) { + Write-ToLog "-> Creating SymLink for log file in Intune Management Extension log folder" "yellow" + New-Item -Path "${env:ProgramData}\Microsoft\IntuneManagementExtension\Logs\WAU-updates.log" -ItemType SymbolicLink -Value $LogFile -Force -ErrorAction SilentlyContinue | Out-Null + } + + Write-ToLog "-> Checking prerequisites..." "yellow" + + #Check if Visual C++ 2019 or 2022 installed + $Visual2019 = "Microsoft Visual C++ 2015-2019 Redistributable*" + $Visual2022 = "Microsoft Visual C++ 2015-2022 Redistributable*" + $path = Get-Item HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*, HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\* | Where-Object { $_.GetValue("DisplayName") -like $Visual2019 -or $_.GetValue("DisplayName") -like $Visual2022 } + + #If not installed, install + if (!($path)) { + try { + if ((Get-CimInStance Win32_OperatingSystem).OSArchitecture -like "*64*") { + $OSArch = "x64" + } + else { + $OSArch = "x86" + } + Write-ToLog "-> Downloading VC_redist.$OSArch.exe..." + $SourceURL = "https://aka.ms/vs/17/release/VC_redist.$OSArch.exe" + $Installer = "$($WAUConfig.InstallLocation)\VC_redist.$OSArch.exe" + $ProgressPreference = 'SilentlyContinue' + Invoke-WebRequest $SourceURL -UseBasicParsing -OutFile (New-Item -Path $Installer -Force) + Write-ToLog "-> Installing VC_redist.$OSArch.exe..." + Start-Process -FilePath $Installer -Args "/quiet /norestart" -Wait + Remove-Item $Installer -ErrorAction Ignore + Write-ToLog "-> MS Visual C++ 2015-2022 installed successfully" "green" + } + catch { + Write-ToLog "-> MS Visual C++ 2015-2022 installation failed." "red" + } + } + else { + Write-ToLog "-> Prerequisites checked. OK" "green" + } + + #Check Package Install + Write-ToLog "-> Checking if Winget is installed/up to date" "yellow" + $TestWinGet = Get-AppxProvisionedPackage -Online | Where-Object { $_.DisplayName -eq "Microsoft.DesktopAppInstaller" } + + #Current: v1.4.10173 = 1.19.10173.0 = 2023.118.406.0 + If ([Version]$TestWinGet.Version -ge "2023.118.406.0") { + + Write-ToLog "-> WinGet is Installed/up to date" "green" + + } + Else { + + #Download WinGet MSIXBundle + Write-ToLog "-> Not installed/up to date. Downloading WinGet..." + $WinGetURL = "https://github.com/microsoft/winget-cli/releases/download/v1.4.10173/Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle" + $WebClient = New-Object System.Net.WebClient + $WebClient.DownloadFile($WinGetURL, "$($WAUConfig.InstallLocation)\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle") + + #Install WinGet MSIXBundle + try { + Write-ToLog "-> Installing Winget MSIXBundle for App Installer..." + Add-AppxProvisionedPackage -Online -PackagePath "$($WAUConfig.InstallLocation)\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle" -SkipLicense | Out-Null + Write-ToLog "-> Installed Winget MSIXBundle for App Installer" "green" + } + catch { + Write-ToLog "-> Failed to intall Winget MSIXBundle for App Installer..." "red" + } + + #Remove WinGet MSIXBundle + Remove-Item -Path "$($WAUConfig.InstallLocation)\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle" -Force -ErrorAction Continue + + } #Reset Winget Sources $ResolveWingetPath = Resolve-Path "$env:programfiles\WindowsApps\Microsoft.DesktopAppInstaller_*_*__8wekyb3d8bbwe\winget.exe" | Sort-Object { [version]($_.Path -replace '^[^\d]+_((\d+\.)*\d+)_.*', '$1') } @@ -13,7 +86,7 @@ function Invoke-PostUpdateActions { & $WingetPath source reset --force #log - Write-Log "-> Winget sources reseted." "green" + Write-ToLog "-> Winget sources reseted." "green" } #Create WAU Regkey if not present @@ -32,7 +105,7 @@ function Invoke-PostUpdateActions { New-ItemProperty $regPath -Name WAU_UpdatePrerelease -Value 0 -PropertyType DWord -Force #log - Write-Log "-> $regPath created." "green" + Write-ToLog "-> $regPath created." "green" } #Fix Notif where WAU_NotificationLevel is not set $regNotif = Get-ItemProperty $regPath -Name WAU_NotificationLevel -ErrorAction SilentlyContinue @@ -40,7 +113,7 @@ function Invoke-PostUpdateActions { New-ItemProperty $regPath -Name WAU_NotificationLevel -Value Full -Force #log - Write-Log "-> Notification level setting was missing. Fixed with 'Full' option." + Write-ToLog "-> Notification level setting was missing. Fixed with 'Full' option." } #Set WAU_MaxLogFiles/WAU_MaxLogSize if not set @@ -50,22 +123,51 @@ function Invoke-PostUpdateActions { New-ItemProperty $regPath -Name WAU_MaxLogSize -Value 1048576 -PropertyType DWord -Force | Out-Null #log - Write-Log "-> MaxLogFiles/MaxLogSize setting was missing. Fixed with 3/1048576 (in bytes, default is 1048576 = 1 MB)." + Write-ToLog "-> MaxLogFiles/MaxLogSize setting was missing. Fixed with 3/1048576 (in bytes, default is 1048576 = 1 MB)." } - #Convert about.xml if exists (previous WAU versions) to reg + #Set WAU_ListPath if not set + $ListPath = Get-ItemProperty $regPath -Name WAU_ListPath -ErrorAction SilentlyContinue + if (!$ListPath) { + New-ItemProperty $regPath -Name WAU_ListPath -Force | Out-Null + + #log + Write-ToLog "-> ListPath setting was missing. Fixed with empty string." + } + + #Set WAU_ModsPath if not set + $ModsPath = Get-ItemProperty $regPath -Name WAU_ModsPath -ErrorAction SilentlyContinue + if (!$ModsPath) { + New-ItemProperty $regPath -Name WAU_ModsPath -Force | Out-Null + + #log + Write-ToLog "-> ModsPath setting was missing. Fixed with empty string." + } + + #Security check + Write-ToLog "-> Checking Mods Directory:" "yellow" + $Protected = Invoke-ModsProtect "$($WAUConfig.InstallLocation)\mods" + if ($Protected -eq $True) { + Write-ToLog "-> The mods directory is now secured!" "green" + } + elseif ($Protected -eq $False) { + Write-ToLog "-> The mods directory was already secured!" "green" + } + else { + Write-ToLog "-> Error: The mods directory couldn't be verified as secured!" "red" + } + + #Convert about.xml if exists (old WAU versions) to reg $WAUAboutPath = "$WorkingDir\config\about.xml" if (test-path $WAUAboutPath) { [xml]$About = Get-Content $WAUAboutPath -Encoding UTF8 -ErrorAction SilentlyContinue New-ItemProperty $regPath -Name DisplayVersion -Value $About.app.version -Force - New-ItemProperty $regPath -Name VersionMajor -Value ([version]$About.app.version).Major -Force - New-ItemProperty $regPath -Name VersionMinor -Value ([version]$About.app.version).Minor -Force #Remove file once converted Remove-Item $WAUAboutPath -Force -Confirm:$false #log - Write-Log "-> $WAUAboutPath converted." "green" + Write-ToLog "-> $WAUAboutPath converted." "green" } #Convert config.xml if exists (previous WAU versions) to reg @@ -81,21 +183,34 @@ function Invoke-PostUpdateActions { Remove-Item $WAUConfigPath -Force -Confirm:$false #log - Write-Log "-> $WAUConfigPath converted." "green" + Write-ToLog "-> $WAUConfigPath converted." "green" } - #Remove old functions + #Remove old functions / files $FileNames = @( "$WorkingDir\functions\Get-WAUConfig.ps1", "$WorkingDir\functions\Get-WAUCurrentVersion.ps1", - "$WorkingDir\functions\Get-WAUUpdateStatus.ps1" + "$WorkingDir\functions\Get-WAUUpdateStatus.ps1", + "$WorkingDir\functions\Write-Log.ps1", + "$WorkingDir\Version.txt" ) foreach ($FileName in $FileNames) { if (Test-Path $FileName) { Remove-Item $FileName -Force -Confirm:$false #log - Write-Log "-> $FileName removed." "green" + Write-ToLog "-> $FileName removed." "green" + } + } + + #Remove old registry key + $RegistryKeys = @( + "VersionMajor", + "VersionMinor" + ) + foreach ($RegistryKey in $RegistryKeys) { + if (Get-ItemProperty -Path $regPath -Name $RegistryKey -ErrorAction SilentlyContinue) { + Remove-ItemProperty -Path $regPath -Name $RegistryKey } } @@ -120,6 +235,6 @@ function Invoke-PostUpdateActions { $Script:WAUConfig = Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Winget-AutoUpdate" #log - Write-Log "Post Update actions finished" "green" + Write-ToLog "Post Update actions finished" "green" } diff --git a/Winget-AutoUpdate/functions/Start-Init.ps1 b/Winget-AutoUpdate/functions/Start-Init.ps1 index 280ecbb..e0b6a83 100644 --- a/Winget-AutoUpdate/functions/Start-Init.ps1 +++ b/Winget-AutoUpdate/functions/Start-Init.ps1 @@ -1,20 +1,25 @@ -#Initialisation +# Initialisation function Start-Init { #Config console output encoding [Console]::OutputEncoding = [System.Text.Encoding]::UTF8 - #Log Header - $Log = "`n##################################################`n# CHECK FOR APP UPDATES - $(Get-Date -Format (Get-culture).DateTimeFormat.ShortDatePattern)`n##################################################" - $Log | Write-host - - #Logs initialisation - $Script:LogFile = "$WorkingDir\logs\updates.log" + $caller = Get-ChildItem $MyInvocation.PSCommandPath | Select-Object -Expand Name + if ($caller -eq "Winget-Upgrade.ps1") { + #Log Header + $Log = "`n##################################################`n# CHECK FOR APP UPDATES - $(Get-Date -Format (Get-culture).DateTimeFormat.ShortDatePattern)`n##################################################" + $Log | Write-host + #Logs initialisation + $Script:LogFile = "$WorkingDir\logs\updates.log" + } + elseif ($caller -eq "Winget-AutoUpdate-Install.ps1") { + $Script:LogFile = "$WingetUpdatePath\logs\updates.log" + } if (!(Test-Path $LogFile)) { #Create file if doesn't exist - New-Item -ItemType File -Path $LogFile -Force + New-Item -ItemType File -Path $LogFile -Force | Out-Null #Set ACL for users on logfile $NewAcl = Get-Acl -Path $LogFile @@ -26,8 +31,28 @@ function Start-Init { $NewAcl.SetAccessRule($fileSystemAccessRule) Set-Acl -Path $LogFile -AclObject $NewAcl } + elseif ((Test-Path $LogFile) -and ($caller -eq "Winget-AutoUpdate-Install.ps1")) { + #Set ACL for users on logfile + $NewAcl = Get-Acl -Path $LogFile + $identity = New-Object System.Security.Principal.SecurityIdentifier S-1-5-11 + $fileSystemRights = "Modify" + $type = "Allow" + $fileSystemAccessRuleArgumentList = $identity, $fileSystemRights, $type + $fileSystemAccessRule = New-Object -TypeName System.Security.AccessControl.FileSystemAccessRule -ArgumentList $fileSystemAccessRuleArgumentList + $NewAcl.SetAccessRule($fileSystemAccessRule) + Set-Acl -Path $LogFile -AclObject $NewAcl + } - #Log file - $Log | out-file -filepath $LogFile -Append + #Check if Intune Management Extension Logs folder and WAU-updates.log exists, make symlink + if ((Test-Path "${env:ProgramData}\Microsoft\IntuneManagementExtension\Logs") -and !(Test-Path "${env:ProgramData}\Microsoft\IntuneManagementExtension\Logs\WAU-updates.log")) { + Write-host "`nCreating SymLink for log file in Intune Management Extension log folder" -ForegroundColor Yellow + New-Item -Path "${env:ProgramData}\Microsoft\IntuneManagementExtension\Logs\WAU-updates.log" -ItemType SymbolicLink -Value $LogFile -Force -ErrorAction SilentlyContinue | Out-Null + } + + + if ($caller -eq "Winget-Upgrade.ps1") { + #Log file + $Log | out-file -filepath $LogFile -Append + } } diff --git a/Winget-AutoUpdate/functions/Start-NotifTask.ps1 b/Winget-AutoUpdate/functions/Start-NotifTask.ps1 index 990651f..3aa17d9 100644 --- a/Winget-AutoUpdate/functions/Start-NotifTask.ps1 +++ b/Winget-AutoUpdate/functions/Start-NotifTask.ps1 @@ -1,4 +1,4 @@ -#Function to send notifications to user +#Function to send the notifications to user function Start-NotifTask { @@ -11,7 +11,8 @@ function Start-NotifTask { [String]$Body, [String]$Button1Text, [String]$Button1Action, - [Switch]$ButtonDismiss = $false + [Switch]$ButtonDismiss = $false, + [Switch]$UserRun = $false ) if (($WAUConfig.WAU_NotificationLevel -eq "Full") -or ($WAUConfig.WAU_NotificationLevel -eq "SuccessOnly" -and $MessageType -eq "Success") -or (!$IsSystem)) { @@ -31,7 +32,7 @@ function Start-NotifTask { $XMLbinding.Attributes.Append($XMLbindingAtt1) | Out-Null $XMLimagepath = "$WorkingDir\icons\$MessageType.png" - if (Test-Path $XMLimagepath){ + if (Test-Path $XMLimagepath) { # Creation of a image node $XMLimage = $ToastTemplate.CreateElement("image") $XMLbinding.AppendChild($XMLimage) | Out-Null @@ -43,7 +44,7 @@ function Start-NotifTask { $XMLimage.Attributes.Append($XMLimageAtt2) | Out-Null } - if ($Title){ + if ($Title) { # Creation of a text node $XMLtitle = $ToastTemplate.CreateElement("text") $XMLtitleText = $ToastTemplate.CreateTextNode($Title) @@ -51,7 +52,7 @@ function Start-NotifTask { $XMLbinding.AppendChild($XMLtitle) | Out-Null } - if ($Message){ + if ($Message) { # Creation of a text node $XMLtext = $ToastTemplate.CreateElement("text") $XMLtextText = $ToastTemplate.CreateTextNode($Message) @@ -59,7 +60,7 @@ function Start-NotifTask { $XMLbinding.AppendChild($XMLtext) | Out-Null } - if ($Body){ + if ($Body) { # Creation of a group node $XMLgroup = $ToastTemplate.CreateElement("group") $XMLbinding.AppendChild($XMLgroup) | Out-Null @@ -91,7 +92,7 @@ function Start-NotifTask { $XMLactionAtt1 = $ToastTemplate.CreateAttribute("content") $XMLactionAtt1.Value = $Button1Text $XMLaction.Attributes.Append($XMLactionAtt1) | Out-Null - if ($Button1Action){ + if ($Button1Action) { $XMLactionAtt2 = $ToastTemplate.CreateAttribute("arguments") $XMLactionAtt2.Value = $Button1Action $XMLaction.Attributes.Append($XMLactionAtt2) | Out-Null @@ -126,7 +127,7 @@ function Start-NotifTask { $ToastTemplate.LastChild.AppendChild($XMLactions) | Out-Null $ToastTemplate.LastChild.AppendChild($XMLtag) | Out-Null - if ($OnClickAction){ + if ($OnClickAction) { $ToastTemplate.toast.SetAttribute("activationType", "Protocol") | Out-Null $ToastTemplate.toast.SetAttribute("launch", $OnClickAction) | Out-Null } diff --git a/Winget-AutoUpdate/functions/Test-ListPath.ps1 b/Winget-AutoUpdate/functions/Test-ListPath.ps1 index 9284eeb..2ec3d7b 100644 --- a/Winget-AutoUpdate/functions/Test-ListPath.ps1 +++ b/Winget-AutoUpdate/functions/Test-ListPath.ps1 @@ -1,4 +1,4 @@ -#Function to check Black/White List External Path +#Function to check Block/Allow List External Path function Test-ListPath ($ListPath, $UseWhiteList, $WingetUpdatePath) { # URL, UNC or Local Path @@ -37,8 +37,21 @@ function Test-ListPath ($ListPath, $UseWhiteList, $WingetUpdatePath) { } } catch { - $Script:ReachNoPath = $True - return $False + try { + $content = $wc.DownloadString("$ExternalList") + if ($null -ne $content -and $content -match "\w\.\w") { + $wc.DownloadFile($ExternalList, $LocalList) + return $true + } + else { + $Script:ReachNoPath = $True + return $False + } + } + catch { + $Script:ReachNoPath = $True + return $False + } } } # If path is UNC or local diff --git a/Winget-AutoUpdate/functions/Test-Mods.ps1 b/Winget-AutoUpdate/functions/Test-Mods.ps1 index 560df80..f46d4da 100644 --- a/Winget-AutoUpdate/functions/Test-Mods.ps1 +++ b/Winget-AutoUpdate/functions/Test-Mods.ps1 @@ -1,4 +1,4 @@ -#Function to check if modification exists in 'mods' directory +#Function to check if modification exists within 'mods' directory function Test-Mods ($app) { diff --git a/Winget-AutoUpdate/functions/Test-ModsPath.ps1 b/Winget-AutoUpdate/functions/Test-ModsPath.ps1 index 29f0bdf..9f468b1 100644 --- a/Winget-AutoUpdate/functions/Test-ModsPath.ps1 +++ b/Winget-AutoUpdate/functions/Test-ModsPath.ps1 @@ -1,6 +1,6 @@ -#Function to check Mods External Path +#Function to check mods External Path -function Test-ModsPath ($ModsPath, $WingetUpdatePath) { +function Test-ModsPath ($ModsPath, $WingetUpdatePath, $AzureBlobSASURL) { # URL, UNC or Local Path # Get local and external Mods paths $LocalMods = -join ($WingetUpdatePath, "\", "mods") @@ -30,7 +30,7 @@ function Test-ModsPath ($ModsPath, $WingetUpdatePath) { # Collect the external list of href links $BinLinks = $BinResponse.Links | Select-Object -ExpandProperty HREF #If there's a directory path in the HREF:s, delete it (IIS) - $CleanBinLinks = $BinLinks -replace "/.*/","" + $CleanBinLinks = $BinLinks -replace "/.*/", "" #Modify strings to HREF:s $index = 0 foreach ($Bin in $CleanBinLinks) { @@ -41,14 +41,14 @@ function Test-ModsPath ($ModsPath, $WingetUpdatePath) { } #Delete Local Bins that don't exist Externally $index = 0 - $CleanLinks = $BinLinks -replace "/.*/","" + $CleanLinks = $BinLinks -replace "/.*/", "" foreach ($Bin in $InternalBinsNames) { If ($CleanLinks -notcontains "$Bin") { Remove-Item $LocalMods\bins\$Bin -Force -ErrorAction SilentlyContinue | Out-Null } $index++ } - $CleanBinLinks = $BinLinks -replace "/.*/","" + $CleanBinLinks = $BinLinks -replace "/.*/", "" $Bin = "" #Loop through all links $wc = New-Object System.Net.WebClient @@ -56,7 +56,7 @@ function Test-ModsPath ($ModsPath, $WingetUpdatePath) { #Check for .exe in listing/HREF:s in an index page pointing to .exe if ($_ -like "*.exe") { $dateExternalBin = "" - $dateLocalBin ="" + $dateLocalBin = "" $wc.OpenRead("$ExternalBins/$_").Close() | Out-Null $dateExternalBin = ([DateTime]$wc.ResponseHeaders['Last-Modified']).ToString("yyyy-MM-dd HH:mm:ss") if (Test-Path -Path $LocalMods"\bins\"$_) { @@ -64,7 +64,7 @@ function Test-ModsPath ($ModsPath, $WingetUpdatePath) { } if ($dateExternalBin -gt $dateLocalBin) { $SaveBin = Join-Path -Path "$LocalMods\bins" -ChildPath $_ - Invoke-WebRequest -Uri "$ExternalBins/$_" -OutFile $SaveBin.Replace("%20"," ") -UseBasicParsing + Invoke-WebRequest -Uri "$ExternalBins/$_" -OutFile $SaveBin.Replace("%20", " ") -UseBasicParsing } } } @@ -74,8 +74,8 @@ function Test-ModsPath ($ModsPath, $WingetUpdatePath) { $ModLinks = $WebResponse.Links | Select-Object -ExpandProperty HREF #If there's a directory path in the HREF:s, delete it (IIS) - $CleanLinks = $ModLinks -replace "/.*/","" - + $CleanLinks = $ModLinks -replace "/.*/", "" + #Modify strings to HREF:s $index = 0 foreach ($Mod in $CleanLinks) { @@ -88,7 +88,7 @@ function Test-ModsPath ($ModsPath, $WingetUpdatePath) { #Delete Local Mods that don't exist Externally $DeletedMods = 0 $index = 0 - $CleanLinks = $ModLinks -replace "/.*/","" + $CleanLinks = $ModLinks -replace "/.*/", "" foreach ($Mod in $InternalModsNames) { If ($CleanLinks -notcontains "$Mod") { Remove-Item $LocalMods\$Mod -Force -ErrorAction SilentlyContinue | Out-Null @@ -96,8 +96,8 @@ function Test-ModsPath ($ModsPath, $WingetUpdatePath) { } $index++ } - - $CleanLinks = $ModLinks -replace "/.*/","" + + $CleanLinks = $ModLinks -replace "/.*/", "" #Loop through all links $wc = New-Object System.Net.WebClient @@ -106,13 +106,13 @@ function Test-ModsPath ($ModsPath, $WingetUpdatePath) { if (($_ -like "*.ps1") -or ($_ -like "*.txt")) { try { $dateExternalMod = "" - $dateLocalMod ="" + $dateLocalMod = "" $wc.OpenRead("$ExternalMods/$_").Close() | Out-Null $dateExternalMod = ([DateTime]$wc.ResponseHeaders['Last-Modified']).ToString("yyyy-MM-dd HH:mm:ss") if (Test-Path -Path $LocalMods"\"$_) { $dateLocalMod = (Get-Item "$LocalMods\$_").LastWriteTime.ToString("yyyy-MM-dd HH:mm:ss") } - + if ($dateExternalMod -gt $dateLocalMod) { try { $SaveMod = Join-Path -Path "$LocalMods\" -ChildPath $_ @@ -134,21 +134,60 @@ function Test-ModsPath ($ModsPath, $WingetUpdatePath) { } return $ModsUpdated, $DeletedMods } + # If Path is Azure Blob + elseif ($ExternalMods -like "AzureBlob") { + Write-ToLog "Azure Blob Storage set as mod source" + Write-ToLog "Checking AZCopy" + Get-AZCopy $WingetUpdatePath + #Safety check to make sure we really do have azcopy.exe and a Blob URL + if ((Test-Path -Path "$WingetUpdatePath\azcopy.exe" -PathType Leaf) -and ($null -ne $AzureBlobSASURL)) { + Write-ToLog "Syncing Blob storage with local storage" + + $AZCopySyncOutput = & $WingetUpdatePath\azcopy.exe sync "$AzureBlobSASURL" "$LocalMods" --from-to BlobLocal --delete-destination=true + $AZCopyOutputLines = $AZCopySyncOutput.Split([Environment]::NewLine) + + foreach ( $_ in $AZCopyOutputLines) { + $AZCopySyncAdditionsRegex = [regex]::new("(?<=Number of Copy Transfers Completed:\s+)\d+") + $AZCopySyncDeletionsRegex = [regex]::new("(?<=Number of Deletions at Destination:\s+)\d+") + $AZCopySyncErrorRegex = [regex]::new("^Cannot perform sync due to error:") + + $AZCopyAdditions = [int] $AZCopySyncAdditionsRegex.Match($_).Value + $AZCopyDeletions = [int] $AZCopySyncDeletionsRegex.Match($_).Value + + if ($AZCopyAdditions -ne 0) { + $ModsUpdated = $AZCopyAdditions + } + + if ($AZCopyDeletions -ne 0) { + $DeletedMods = $AZCopyDeletions + } + + if ($AZCopySyncErrorRegex.Match($_).Value) { + Write-ToLog "AZCopy Sync Error! $_" + } + } + } + else { + Write-ToLog "Error 'azcopy.exe' or SAS Token not found!" + } + + return $ModsUpdated, $DeletedMods + } # If path is UNC or local else { $ExternalBins = "$ModsPath\bins" if (Test-Path -Path $ExternalBins"\*.exe") { $ExternalBinsNames = Get-ChildItem -Path $ExternalBins -Name -Recurse -Include *.exe #Delete Local Bins that don't exist Externally - foreach ($Bin in $InternalBinsNames){ - If ($Bin -notin $ExternalBinsNames ){ + foreach ($Bin in $InternalBinsNames) { + If ($Bin -notin $ExternalBinsNames ) { Remove-Item $LocalMods\bins\$Bin -Force -ErrorAction SilentlyContinue | Out-Null } } #Copy newer external bins - foreach ($Bin in $ExternalBinsNames){ + foreach ($Bin in $ExternalBinsNames) { $dateExternalBin = "" - $dateLocalBin ="" + $dateLocalBin = "" if (Test-Path -Path $LocalMods"\bins\"$Bin) { $dateLocalBin = (Get-Item "$LocalMods\bins\$Bin").LastWriteTime.ToString("yyyy-MM-dd HH:mm:ss") } @@ -162,20 +201,20 @@ function Test-ModsPath ($ModsPath, $WingetUpdatePath) { if ((Test-Path -Path $ExternalMods"\*.ps1") -or (Test-Path -Path $ExternalMods"\*.txt")) { #Get File Names Externally $ExternalModsNames = Get-ChildItem -Path $ExternalMods -Name -Recurse -Include *.ps1, *.txt - + #Delete Local Mods that don't exist Externally $DeletedMods = 0 - foreach ($Mod in $InternalModsNames){ - If ($Mod -notin $ExternalModsNames ){ + foreach ($Mod in $InternalModsNames) { + If ($Mod -notin $ExternalModsNames ) { Remove-Item $LocalMods\$Mod -Force -ErrorAction SilentlyContinue | Out-Null $DeletedMods++ } } #Copy newer external mods - foreach ($Mod in $ExternalModsNames){ + foreach ($Mod in $ExternalModsNames) { $dateExternalMod = "" - $dateLocalMod ="" + $dateLocalMod = "" if (Test-Path -Path $LocalMods"\"$Mod) { $dateLocalMod = (Get-Item "$LocalMods\$Mod").LastWriteTime.ToString("yyyy-MM-dd HH:mm:ss") } diff --git a/Winget-AutoUpdate/functions/Test-Network.ps1 b/Winget-AutoUpdate/functions/Test-Network.ps1 index a726373..5e4fc4f 100644 --- a/Winget-AutoUpdate/functions/Test-Network.ps1 +++ b/Winget-AutoUpdate/functions/Test-Network.ps1 @@ -1,4 +1,4 @@ -#Function to check connectivity +#Function to check the connectivity function Test-Network { @@ -9,7 +9,7 @@ function Test-Network { $ProgressPreference = 'SilentlyContinue' #Test connectivity during 30 min then timeout - Write-Log "Checking internet connection..." "Yellow" + Write-ToLog "Checking internet connection..." "Yellow" While ($timeout -lt 1800) { $URLtoTest = "https://raw.githubusercontent.com/Romanitho/Winget-AutoUpdate/main/LICENSE" @@ -17,7 +17,7 @@ function Test-Network { if ($URLcontent -like "*MIT License*") { - Write-Log "Connected !" "Green" + Write-ToLog "Connected !" "Green" #Check for metered connection [void][Windows.Networking.Connectivity.NetworkInformation, Windows, ContentType = WindowsRuntime] @@ -25,17 +25,17 @@ function Test-Network { if ($cost.ApproachingDataLimit -or $cost.OverDataLimit -or $cost.Roaming -or $cost.BackgroundDataUsageRestricted -or ($cost.NetworkCostType -ne "Unrestricted")) { - Write-Log "Metered connection detected." "Yellow" + Write-ToLog "Metered connection detected." "Yellow" if ($WAUConfig.WAU_DoNotRunOnMetered -eq 1) { - Write-Log "WAU is configured to bypass update checking on metered connection" + Write-ToLog "WAU is configured to bypass update checking on metered connection" return $false } else { - Write-Log "WAU is configured to force update checking on metered connection" + Write-ToLog "WAU is configured to force update checking on metered connection" return $true } @@ -56,7 +56,7 @@ function Test-Network { #Send Warning Notif if no connection for 5 min if ($timeout -eq 300) { #Log - Write-Log "Notify 'No connection' sent." "Yellow" + Write-ToLog "Notify 'No connection' sent." "Yellow" #Notif $Title = $NotifLocale.local.outputs.output[0].title @@ -71,7 +71,7 @@ function Test-Network { } #Send Timeout Notif if no connection for 30 min - Write-Log "Timeout. No internet connection !" "Red" + Write-ToLog "Timeout. No internet connection !" "Red" #Notif $Title = $NotifLocale.local.outputs.output[1].title diff --git a/Winget-AutoUpdate/functions/Test-PendingReboot.ps1 b/Winget-AutoUpdate/functions/Test-PendingReboot.ps1 index 55bc72f..bb1d52e 100644 --- a/Winget-AutoUpdate/functions/Test-PendingReboot.ps1 +++ b/Winget-AutoUpdate/functions/Test-PendingReboot.ps1 @@ -1,4 +1,4 @@ -#Function to check if there's a Pending Reboot +#Function to check if there is a Pending Reboot function Test-PendingReboot { diff --git a/Winget-AutoUpdate/functions/Update-App.ps1 b/Winget-AutoUpdate/functions/Update-App.ps1 index 11096a4..95b3064 100644 --- a/Winget-AutoUpdate/functions/Update-App.ps1 +++ b/Winget-AutoUpdate/functions/Update-App.ps1 @@ -1,15 +1,15 @@ -#Function to Update an App +#Function to update an App Function Update-App ($app) { #Get App Info $ReleaseNoteURL = Get-AppInfo $app.Id - if ($ReleaseNoteURL){ + if ($ReleaseNoteURL) { $Button1Text = $NotifLocale.local.outputs.output[10].message } #Send available update notification - Write-Log "Updating $($app.Name) from $($app.Version) to $($app.AvailableVersion)..." "Cyan" + Write-ToLog "Updating $($app.Name) from $($app.Version) to $($app.AvailableVersion)..." "Cyan" $Title = $NotifLocale.local.outputs.output[2].title -f $($app.Name) $Message = $NotifLocale.local.outputs.output[2].message -f $($app.Version), $($app.AvailableVersion) $MessageType = "info" @@ -20,26 +20,26 @@ Function Update-App ($app) { $ModsPreInstall, $ModsOverride, $ModsUpgrade, $ModsInstall, $ModsInstalled = Test-Mods $($app.Id) #Winget upgrade - Write-Log "########## WINGET UPGRADE PROCESS STARTS FOR APPLICATION ID '$($App.Id)' ##########" "Gray" + Write-ToLog "########## WINGET UPGRADE PROCESS STARTS FOR APPLICATION ID '$($App.Id)' ##########" "Gray" #If PreInstall script exist if ($ModsPreInstall) { - Write-Log "Modifications for $($app.Id) before upgrade are being applied..." "Yellow" + Write-ToLog "Modifications for $($app.Id) before upgrade are being applied..." "Yellow" & "$ModsPreInstall" } #Run Winget Upgrade command if ($ModsOverride) { - Write-Log "-> Running (overriding default): Winget upgrade --id $($app.Id) --accept-package-agreements --accept-source-agreements --override $ModsOverride" + Write-ToLog "-> Running (overriding default): Winget upgrade --id $($app.Id) --accept-package-agreements --accept-source-agreements --override $ModsOverride" & $Winget upgrade --id $($app.Id) --accept-package-agreements --accept-source-agreements --override $ModsOverride | Tee-Object -file $LogFile -Append } else { - Write-Log "-> Running: Winget upgrade --id $($app.Id) --accept-package-agreements --accept-source-agreements -h" + Write-ToLog "-> Running: Winget upgrade --id $($app.Id) --accept-package-agreements --accept-source-agreements -h" & $Winget upgrade --id $($app.Id) --accept-package-agreements --accept-source-agreements -h | Tee-Object -file $LogFile -Append } if ($ModsUpgrade) { - Write-Log "Modifications for $($app.Id) during upgrade are being applied..." "Yellow" + Write-ToLog "Modifications for $($app.Id) during upgrade are being applied..." "Yellow" & "$ModsUpgrade" } @@ -53,25 +53,25 @@ Function Update-App ($app) { #Test for a Pending Reboot (Component Based Servicing/WindowsUpdate/CCM_ClientUtilities) $PendingReboot = Test-PendingReboot if ($PendingReboot -eq $true) { - Write-Log "-> A Pending Reboot lingers and probably prohibited $($app.Name) from upgrading...`n-> ...an install for $($app.Name) is NOT executed!" "Red" + Write-ToLog "-> A Pending Reboot lingers and probably prohibited $($app.Name) from upgrading...`n-> ...an install for $($app.Name) is NOT executed!" "Red" $FailedToUpgrade = $true break } #If app failed to upgrade, run Install command - Write-Log "-> An upgrade for $($app.Name) failed, now trying an install instead..." "Yellow" - + Write-ToLog "-> An upgrade for $($app.Name) failed, now trying an install instead..." "Yellow" + if ($ModsOverride) { - Write-Log "-> Running (overriding default): Winget install --id $($app.Id) --accept-package-agreements --accept-source-agreements --override $ModsOverride" + Write-ToLog "-> Running (overriding default): Winget install --id $($app.Id) --accept-package-agreements --accept-source-agreements --override $ModsOverride" & $Winget install --id $($app.Id) --accept-package-agreements --accept-source-agreements --override $ModsOverride | Tee-Object -file $LogFile -Append } else { - Write-Log "-> Running: Winget install --id $($app.Id) --accept-package-agreements --accept-source-agreements -h" + Write-ToLog "-> Running: Winget install --id $($app.Id) --accept-package-agreements --accept-source-agreements -h" & $Winget install --id $($app.Id) --accept-package-agreements --accept-source-agreements -h | Tee-Object -file $LogFile -Append } if ($ModsInstall) { - Write-Log "Modifications for $($app.Id) during install are being applied..." "Yellow" + Write-ToLog "Modifications for $($app.Id) during install are being applied..." "Yellow" & "$ModsInstall" } @@ -87,18 +87,18 @@ Function Update-App ($app) { if ($FailedToUpgrade -eq $false) { if ($ModsInstalled) { - Write-Log "Modifications for $($app.Id) after upgrade/install are being applied..." "Yellow" + Write-ToLog "Modifications for $($app.Id) after upgrade/install are being applied..." "Yellow" & "$ModsInstalled" } } - Write-Log "########## WINGET UPGRADE PROCESS FINISHED FOR APPLICATION ID '$($App.Id)' ##########" "Gray" + Write-ToLog "########## WINGET UPGRADE PROCESS FINISHED FOR APPLICATION ID '$($App.Id)' ##########" "Gray" #Notify installation if ($FailedToUpgrade -eq $false) { #Send success updated app notification - Write-Log "$($app.Name) updated to $($app.AvailableVersion) !" "Green" + Write-ToLog "$($app.Name) updated to $($app.AvailableVersion) !" "Green" #Send Notif $Title = $NotifLocale.local.outputs.output[3].title -f $($app.Name) @@ -113,7 +113,7 @@ Function Update-App ($app) { else { #Send failed updated app notification - Write-Log "$($app.Name) update failed." "Red" + Write-ToLog "$($app.Name) update failed." "Red" #Send Notif $Title = $NotifLocale.local.outputs.output[4].title -f $($app.Name) diff --git a/Winget-AutoUpdate/functions/Update-WAU.ps1 b/Winget-AutoUpdate/functions/Update-WAU.ps1 index 25a158f..123deb9 100644 --- a/Winget-AutoUpdate/functions/Update-WAU.ps1 +++ b/Winget-AutoUpdate/functions/Update-WAU.ps1 @@ -1,4 +1,4 @@ -#Function to Update WAU +#Function to update WAU function Update-WAU { @@ -19,44 +19,44 @@ function Update-WAU { New-Item $ZipFile -ItemType File -Force | Out-Null #Download the zip - Write-Log "Downloading the GitHub Repository version $WAUAvailableVersion" "Cyan" - Invoke-RestMethod -Uri "https://github.com/Romanitho/Winget-AutoUpdate/archive/refs/tags/v$($WAUAvailableVersion).zip/" -OutFile $ZipFile + Write-ToLog "Downloading the GitHub Repository version $WAUAvailableVersion" "Cyan" + Invoke-RestMethod -Uri "https://github.com/Romanitho/Winget-AutoUpdate/releases/download/v$($WAUAvailableVersion)/WAU.zip" -OutFile $ZipFile #Extract Zip File - Write-Log "Unzipping the WAU GitHub Repository" "Cyan" + Write-ToLog "Unzipping the WAU Update package" "Cyan" $location = "$WorkingDir\WAU_update" Expand-Archive -Path $ZipFile -DestinationPath $location -Force Get-ChildItem -Path $location -Recurse | Unblock-File #Update scritps - Write-Log "Updating WAU" "Yellow" - $TempPath = (Resolve-Path "$location\*\Winget-AutoUpdate\")[0].Path + Write-ToLog "Updating WAU..." "Yellow" + $TempPath = (Resolve-Path "$location\Winget-AutoUpdate\")[0].Path if ($TempPath) { Copy-Item -Path "$TempPath\*" -Destination "$WorkingDir\" -Exclude "icons" -Recurse -Force } #Remove update zip file and update temp folder - Write-Log "Done. Cleaning temp files" "Cyan" + Write-ToLog "Done. Cleaning temp files..." "Cyan" Remove-Item -Path $ZipFile -Force -ErrorAction SilentlyContinue Remove-Item -Path $location -Recurse -Force -ErrorAction SilentlyContinue #Set new version to registry $WAUConfig | New-ItemProperty -Name DisplayVersion -Value $WAUAvailableVersion -Force - $WAUConfig | New-ItemProperty -Name VersionMajor -Value ([version]$WAUAvailableVersion).Major -Force - $WAUConfig | New-ItemProperty -Name VersionMinor -Value ([version]$WAUAvailableVersion).Minor -Force + $WAUConfig | New-ItemProperty -Name VersionMajor -Value ([version]$WAUAvailableVersion.Replace("-", ".")).Major -Force + $WAUConfig | New-ItemProperty -Name VersionMinor -Value ([version]$WAUAvailableVersion.Replace("-", ".")).Minor -Force #Set Post Update actions to 1 $WAUConfig | New-ItemProperty -Name WAU_PostUpdateActions -Value 1 -Force #Send success Notif - Write-Log "WAU Update completed." "Green" + Write-ToLog "WAU Update completed." "Green" $Title = $NotifLocale.local.outputs.output[3].title -f "Winget-AutoUpdate" $Message = $NotifLocale.local.outputs.output[3].message -f $WAUAvailableVersion $MessageType = "success" Start-NotifTask -Title $Title -Message $Message -MessageType $MessageType -Button1Action $OnClickAction -Button1Text $Button1Text #Rerun with newer version - Write-Log "Re-run WAU" + Write-ToLog "Re-run WAU" Start-Process powershell -ArgumentList "-NoProfile -ExecutionPolicy Bypass -Command `"$WorkingDir\winget-upgrade.ps1`"" exit @@ -70,7 +70,7 @@ function Update-WAU { $Message = $NotifLocale.local.outputs.output[4].message $MessageType = "error" Start-NotifTask -Title $Title -Message $Message -MessageType $MessageType -Button1Action $OnClickAction -Button1Text $Button1Text - Write-Log "WAU Update failed" "Red" + Write-ToLog "WAU Update failed" "Red" } diff --git a/Winget-AutoUpdate/functions/Write-Log.ps1 b/Winget-AutoUpdate/functions/Write-ToLog.ps1 similarity index 72% rename from Winget-AutoUpdate/functions/Write-Log.ps1 rename to Winget-AutoUpdate/functions/Write-ToLog.ps1 index aa30cb2..db1116e 100644 --- a/Winget-AutoUpdate/functions/Write-Log.ps1 +++ b/Winget-AutoUpdate/functions/Write-ToLog.ps1 @@ -1,6 +1,6 @@ -#Write Log Function +#Write to Log Function -function Write-Log ($LogMsg, $LogColor = "White") { +function Write-ToLog ($LogMsg, $LogColor = "White") { #Get log $Log = "$(Get-Date -UFormat "%T") - $LogMsg" diff --git a/Winget-AutoUpdate/locale/de.xml b/Winget-AutoUpdate/locale/de.xml index bb95779..1fbeb63 100644 --- a/Winget-AutoUpdate/locale/de.xml +++ b/Winget-AutoUpdate/locale/de.xml @@ -49,6 +49,7 @@ Die manuelle suche nach Updates wurde abgeschlossen. + See changelog diff --git a/Winget-AutoUpdate/locale/en.xml b/Winget-AutoUpdate/locale/en.xml index 6f927b0..b7c6479 100644 --- a/Winget-AutoUpdate/locale/en.xml +++ b/Winget-AutoUpdate/locale/en.xml @@ -43,8 +43,8 @@ Couldn't start a manual check for updated apps! - - Check for updated apps already running... + + A check for updated apps already running... diff --git a/Winget-AutoUpdate/locale/nb.xml b/Winget-AutoUpdate/locale/nb.xml new file mode 100644 index 0000000..0e1923c --- /dev/null +++ b/Winget-AutoUpdate/locale/nb.xml @@ -0,0 +1,62 @@ + + + + + Sjekk nettverkstilkoblingen. + + Kan ikke se etter programvareoppdateringer for øyeblikket! + + + + Ingen internettforbindelse. + + Oppdateringer kunne ikke bekreftes. + + + + {0} vil bli oppdatert! + + {0} til {1} + + + + {0} oppdatert. + + Installert versjon: {0} + + + + {0} kunne ikke oppdateres! + + Vennligst kontakt support. + + + + Logger er ikke tilgjengelig ennå! + + + + Starter en manuell sjekk for oppdaterte apper... + + + + Kunne ikke starte en manuell sjekk for oppdaterte apper! + + + + Se etter oppdaterte apper kjører allerede... + + + + Manuell sjekk for oppdaterte apper fullført... + + + + Se endringslogg + + + + Åpne loggfilen + + + diff --git a/Winget-AutoUpdate/locale/nl.xml b/Winget-AutoUpdate/locale/nl.xml index c08bfed..9e28c5b 100644 --- a/Winget-AutoUpdate/locale/nl.xml +++ b/Winget-AutoUpdate/locale/nl.xml @@ -4,59 +4,59 @@ Controleer de netwerkverbinding. - Er kan op dit moment niet gecontroleerd worden op software-updates! + Er kan op dit moment niet gecontroleerd worden op software updates! Geen internetverbinding. - Updates kon niet worden gecontroleerd. + Updates konden niet worden gecontroleerd. - {0} wordt geupdate! + {0} zal geüpdatet worden ! {0} to {1} - {0} geupdate. + {0} is geüpdatet. - Geinstalleerde versie: {0} + Geïnstalleerde versie: {0} - {0} kan niet worden geupdate! + {0} kan niet worden geüpdatet! Neem contact op met support. - Logs are not available yet! + Logs zijn nog niet beschikbaar ! - Starting a manual check for updated apps... + Start een manuele controle op software updates... - Couldn't start a manual check for updated apps! + Kon geen manuele controle op software updates starten! - Check for updated apps already running... + Er wordt al naar software updates gezocht... - Manual check for updated apps completed... + Manuele controle op software updates voltooid... - See changelog + Zie changelog - Open log file + Open logbestand diff --git a/Winget-AutoUpdate/locale/sv.xml b/Winget-AutoUpdate/locale/sv.xml index 73bd603..8e0de4a 100644 --- a/Winget-AutoUpdate/locale/sv.xml +++ b/Winget-AutoUpdate/locale/sv.xml @@ -43,7 +43,7 @@ Kunde inte starta en manuell koll efter uppdaterade appar! - + En koll efter uppdaterade appar körs redan... diff --git a/Winget-AutoUpdate/mods/_AppID-template.ps1 b/Winget-AutoUpdate/mods/_AppID-template.ps1 index b1344cf..72eb8df 100644 --- a/Winget-AutoUpdate/mods/_AppID-template.ps1 +++ b/Winget-AutoUpdate/mods/_AppID-template.ps1 @@ -1,6 +1,6 @@ <# ARRAYS/VARIABLES #> #App to Run (as SYSTEM) -#$RunWait = $False if it shouldn't be waited for completion. Example: +#$RunWait = $False if it shouldn't be waited for completion. For example: #$RunSystem = "$PSScriptRoot\bins\MsiZap.exe" #$RunSwitch = "tw! {GUID}" $RunSystem = "" @@ -13,9 +13,18 @@ $Proc = @("") #Beginning of Process Name to Wait for to End - optional wildcard (*) after, without .exe, multiple: "proc1","proc2" $Wait = @("") +#Install App from Winget Repo, multiple: "appID1","appID2". Example: +#$WingetIDInst = @("Microsoft.PowerToys") +$WingetIDInst = @("") + +#WingetID to uninstall in default manifest mode (silent if supported) +#Multiple: "ID1","ID2". Example: +#$WingetIDUninst = @("Microsoft.PowerToys") +$WingetIDUninst = @("") + #Beginning of App Name string to Silently Uninstall (MSI/NSIS/INNO/EXE with defined silent uninstall in registry) #Multiple: "app1*","app2*", required wildcard (*) after; search is done with "-like"! -$App = @("") +$AppUninst = @("") #Beginning of Desktop Link Name to Remove - optional wildcard (*) after, without .lnk, multiple: "lnk1","lnk2" $Lnk = @("") @@ -37,18 +46,23 @@ $AddType = "" $DelKey = "" $DelValue = "" -#Remove file/directory, multiple: "file1","file2" +#Remove file/directory, multiple: "file1","file2" Example: +#$DelFile = @("${env:ProgramFiles}\PowerToys\PowerToys.Update.exe") $DelFile = @("") -#Copy file/directory -#Example: +#Rename file/directory. Example: +#$RenFile = "${env:ProgramFiles}\PowerToys\PowerToys.Update.exe" +#$NewName = "PowerToys.Update.org" +$RenFile = "" +$NewName = "" + +#Copy file/directory. Example: #$CopyFile = "C:\Logfiles" #$CopyTo = "C:\Drawings\Logs" $CopyFile = "" $CopyTo = "" -#Find/Replace text in file -#Example: +#Find/Replace text in file. Example: #$File = "C:\dummy.txt" #$FindText = 'brown fox' #$ReplaceText = 'white fox' @@ -59,10 +73,6 @@ $ReplaceText = '' #Grant "Modify" for directory/file to "Authenticated Users" - multiple: "dir1","dir2" $GrantPath = @("") -#Install App from Winget Repo, multiple: "appID1","appID2". Example: -#$AppID = @("Microsoft.PowerToys") -$AppID = @("") - #App to Run (as current logged-on user) $RunUser = "" $User = $True @@ -80,8 +90,14 @@ if ($Proc) { if ($Wait) { Wait-ModsProc $Wait } -if ($App) { - Uninstall-ModsApp $App +if ($WingetIDInst) { + Install-WingetID $WingetIDInst +} +if ($WingetIDUninst) { + Uninstall-WingetID $WingetIDUninst +} +if ($AppUninst) { + Uninstall-ModsApp $AppUninst } if ($Lnk) { Remove-ModsLnk $Lnk @@ -95,6 +111,9 @@ if ($DelKey) { if ($DelFile) { Remove-ModsFile $DelFile } +if ($RenFile -and $NewName) { + Rename-ModsFile $RenFile $NewName +} if ($CopyFile -and $CopyTo) { Copy-ModsFile $CopyFile $CopyTo } @@ -104,9 +123,6 @@ if ($File -and $FindText -and $ReplaceText) { if ($GrantPath) { Grant-ModsPath $GrantPath } -if ($AppID) { - Install-ModsApp $AppID -} if ($RunUser) { Invoke-ModsApp $RunUser "" "" $User } diff --git a/Winget-AutoUpdate/mods/_Mods-Functions.ps1 b/Winget-AutoUpdate/mods/_Mods-Functions.ps1 index 054e331..63e64d1 100644 --- a/Winget-AutoUpdate/mods/_Mods-Functions.ps1 +++ b/Winget-AutoUpdate/mods/_Mods-Functions.ps1 @@ -1,45 +1,56 @@ -#Common shared functions for mods handling +#Common shared functions to handle the mods function Invoke-ModsApp ($Run, $RunSwitch, $RunWait, $User) { if (Test-Path "$Run") { - if (!$RunSwitch) {$RunSwitch = " "} - if (!$User) { - if (!$RunWait) { - Start-Process $Run -ArgumentList $RunSwitch - } - else { - Start-Process $Run -ArgumentList $RunSwitch -Wait - } - } - else { - Start-Process explorer $Run - } + if (!$RunSwitch) { $RunSwitch = " " } + if (!$User) { + if (!$RunWait) { + Start-Process $Run -ArgumentList $RunSwitch + } + else { + Start-Process $Run -ArgumentList $RunSwitch -Wait + } + } + else { + Start-Process explorer $Run + } } Return } function Stop-ModsProc ($Proc) { - foreach ($process in $Proc) - { + foreach ($process in $Proc) { Stop-Process -Name $process -Force -ErrorAction SilentlyContinue | Out-Null } Return } function Wait-ModsProc ($Wait) { - foreach ($process in $Wait) - { + foreach ($process in $Wait) { Get-Process $process -ErrorAction SilentlyContinue | Foreach-Object { $_.WaitForExit() } } Return } -function Uninstall-ModsApp ($App) { - foreach ($app in $App) - { +function Install-WingetID ($WingetIDInst) { + foreach ($app in $WingetIDInst) { + & $Winget install --id $app --accept-package-agreements --accept-source-agreements -h + } + Return +} + +function Uninstall-WingetID ($WingetIDUninst) { + foreach ($app in $WingetIDUninst) { + & $Winget uninstall --id $app -e --accept-source-agreements -h + } + Return +} + +function Uninstall-ModsApp ($AppUninst) { + foreach ($app in $AppUninst) { $InstalledSoftware = Get-ChildItem "HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall" - foreach ($obj in $InstalledSoftware){ + foreach ($obj in $InstalledSoftware) { if ($obj.GetValue('DisplayName') -like $App) { $UninstallString = $obj.GetValue('UninstallString') $CleanedUninstallString = $UninstallString.Trim([char]0x0022) @@ -95,7 +106,7 @@ function Uninstall-ModsApp ($App) { } if (!$x64) { $InstalledSoftware = Get-ChildItem "HKLM:\Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall" - foreach ($obj in $InstalledSoftware){ + foreach ($obj in $InstalledSoftware) { if ($obj.GetValue('DisplayName') -like $App) { $UninstallString = $obj.GetValue('UninstallString') $CleanedUninstallString = $UninstallString.Trim([char]0x0022) @@ -153,8 +164,7 @@ function Uninstall-ModsApp ($App) { Return } function Remove-ModsLnk ($Lnk) { - foreach ($link in $Lnk) - { + foreach ($link in $Lnk) { Remove-Item -Path "${env:Public}\Desktop\$link.lnk" -Force -ErrorAction SilentlyContinue | Out-Null } Return @@ -162,7 +172,7 @@ function Remove-ModsLnk ($Lnk) { function Add-ModsReg ($AddKey, $AddValue, $AddTypeData, $AddType) { if ($AddKey -like "HKEY_LOCAL_MACHINE*") { - $AddKey = $AddKey.replace("HKEY_LOCAL_MACHINE","HKLM:") + $AddKey = $AddKey.replace("HKEY_LOCAL_MACHINE", "HKLM:") } if (!(Test-Path "$AddKey")) { New-Item $AddKey -Force -ErrorAction SilentlyContinue | Out-Null @@ -173,7 +183,7 @@ function Add-ModsReg ($AddKey, $AddValue, $AddTypeData, $AddType) { function Remove-ModsReg ($DelKey, $DelValue) { if ($DelKey -like "HKEY_LOCAL_MACHINE*") { - $DelKey = $DelKey.replace("HKEY_LOCAL_MACHINE","HKLM:") + $DelKey = $DelKey.replace("HKEY_LOCAL_MACHINE", "HKLM:") } if (Test-Path "$DelKey") { if (!$DelValue) { @@ -187,8 +197,7 @@ function Remove-ModsReg ($DelKey, $DelValue) { } function Remove-ModsFile ($DelFile) { - foreach ($file in $DelFile) - { + foreach ($file in $DelFile) { if (Test-Path "$file") { Remove-Item -Path $file -Force -Recurse -ErrorAction SilentlyContinue | Out-Null } @@ -196,6 +205,13 @@ function Remove-ModsFile ($DelFile) { Return } +function Rename-ModsFile ($RenFile, $NewName) { + if (Test-Path "$RenFile") { + Rename-Item -Path $RenFile -NewName $NewName -Force -ErrorAction SilentlyContinue | Out-Null + } + Return +} + function Copy-ModsFile ($CopyFile, $CopyTo) { if (Test-Path "$CopyFile") { Copy-Item -Path $CopyFile -Destination $CopyTo -Recurse -Force -ErrorAction SilentlyContinue | Out-Null @@ -205,14 +221,13 @@ function Copy-ModsFile ($CopyFile, $CopyTo) { function Edit-ModsFile ($File, $FindText, $ReplaceText) { if (Test-Path "$File") { - ((Get-Content -path $File -Raw) -replace "$FindText","$ReplaceText") | Set-Content -Path $File -Force -ErrorAction SilentlyContinue | Out-Null + ((Get-Content -path $File -Raw) -replace "$FindText", "$ReplaceText") | Set-Content -Path $File -Force -ErrorAction SilentlyContinue | Out-Null } Return } function Grant-ModsPath ($GrantPath) { - foreach ($path in $GrantPath) - { + foreach ($path in $GrantPath) { if (Test-Path "$path") { $NewAcl = Get-Acl -Path $path $identity = New-Object System.Security.Principal.SecurityIdentifier S-1-5-11 @@ -229,11 +244,3 @@ function Grant-ModsPath ($GrantPath) { } Return } - -function Install-ModsApp ($AppID) { - foreach ($app in $AppID) - { - & $Winget install --id $app --accept-package-agreements --accept-source-agreements -h - } - Return -}