Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
cfc58fb
Delete AppMap.ps1
TecharyAdam Feb 4, 2026
806f558
Delete Intune-Packager.ps1
TecharyAdam Feb 4, 2026
f8d2b4e
Delete TecharyGet.psd1
TecharyAdam Feb 4, 2026
987470a
Delete TecharyGet.psm1
TecharyAdam Feb 4, 2026
4004e23
Add files via upload
TecharyAdam Feb 4, 2026
a010d5e
Revise README.md for TecharyGet module details
TecharyAdam Feb 4, 2026
75da1dd
Revise README by removing outdated sections
TecharyAdam Feb 4, 2026
b28813c
Update README to streamline installation and usage
TecharyAdam Feb 4, 2026
b6503ab
Add Install-TecharyApp function for app installation
TecharyAdam Mar 9, 2026
a722e94
Rename Install-SmartApp.ps1 to Install-TecharyApp.ps1
TecharyAdam Mar 9, 2026
d59103c
Add Uninstall-TecharyApp function for app removal
TecharyAdam Mar 9, 2026
0592b69
Rename Install-SmartApp to Install-TecharyApp
TecharyAdam Mar 9, 2026
f094a98
Update Install-TecharyApp function for MSI fallback
TecharyAdam Mar 9, 2026
dfd243c
Refactor TecharyGet.psm1 for consistency
TecharyAdam Mar 9, 2026
ed4e88e
Update module manifest for TecharyGet
TecharyAdam Mar 9, 2026
4d9c0fe
Update TecharyGet module manifest with new functions
TecharyAdam Mar 9, 2026
315ba93
Update TecharyGet.psd1
TecharyAdam Mar 9, 2026
230a31d
Delete Public/Get-GitHubInstaller.ps1
TecharyAdam Mar 9, 2026
f2b0eb3
Delete Public/Install-AppPackage.ps1
TecharyAdam Mar 9, 2026
686b9b1
Delete Public/Install-NableAgent.ps1
TecharyAdam Mar 9, 2026
182e62e
Delete Public/Install-TecharyApp.ps1
TecharyAdam Mar 9, 2026
9958f1a
Delete Public/Invoke-PackagerCleanup.ps1
TecharyAdam Mar 9, 2026
28b91e2
Delete Public/New-IntunePackage.ps1
TecharyAdam Mar 9, 2026
c1c62bf
Delete Public/New-IntunePackageUI.ps1
TecharyAdam Mar 9, 2026
292bad8
Delete Public/Uninstall-TecharyApp.ps1
TecharyAdam Mar 9, 2026
d6f4a83
Delete Public/Write-PackagerLog.ps1
TecharyAdam Mar 9, 2026
ddf7ffe
Add aa.txt with initial content 'aa'
TecharyAdam Mar 9, 2026
533b85f
Add files via upload
TecharyAdam Mar 9, 2026
30ee674
Update TecharyGet.psd1
TecharyAdam Mar 9, 2026
f329355
Delete Public/aa.txt
TecharyAdam Mar 10, 2026
b58ab70
Update TecharyGet.psd1
TecharyAdam Mar 10, 2026
3f033ad
Update TecharyGet.psd1
TecharyAdam Mar 10, 2026
c53aa25
Refactor Install-NableAgent function
TecharyAdam Mar 10, 2026
ec8c178
Update TecharyGet.psd1
TecharyAdam Mar 10, 2026
f20dead
Update README with Nable Agent installation example
TecharyAdam Mar 10, 2026
fe90072
Update Get-GitHubInstaller.ps1
TecharyAdam Mar 11, 2026
cbac32d
Update Get-GitHubInstaller.ps1
TecharyAdam Mar 11, 2026
11db0ca
Update README with App ID details
TecharyAdam Mar 11, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
589 changes: 0 additions & 589 deletions AppMap.ps1

This file was deleted.

176 changes: 0 additions & 176 deletions Intune-Packager.ps1

This file was deleted.

23 changes: 23 additions & 0 deletions Private/CustomApps.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
[
{
"Id": "MyDPD",
"Url": "https://apis.my.dpd.co.uk/apps/download/public",
"SilentArgs": "--Silent",
"InstallerType": "exe",
"DisplayName": "MyDPD"
},
{
"Id": "RoyalMail",
"Url": "http://app.printnode.com/download/client/royalmail/windows",
"SilentArgs": "/VERYSILENT /SUPPRESSMSGBOXES",
"InstallerType": "exe",
"DisplayName": "Royal Mail"
},
{
"Id": "Crosschex",
"Url": "https://www.anviz.com/file/download/5539/CrossChex_Standard_4.3.16.exe",
"SilentArgs": "/exenoui ALLUSERS=1 /qn",
"InstallerType": "exe",
"DisplayName": "Crosschex"
}
]
67 changes: 67 additions & 0 deletions Private/Get-CustomApp.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
function Get-CustomApp {
param (
[string]$Id
)

# --- 1. CLOUD SOURCE ---
# We use the "Raw" GitHub URL so we get just the JSON text.
# Structure: https://raw.githubusercontent.com/<User>/<Repo>/<Branch>/<PathToFile>
$CloudUrl = "https://raw.githubusercontent.com/Techary/TecharyGet/BETA/TecharyGet/Private/CustomApps.json"

# --- 2. LOCAL CACHE ---
# We cache the file locally so the script works even if GitHub is briefly down
# or if the machine is offline (using the last known good copy).
$CacheDir = "$env:PROGRAMDATA\TecharyGet"
$CachePath = "$CacheDir\CustomApps_Cache.json"

# --- 3. SYNC LOGIC ---
try {
if (-not (Test-Path $CacheDir)) { New-Item -ItemType Directory -Path $CacheDir -Force | Out-Null }

# Logic: Only download if the cache doesn't exist OR it's older than 60 minutes.
# This prevents spamming GitHub every time you run a command.
$NeedUpdate = $true
if (Test-Path $CachePath) {
$LastWrite = (Get-Item $CachePath).LastWriteTime
if ((Get-Date) -lt $LastWrite.AddMinutes(60)) { $NeedUpdate = $false }
}

if ($NeedUpdate) {
Write-PackagerLog -Message "Syncing Custom Catalog from GitHub..." -Severity Info
Invoke-WebRequest -Uri $CloudUrl -OutFile $CachePath -UseBasicParsing -ErrorAction Stop
}
}
catch {
Write-PackagerLog -Message "Could not sync from GitHub (Offline?). Using local cache." -Severity Warning
}

# --- 4. READ DATA ---
$JsonContent = $null

# Prefer the fresh Cache
if (Test-Path $CachePath) {
$JsonContent = Get-Content -Path $CachePath -Raw
}
# Fallback to the file shipped with the module (if cache is empty/broken)
else {
$LocalModulePath = Join-Path (Split-Path $PSScriptRoot -Parent) "Private\CustomApps.json"
if (Test-Path $LocalModulePath) {
$JsonContent = Get-Content -Path $LocalModulePath -Raw
}
}

# --- 5. PARSE & RETURN ---
if ($JsonContent) {
try {
$Data = $JsonContent | ConvertFrom-Json
$Match = $Data | Where-Object { $_.Id -eq $Id }
return $Match
}
catch {
Write-PackagerLog -Message "Error parsing CustomApps.json: $_" -Severity Error
return $null
}
}

return $null
}
123 changes: 123 additions & 0 deletions Public/Get-GitHubInstaller.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
function Get-GitHubInstaller {
[CmdletBinding()]
param (
[Parameter(Mandatory=$true)]
[string]$Id,
[string]$DownloadPath = "$env:TEMP\AppPackager"
)

Write-PackagerLog -Message "Querying GitHub Manifests for: $Id"

try {
# 1. Detect Architecture
if ($env:PROCESSOR_ARCHITECTURE -eq "ARM64") { $SysArch = "arm64" }
elseif ([Environment]::Is64BitOperatingSystem) { $SysArch = "x64" }
else { $SysArch = "x86" }

# 2. Construct API Path
$IdPath = $Id.Replace(".", "/")
$FirstChar = $Id.Substring(0,1).ToLower()
$BaseApi = "https://api.github.com/repos/microsoft/winget-pkgs/contents/manifests/$FirstChar/$IdPath"

# 3. Get Version (Latest)
$VersionsResponse = Invoke-RestMethod -Uri $BaseApi -Method Get -ErrorAction Stop
$LatestVersionObj = $VersionsResponse |
Where-Object { $_.type -eq "dir" } |
Select-Object *, @{N='ParsedVersion'; E={ try { [Version]$_.name } catch { $null } }} |
Where-Object { $_.ParsedVersion -ne $null } |
Sort-Object ParsedVersion -Descending |
Select-Object -First 1

if (-not $LatestVersionObj) { throw "Could not determine a valid numeric version." }
$LatestVersion = $LatestVersionObj.Name

# 4. Get Manifest
$VersionPath = "$BaseApi/$LatestVersion"
$VersionFiles = Invoke-RestMethod -Uri $VersionPath -Method Get
$InstallerFile = $VersionFiles | Where-Object { $_.name -like "*.installer.yaml" } | Select-Object -First 1
if (-not $InstallerFile) { throw "No installer YAML found." }

$YamlContent = Invoke-RestMethod -Uri $InstallerFile.download_url

# --- PARSING LOGIC ---
# We split by "- Architecture" to separate blocks, but keep the delimiter to help identification
$Blocks = $YamlContent -split '(?=-\s*Architecture:)'

$SelectedUrl = $null
$SelectedArgs = $null
$SelectedType = "exe"
$SelectedCode = $null

foreach ($Block in $Blocks) {
if ([string]::IsNullOrWhiteSpace($Block)) { continue }

# Extract Architecture from this block
if ($Block -match 'Architecture:\s*([a-zA-Z0-9]+)') {
$BlockArch = $Matches[1].Trim()

# If this block matches our system, scrape it!
if ($BlockArch -eq $SysArch) {
if ($Block -match 'InstallerUrl:\s*["'']?([^"''\r\n]+)["'']?') { $SelectedUrl = $Matches[1].Trim() }
if ($Block -match 'InstallerType:\s*([a-zA-Z0-9]+)') { $SelectedType = $Matches[1].Trim() }

# Scrape Arguments
if ($Block -match 'Silent:\s*(.+)') { $SelectedArgs = $Matches[1].Trim().Trim("'").Trim('"') }
elseif ($Block -match 'SilentWithProgress:\s*(.+)') { $SelectedArgs = $Matches[1].Trim().Trim("'").Trim('"') }

# Scrape Product Code (Flexible Regex)
# This now matches "{GUID}" OR "SimpleString"
if ($Block -match 'ProductCode:\s*["'']?([^"''\r\n]+)["'']?') {
$SelectedCode = $Matches[1].Trim()
}

# If we found a URL, we stop looking (we prefer the first match for our arch)
if ($SelectedUrl) { break }
}
}
}

# Fallbacks (Global properties if not in block)
if (-not $SelectedUrl) { if ($YamlContent -match 'InstallerUrl:\s*["'']?([^"''\r\n]+)["'']?') { $SelectedUrl = $Matches[1].Trim() } }
if (-not $SelectedArgs) {
if ($YamlContent -match 'Silent:\s*(.+)') { $SelectedArgs = $Matches[1].Trim().Trim("'").Trim('"') }
}
if (-not $SelectedCode) {
if ($YamlContent -match 'ProductCode:\s*["'']?([^"''\r\n]+)["'']?') { $SelectedCode = $Matches[1].Trim() }
}

# Special Override for Dell (Command Update)
if ($Id -eq "Dell.CommandUpdate") { $SelectedArgs = '/s /l="C:\Windows\Temp\DellCommand.log" /v"/qn"' }

# Special Override for 8x8 Work MSI
if ($Id -eq "8x8.Work") { $SelectedArgs = "/qn /norestart" }

# Special Override for Sublime Text 4
if ($Id -eq "SublimeHQ.SublimeText.4") { $SelectedArgs = "/VERYSILENT /NORESTART" }

# --- DOWNLOAD ---
$UriObj = [System.Uri]$SelectedUrl
$RealExtension = [System.IO.Path]::GetExtension($UriObj.LocalPath).ToLower()
if (-not $RealExtension) { $RealExtension = ".$SelectedType" }
$FileName = "$Id-$LatestVersion-$SysArch$RealExtension"

if (Test-Path $DownloadPath) { Remove-Item "$DownloadPath\*" -Recurse -Force -ErrorAction SilentlyContinue }
New-Item -ItemType Directory -Path $DownloadPath -Force | Out-Null
$FullPath = Join-Path $DownloadPath $FileName

Write-PackagerLog -Message "Downloading to $FullPath..."
Invoke-WebRequest -Uri $SelectedUrl -OutFile $FullPath -UseBasicParsing -UserAgent "Mozilla/5.0"

return [PSCustomObject]@{
Name = $Id
InstallerPath = $FullPath
FileName = $FileName
SilentArgs = $SelectedArgs
InstallerType = $SelectedType
ProductCode = $SelectedCode
}
}
catch {
Write-PackagerLog -Message "GitHub Scraping Failed: $_" -Severity Error
throw $_
}
}
Loading