-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Winget acting strange after moving package cache and temp to Dev-Drive #4616
Comments
This comment was marked as off-topic.
This comment was marked as off-topic.
What steps did you take to move the cache and temporary directories to a Dev Drive? |
I don't think this has anything to do with the Dev Drive, but instead it just happened to coincide with an update to winget. The packages with ARP\ or MSIX\ prefixes are the ones for which winget did not find a matching package in the source and we just list what is installed on the machine. You should be able to uninstall it with winget using that ID (use |
@denelon Thanks for getting back to me. I followed what's documented here by MS. I did end up making a PowerShell script that will automate the creation of the folder on the Dev Drive (if it doesn't exist), then checks if the folder exists locally and checks if there's anything in it, if there is, then it will copy the content to the new folder on the Dev Drive, then checks if the environmental variables already exists and sets up the environmental variables in 'the
@florelis Thanks for the response. Yeah, I thought this too, but I did try to clean install a few times. It just so happens to coincide that every time you move the package cache and the temp directories, it starts to exhibit this behavior. However, it's hard to say, because it seems that
@florelis Great. That's at least still somewhat helpful. Thank you. Good to know. |
@peterlobster that would be helpful. If I can reproduce what's happening, maybe we can figure out a fix or a temporary work around. |
@denelon Ok. My colleague @ran-dall, who is the other main author, told me to mention these are very experimental but so far, they've been working for us. FWIW we do plan on open sourcing the scripts once we've tested everything, as we find them useful. So, we have two main scripts we're working with,
Script# Function to check if a drive is a Dev Drive
function Get-DevDrive {
$devDrives = Get-Volume | Where-Object { $_.FileSystemType -eq 'ReFS' -and $_.DriveType -eq 'Fixed' }
$devDriveLetters = @()
foreach ($drive in $devDrives) {
$driveLetter = "$($drive.DriveLetter):"
Write-Host "`nDev Drive found: $driveLetter"
$devDriveLetters += $driveLetter
}
if ($devDriveLetters.Count -eq 0) {
Write-Output "No Dev Drive found on the system."
return $null
} elseif ($devDriveLetters.Count -eq 1) {
return $devDriveLetters[0]
} else {
Write-Host "Multiple Dev Drives found:"
for ($i = 0; $i -lt $devDriveLetters.Count; $i++) {
Write-Host "[$i] $($devDriveLetters[$i])"
}
$selection = Read-Host "Please select the drive you want to configure by entering the corresponding number"
if ($selection -match '^\d+$' -and [int]$selection -lt $devDriveLetters.Count) {
return $devDriveLetters[$selection]
} else {
Write-Output "Invalid selection. Exiting script."
return $null
}
}
}
# Function to test if a Dev Drive is trusted
function Test-DevDriveTrusted {
param (
[string]$DriveLetter
)
$result = fsutil devdrv query $DriveLetter | Out-String
return $result -match "This is a trusted developer volume"
}
# Function to get allowed filters on a Dev Drive
function Get-DevDriveAllowedFilters {
param (
[string]$DriveLetter
)
$result = fsutil devdrv query $DriveLetter | Out-String
if ($result -match "Filters allowed on this developer volume:\s*(.*)") {
$allowedFiltersLine = $matches[1]
$allowedFiltersLine = $allowedFiltersLine.Trim()
return $allowedFiltersLine -split ",\s*"
}
return @()
}
# Function to add filters to a Dev Drive
function Add-DevDriveFilters {
param (
[string]$DriveLetter,
[string[]]$Filters
)
$allowedFilters = Get-DevDriveAllowedFilters -DriveLetter $DriveLetter
$filtersToAdd = $Filters | Where-Object { $allowedFilters -notcontains $_ }
if ($filtersToAdd.Count -gt 0) {
$filterString = $filtersToAdd -join ","
try {
fsutil devdrv setfiltersallowed /f /volume $DriveLetter $filterString > $null
Write-Output "Filters added to $DriveLetter $filterString"
} catch {
Write-Error "Failed to add filters to $DriveLetter $_"
}
} else {
Write-Output "All specified filters are already allowed on $DriveLetter."
}
}
# Function to prompt the user to add filters
function PromptForFilters {
param (
[string]$DriveLetter
)
$filters = @()
Write-Host "Default filters: WdFilter, PrjFlt, bindFlt, wcifs, FileInfo, ProcMon24, WinSetupMon"
$defaultResponse = Read-Host "Would you like to use the default filters? (Y/N)"
if ($defaultResponse -eq 'Y') {
$filters += "WdFilter", "PrjFlt", "bindFlt", "wcifs", "FileInfo", "ProcMon24", "WinSetupMon"
} else {
$filterOptions = @(
@{ Name = "PrjFlt"; Description = "GVFS: Sparse enlistments of Windows" },
@{ Name = "MsSecFlt"; Description = "MSSense: Microsoft Defender for Endpoint for EDR Sensor" },
@{ Name = "WdFilter"; Description = "Defender: Windows Defender Filter" },
@{ Name = "bindFlt, wcifs"; Description = "Docker: Running containers out of Dev Drive" },
@{ Name = "FileInfo"; Description = "Windows Performance Recorder: Measure file system operations & Resource Monitor: Shows resource usage. Required to show file names in Disk Activity" },
@{ Name = "ProcMon24"; Description = "Process Monitor - Sysinternals: Monitor file system activities [EXPERIMENTAL]" },
@{ Name = "WinSetupMon"; Description = "Windows Upgrade: Used during OS Upgrade. Required if user moves TEMP environment variable to Dev Drive" }
)
foreach ($option in $filterOptions) {
$response = Read-Host "Do you want to add the filter $($option.Name) - $($option.Description)? (Y/N)"
if ($response -eq 'Y') {
$filters += $option.Name -split ',\s*'
}
}
}
Add-DevDriveFilters -DriveLetter $DriveLetter -Filters $filters
}
# Function to check if the Anti-Virus filter is enabled and give the option to change it
function ManageAntiVirusFilter {
param (
[string]$DriveLetter
)
$result = fsutil devdrv query $DriveLetter | Out-String
$avEnabled = $result -match "Developer volumes are protected by antivirus filter"
if ($avEnabled) {
Write-Host "Developer volumes are currently protected by antivirus filter."
$response = Read-Host "Do you want to disable the antivirus filter? (Y/N)"
if ($response -eq 'Y') {
fsutil devdrv enable /disallowAV > $null
Write-Output "Antivirus filter has been disabled for Dev Drive $DriveLetter."
}
} else {
Write-Host "Developer volumes are not protected by antivirus filter."
$response = Read-Host "Do you want to enable the antivirus filter? (Y/N)"
if ($response -eq 'Y') {
fsutil devdrv enable /allowAV > $null
Write-Output "Antivirus filter has been enabled for Dev Drive $DriveLetter."
}
}
}
# Main Script
$devDrive = Get-DevDrive
if ($null -ne $devDrive) {
$isTrusted = Test-DevDriveTrusted -DriveLetter $devDrive
if (-not $isTrusted) {
$userResponse = Read-Host "`nDev Drive $devDrive is not trusted. Do you want to set it as trusted? (Y/N)"
if ($userResponse -eq 'Y') {
fsutil devdrv trust $devDrive > $null
Write-Output "Dev Drive $devDrive has been set as trusted."
} else {
Write-Output "Dev Drive $devDrive remains untrusted."
exit
}
} else {
Write-Output "`nDev Drive $devDrive is already trusted."
}
ManageAntiVirusFilter -DriveLetter $devDrive
PromptForFilters -DriveLetter $devDrive
} else {
Write-Output "No Dev Drive found to configure."
}
Script# Function to check if a drive is a Dev Drive
function Get-DevDrive {
$devDrives = Get-Volume | Where-Object { $_.FileSystemType -eq 'ReFS' -and $_.DriveType -eq 'Fixed' }
$devDriveLetters = @()
foreach ($drive in $devDrives) {
$driveLetter = "$($drive.DriveLetter):"
Write-Host "`nDev Drive found: $driveLetter"
$devDriveLetters += $driveLetter
}
switch ($devDriveLetters.Count) {
0 {
Write-Output "No Dev Drive found on the system."
return $null
}
1 {
return $devDriveLetters[0]
}
default {
Write-Host "Multiple Dev Drives found:"
for ($i = 0; $i -lt $devDriveLetters.Count; $i++) {
Write-Host "[$i] $($devDriveLetters[$i])"
}
while ($true) {
$selection = Read-Host "Please select the drive you want to configure by entering the corresponding number"
if ($selection -match '^\d+$' -and [int]$selection -lt $devDriveLetters.Count) {
return $devDriveLetters[$selection]
} else {
Write-Host "Invalid selection. Please enter a valid number."
}
}
}
}
}
# Main script to set up the Environment Variables for Package Cache
# Retrieve the Dev Drive
$selectedDrive = Get-DevDrive
if ($selectedDrive) {
Write-Host "Selected Dev Drive: $selectedDrive`n"
} else {
Write-Host "No valid Dev Drive selected. Exiting script."
exit 1
}
# Define the Dev Drive base path
$DevDrive = "$selectedDrive\packages"
# Function to create a directory if it doesn't exist
function New-DirectoryIfNotExists {
param (
[string]$Path
)
if (-not (Test-Path -Path $Path)) {
New-Item -Path $Path -ItemType Directory -Force
Write-Output "Created directory: $Path"
} else {
Write-Output "Directory already exists: $Path"
}
}
# Function to set a user environment variable with verbose output
function Set-UserEnvironmentVariable {
param (
[string]$Name,
[string]$Value
)
$currentValue = [System.Environment]::GetEnvironmentVariable($Name, [System.EnvironmentVariableTarget]::User)
if ($currentValue -eq $Value) {
Write-Output "Environment variable '$Name' is already set to '$Value'. No further setup is required."
} else {
try {
$output = setx $Name $Value
if ($output -match "SUCCESS: Specified value was saved.") {
Write-Output "SUCCESS: Environment variable '$Name' was set to '$Value'."
} else {
Write-Output "ERROR: Could not set environment variable '$Name'. Message: $output"
}
} catch {
Write-Output "ERROR: Access to the registry path is denied for environment variable '$Name'."
}
}
}
# Function to move contents from one directory to another
function Move-CacheContents {
param (
[string]$SourcePath,
[string]$DestinationPath
)
if (Test-Path -Path $SourcePath) {
Move-Item -Path "$SourcePath\*" -Destination $DestinationPath -Force
Remove-Item -Path $SourcePath -Recurse -Force
Write-Output "Moved contents from '$SourcePath' to '$DestinationPath' and removed the old directory."
} else {
Write-Output "No contents to move from '$SourcePath'."
}
}
# Create necessary directories
$directories = @(
"$DevDrive\npm",
"$DevDrive\$env:USERNAME\.nuget\packages",
"$DevDrive\vcpkg",
"$DevDrive\pip",
"$DevDrive\cargo",
"$DevDrive\maven",
"$DevDrive\gradle"
)
Write-Output "### Directory Setup ###"
foreach ($dir in $directories) {
New-DirectoryIfNotExists -Path $dir
}
Write-Output ""
# Environment variable setup and cache moving
$cacheSettings = @(
@{ Name = "npm_config_cache"; Value = "$DevDrive\npm"; SourcePaths = @("$env:APPDATA\npm-cache", "$env:LOCALAPPDATA\npm-cache") },
@{ Name = "NUGET_PACKAGES"; Value = "$DevDrive\$env:USERNAME\.nuget\packages"; SourcePaths = @("$env:USERPROFILE\.nuget\packages") },
@{ Name = "VCPKG_DEFAULT_BINARY_CACHE"; Value = "$DevDrive\vcpkg"; SourcePaths = @("$env:LOCALAPPDATA\vcpkg\archives", "$env:APPDATA\vcpkg\archives") },
@{ Name = "PIP_CACHE_DIR"; Value = "$DevDrive\pip"; SourcePaths = @("$env:LOCALAPPDATA\pip\Cache") },
@{ Name = "CARGO_HOME"; Value = "$DevDrive\cargo"; SourcePaths = @("$env:USERPROFILE\.cargo") },
@{ Name = "GRADLE_USER_HOME"; Value = "$DevDrive\gradle"; SourcePaths = @("$env:USERPROFILE\.gradle") }
)
foreach ($setting in $cacheSettings) {
Write-Output "### Setting up $($setting.Name) ###"
Set-UserEnvironmentVariable -Name $setting.Name -Value $setting.Value
foreach ($source in $setting.SourcePaths) {
Move-CacheContents -SourcePath $source -DestinationPath $setting.Value
}
Write-Output ""
}
# Additional step to set MAVEN_OPTS and move Maven repository
Write-Output "### Setting up MAVEN_OPTS ###"
$mavenRepoLocal = "$DevDrive\maven"
New-DirectoryIfNotExists -Path $mavenRepoLocal
$mavenOpts = [System.Environment]::GetEnvironmentVariable('MAVEN_OPTS', [System.EnvironmentVariableTarget]::User)
$escapedMavenRepoLocal = [regex]::Escape($mavenRepoLocal)
if ($mavenOpts -notmatch "-Dmaven\.repo\.local=$escapedMavenRepoLocal") {
$newMavenOpts = "-Dmaven.repo.local=$mavenRepoLocal $mavenOpts"
Set-UserEnvironmentVariable -Name "MAVEN_OPTS" -Value $newMavenOpts
Write-Output "Environment variable 'MAVEN_OPTS' set to: $newMavenOpts"
} else {
Write-Output "Environment variable 'MAVEN_OPTS' is already set correctly. No further setup is required."
}
Move-CacheContents -SourcePath "$env:USERPROFILE\.m2\repository" -DestinationPath $mavenRepoLocal
Write-Output ""
# Optional: Move TMP and TEMP to Dev Drive if not already on Dev Drive
Write-Output "### Setting up TMP and TEMP ###"
$currentTemp = [System.Environment]::GetEnvironmentVariable('TEMP', [System.EnvironmentVariableTarget]::User)
$currentTmp = [System.Environment]::GetEnvironmentVariable('TMP', [System.EnvironmentVariableTarget]::User)
if (($currentTemp -notlike "$selectedDrive*") -or ($currentTmp -notlike "$selectedDrive*")) {
$confirmMoveTemp = Read-Host "Do you want to move TMP and TEMP directories to the Dev Drive? (y/n)"
if ($confirmMoveTemp -eq 'y') {
$tempPath = "$selectedDrive\temp"
New-DirectoryIfNotExists -Path $tempPath
Set-UserEnvironmentVariable -Name "TEMP" -Value $tempPath
Set-UserEnvironmentVariable -Name "TMP" -Value $tempPath
Write-Output "Environment variables 'TEMP' and 'TMP' set to: $tempPath"
} else {
Write-Output "Skipping move of TMP and TEMP directories."
}
} else {
Write-Output "TEMP and TMP are already set to the Dev Drive."
}
Write-Output ""
Write-Output "### Setup Complete ###"
Write-Output "Package cache on Dev Drive was set successfully."
(Also, to note, both scripts will try to automatically find the Dev Drive) I should also mention that we also manually add a user with full control over the directories to the Dev Drive. However, beyond that, those are the steps to replicate. |
I noticed something subtle in what was stated about running Windows Update and WinGet being updated on a fresh Windows 11 install. Currently, WinGet is updated via the Microsoft Store independent of what Windows Update is doing. It's likely the version of WinGet on a fresh install is out of date. If it's WinGet 1.6 or newer, WinGet can upgrade itself via the community repository with |
@denelon When I try to run
@denelon This is a clever idea (one I considered before, but wasn't sure if it would have any result), however, also this produced no output on a fresh Windows 11 install. |
@denelon Update: So I tried uninstalling and reinstalling the packages like you suggested, turns out, even if you do reinstall, the same problem exists. |
We made some changes in the client for 1.8 and 1.9-preview to handle packages installed side-by-side. The packages starting with prefixes like "ARP" or "MSIX" are packages that are installed on the device, but not matching with any of WinGet's configured sources. Those packages may be removable using |
@denelon My apologies for not being clearer. So, I uninstalled
(I also just reconfirmed the behavior) Thank you for the tip using `winget repair , however, it doesn't seem to have any notable effect on the issue in this case.
|
I believe this is a case of Spotify having an age rating so it's not available to WinGet via the REST source "msstore". If WinGet was used to install a package via the "msstore" source, then the source would match via There are several related issues:
We're working on the problem of how to handle the additional requirements for offering version information to WinGet for packages in the "msstore" source. There is work to be done by both teams. On the WinGet side, we need to provide additional information to the "msstore" source to help identify which versions of packages are applicable for the device and the user MSA logged into the store, and their REST source would need to be able to offer the specific version that applies in that case. The Microsoft Store shows a "TEEN" rating for Spotify and the "msstore" REST source only offers content rated "E for Everyone" to the WinGet CLI. |
@denelon I've actually had this for a while now. It changed right around when we were testing V2 of the index. I started to notice that packages installed by Winget were all the sudden not being noticed by Winget. I saw some commits where it was recommended to uninstall source, to which I did, but no luck as it comes right back. I haven't made an issue yet because I thought it was my error so I was going to try and fix it first. Any chance these could be related? |
Brief description of your issue
After moving the package cache and temporary directories to a Dev-Drive, winget list displays packages with unusual prefixes such as MSIX/ or ARP/. This behavior did not occur before the change.
Additionally, updating or working these packages with prefixes seems impossible. It only affects the packages that were deployed by default during the Windows 11 installation.
VS Code, for example, was install after the Dev-Drive was setup and seems to work correctly:
However, Intel Graphics Command Center, for example, does update or not work correctly. I believe Intel Graphics Command Center was installed by Windows automatically.
Below is the output on a fresh Win 11 install.
Steps to reproduce
Expected behavior
winget list
should display a list of installed packages without unusual prefixes and should allow for updating these packages.Actual behavior
winget list
shows some packages with prefixes like MSIX/ or ARP/ (something I haven't seen before), and these packages cannot be updated.Environment
The text was updated successfully, but these errors were encountered: