mirror of
https://github.com/github/awesome-copilot.git
synced 2026-03-12 12:15:12 +00:00
* feat: add winmd-api-search skill for Windows desktop API discovery Add a skill that helps find and explore Windows desktop APIs (WinRT/WinAppSDK). It searches a local WinMD metadata cache to discover APIs for platform capabilities like camera, file access, notifications, UI controls, AI/ML, sensors, and networking. Includes bundled scripts: - Update-WinMdCache.ps1: generates the JSON cache from SDK and NuGet packages - Invoke-WinMdQuery.ps1: searches types, members, enums, and namespaces - cache-generator: .NET tool that parses WinMD files into JSON Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * feat: sync winmd-api-search with latest upstream changes Updates from PowerToys source branch: - Detect installed WinAppSDK runtime via Get-AppxPackage - Respect NUGET_PACKAGES env var for global packages path - Use OS architecture for runtime package detection - Fix method/event visibility to use MemberAccessMask equality - Fix EnumerationOptions, TypeSpecification decoding, search sort - Robust scan with case-insensitive dedup and multi-path search - Deduplicate packages by (Id, Version) - Fix assets.json selection and pin SRM version - Fix SDK version sorting and global namespace handling Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: remove en-us locale from Microsoft Learn URLs Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * feat: filter assets.json by package type; unique scan-mode manifests - Filter assets.json libraries by type==package to skip project references - Append short path hash to manifest names in scan mode to avoid collisions - Support prefix match in query script for scan-mode manifest names Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
209 lines
7.4 KiB
PowerShell
209 lines
7.4 KiB
PowerShell
<#
|
|
.SYNOPSIS
|
|
Generate or refresh the WinMD cache for the Agent Skill.
|
|
|
|
.DESCRIPTION
|
|
Builds and runs the standalone cache generator to export cached JSON files
|
|
from all WinMD metadata found in project NuGet packages and Windows SDK.
|
|
|
|
The cache is per-package+version: if two projects reference the same
|
|
package at the same version, the WinMD data is parsed once and shared.
|
|
|
|
Supports single project or recursive scan of an entire repo.
|
|
|
|
.PARAMETER ProjectDir
|
|
Path to a project directory (contains .csproj/.vcxproj), or a project file itself.
|
|
Defaults to scanning the workspace root.
|
|
|
|
.PARAMETER Scan
|
|
Recursively discover all .csproj/.vcxproj files under ProjectDir.
|
|
|
|
.PARAMETER OutputDir
|
|
Path to the cache output directory. Defaults to "Generated Files\winmd-cache".
|
|
|
|
.EXAMPLE
|
|
.\Update-WinMdCache.ps1
|
|
.\Update-WinMdCache.ps1 -ProjectDir BlankWinUI
|
|
.\Update-WinMdCache.ps1 -Scan -ProjectDir .
|
|
.\Update-WinMdCache.ps1 -ProjectDir "src\MyApp\MyApp.csproj"
|
|
#>
|
|
[CmdletBinding()]
|
|
param(
|
|
[string]$ProjectDir,
|
|
[switch]$Scan,
|
|
[string]$OutputDir = 'Generated Files\winmd-cache'
|
|
)
|
|
|
|
$ErrorActionPreference = 'Stop'
|
|
|
|
# Convention: skill lives at .github/skills/winmd-api-search/scripts/
|
|
# so workspace root is 4 levels up from $PSScriptRoot.
|
|
$root = (Resolve-Path (Join-Path $PSScriptRoot '..\..\..\..')).Path
|
|
$generatorProj = Join-Path (Join-Path $PSScriptRoot 'cache-generator') 'CacheGenerator.csproj'
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# WinAppSDK version detection -- look only at the repo root folder (no recursion)
|
|
# ---------------------------------------------------------------------------
|
|
|
|
function Get-WinAppSdkVersionFromDirectoryPackagesProps {
|
|
<#
|
|
.SYNOPSIS
|
|
Extract Microsoft.WindowsAppSDK version from a Directory.Packages.props
|
|
(Central Package Management) at the repo root.
|
|
#>
|
|
param([string]$RepoRoot)
|
|
$propsFile = Join-Path $RepoRoot 'Directory.Packages.props'
|
|
if (-not (Test-Path $propsFile)) { return $null }
|
|
try {
|
|
[xml]$xml = Get-Content $propsFile -Raw
|
|
$node = $xml.SelectNodes('//PackageVersion') |
|
|
Where-Object { $_.Include -eq 'Microsoft.WindowsAppSDK' } |
|
|
Select-Object -First 1
|
|
if ($node) { return $node.Version }
|
|
} catch {
|
|
Write-Verbose "Could not parse $propsFile : $_"
|
|
}
|
|
return $null
|
|
}
|
|
|
|
function Get-WinAppSdkVersionFromPackagesConfig {
|
|
<#
|
|
.SYNOPSIS
|
|
Extract Microsoft.WindowsAppSDK version from a packages.config at the repo root.
|
|
#>
|
|
param([string]$RepoRoot)
|
|
$configFile = Join-Path $RepoRoot 'packages.config'
|
|
if (-not (Test-Path $configFile)) { return $null }
|
|
try {
|
|
[xml]$xml = Get-Content $configFile -Raw
|
|
$node = $xml.SelectNodes('//package') |
|
|
Where-Object { $_.id -eq 'Microsoft.WindowsAppSDK' } |
|
|
Select-Object -First 1
|
|
if ($node) { return $node.version }
|
|
} catch {
|
|
Write-Verbose "Could not parse $configFile : $_"
|
|
}
|
|
return $null
|
|
}
|
|
|
|
# Try Directory.Packages.props first (CPM), then packages.config
|
|
$winAppSdkVersion = Get-WinAppSdkVersionFromDirectoryPackagesProps -RepoRoot $root
|
|
if (-not $winAppSdkVersion) {
|
|
$winAppSdkVersion = Get-WinAppSdkVersionFromPackagesConfig -RepoRoot $root
|
|
}
|
|
if ($winAppSdkVersion) {
|
|
Write-Host "Detected WinAppSDK version from repo: $winAppSdkVersion" -ForegroundColor Cyan
|
|
} else {
|
|
Write-Host "No WinAppSDK version found at repo root; will use latest (Version=*)" -ForegroundColor Yellow
|
|
}
|
|
|
|
# Default: if no ProjectDir, scan the workspace root
|
|
if (-not $ProjectDir) {
|
|
$ProjectDir = $root
|
|
$Scan = $true
|
|
}
|
|
|
|
Push-Location $root
|
|
|
|
try {
|
|
# Detect installed .NET SDK -- require >= 8.0, prefer stable over preview
|
|
$dotnetSdks = dotnet --list-sdks 2>$null
|
|
$bestMajor = $dotnetSdks |
|
|
Where-Object { $_ -notmatch 'preview|rc|alpha|beta' } |
|
|
ForEach-Object { if ($_ -match '^(\d+)\.') { [int]$Matches[1] } } |
|
|
Where-Object { $_ -ge 8 } |
|
|
Sort-Object -Descending |
|
|
Select-Object -First 1
|
|
|
|
# Fall back to preview SDKs if no stable SDK found
|
|
if (-not $bestMajor) {
|
|
$bestMajor = $dotnetSdks |
|
|
ForEach-Object { if ($_ -match '^(\d+)\.') { [int]$Matches[1] } } |
|
|
Where-Object { $_ -ge 8 } |
|
|
Sort-Object -Descending |
|
|
Select-Object -First 1
|
|
}
|
|
|
|
if (-not $bestMajor) {
|
|
Write-Error "No .NET SDK >= 8.0 found. Install from https://dotnet.microsoft.com/download"
|
|
exit 1
|
|
}
|
|
|
|
$targetFramework = "net$bestMajor.0"
|
|
Write-Host "Using .NET SDK: $targetFramework" -ForegroundColor Cyan
|
|
|
|
# Build MSBuild properties -- pass detected WinAppSDK version when available
|
|
$sdkVersionProp = ''
|
|
if ($winAppSdkVersion) {
|
|
$sdkVersionProp = "-p:WinAppSdkVersion=$winAppSdkVersion"
|
|
}
|
|
|
|
Write-Host "Building cache generator..." -ForegroundColor Cyan
|
|
$restoreArgs = @($generatorProj, "-p:TargetFramework=$targetFramework", '--nologo', '-v', 'q')
|
|
if ($sdkVersionProp) { $restoreArgs += $sdkVersionProp }
|
|
dotnet restore @restoreArgs
|
|
if ($LASTEXITCODE -ne 0) {
|
|
Write-Error "Restore failed"
|
|
exit 1
|
|
}
|
|
$buildArgs = @($generatorProj, '-c', 'Release', '--nologo', '-v', 'q', "-p:TargetFramework=$targetFramework", '--no-restore')
|
|
if ($sdkVersionProp) { $buildArgs += $sdkVersionProp }
|
|
dotnet build @buildArgs
|
|
if ($LASTEXITCODE -ne 0) {
|
|
Write-Error "Build failed"
|
|
exit 1
|
|
}
|
|
|
|
# Run the built executable directly (avoids dotnet run target framework mismatch issues)
|
|
$generatorDir = Join-Path $PSScriptRoot 'cache-generator'
|
|
$exePath = Join-Path $generatorDir "bin\Release\$targetFramework\CacheGenerator.exe"
|
|
if (-not (Test-Path $exePath)) {
|
|
# Fallback: try dll with dotnet
|
|
$dllPath = Join-Path $generatorDir "bin\Release\$targetFramework\CacheGenerator.dll"
|
|
if (Test-Path $dllPath) {
|
|
$exePath = $null
|
|
} else {
|
|
Write-Error "Built executable not found at: $exePath"
|
|
exit 1
|
|
}
|
|
}
|
|
|
|
$runArgs = @()
|
|
if ($Scan) {
|
|
$runArgs += '--scan'
|
|
}
|
|
|
|
# Detect installed WinAppSDK runtime via Get-AppxPackage (the WindowsApps
|
|
# folder is ACL-restricted so C# cannot enumerate it directly).
|
|
# WinMD files are architecture-independent metadata, so pick whichever arch
|
|
# matches the current OS to ensure the package is present.
|
|
$osArch = [System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture.ToString()
|
|
$runtimePkg = Get-AppxPackage -Name 'Microsoft.WindowsAppRuntime.*' -ErrorAction SilentlyContinue |
|
|
Where-Object { $_.Name -notmatch 'CBS' -and $_.Architecture -eq $osArch } |
|
|
Sort-Object -Property Version -Descending |
|
|
Select-Object -First 1
|
|
if ($runtimePkg -and $runtimePkg.InstallLocation -and (Test-Path $runtimePkg.InstallLocation)) {
|
|
Write-Host "Detected WinAppSDK runtime: $($runtimePkg.Name) v$($runtimePkg.Version)" -ForegroundColor Cyan
|
|
$runArgs += '--winappsdk-runtime'
|
|
$runArgs += $runtimePkg.InstallLocation
|
|
}
|
|
|
|
$runArgs += $ProjectDir
|
|
$runArgs += $OutputDir
|
|
|
|
Write-Host "Exporting WinMD cache..." -ForegroundColor Cyan
|
|
if ($exePath) {
|
|
& $exePath @runArgs
|
|
} else {
|
|
dotnet $dllPath @runArgs
|
|
}
|
|
if ($LASTEXITCODE -ne 0) {
|
|
Write-Error "Cache export failed"
|
|
exit 1
|
|
}
|
|
|
|
Write-Host "Cache updated at: $OutputDir" -ForegroundColor Green
|
|
} finally {
|
|
Pop-Location
|
|
}
|