Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Add new subcommand "scoop diag" #5543

Open
wants to merge 11 commits into
base: develop
Choose a base branch
from
2 changes: 1 addition & 1 deletion bin/uninstall.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ param(
. "$PSScriptRoot\..\lib\versions.ps1"
. "$PSScriptRoot\..\lib\manifest.ps1"

if ($global -and !(is_admin)) {
if ($global -and !(Test-IsAdmin)) {
error 'You need admin rights to uninstall globally.'
exit 1
}
Expand Down
5 changes: 5 additions & 0 deletions lib/core.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -253,11 +253,16 @@ function format($str, $hash) {
$executionContext.invokeCommand.expandString($str)
}
function is_admin {
Show-DeprecatedWarning $MyInvocation 'Test-IsAdmin'
$admin = [security.principal.windowsbuiltinrole]::administrator
$id = [security.principal.windowsidentity]::getcurrent()
([security.principal.windowsprincipal]($id)).isinrole($admin)
}

function Test-IsAdmin {
return ([System.Security.Principal.WindowsPrincipal] [System.Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator)
}

# messages
function abort($msg, [int] $exit_code=1) { write-host $msg -f red; exit $exit_code }
function error($msg) { write-host "ERROR $msg" -f darkred }
Expand Down
197 changes: 185 additions & 12 deletions lib/diagnostic.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ Diagnostic tests.
Return $true if the test passed, otherwise $false.
Use 'warn' to highlight the issue, and follow up with the recommended actions to rectify.
#>
function check_windows_defender($global) {
function Invoke-WindowsDefenderCheck($global) {
$defender = Get-Service -Name WinDefend -ErrorAction SilentlyContinue
if (Test-CommandAvailable Get-MpPreference) {
if ((Get-MpPreference).DisableRealtimeMonitoring) { return $true }
Expand All @@ -26,8 +26,12 @@ function check_windows_defender($global) {
return $true
}

function check_main_bucket {
if ((Get-LocalBucket) -notcontains 'main') {
function Test-MainBucketAvailable {
return ((Get-LocalBucket) -contains 'main')
}

function Invoke-MainBucketCheck {
if (!(Test-MainBucketAvailable)) {
warn 'Main bucket is not added.'
Write-Host " run 'scoop bucket add main'"

Expand All @@ -37,13 +41,25 @@ function check_main_bucket {
return $true
}

function check_long_paths {
if ([System.Environment]::OSVersion.Version.Major -lt 10 -or [System.Environment]::OSVersion.Version.Build -lt 1607) {
function Test-WindowsLongPathsSupported {
return !([System.Environment]::OSVersion.Version.Major -lt 10 -or [System.Environment]::OSVersion.Version.Build -lt 1607)
}

function Test-WindowsLongPathsEnabled {
return ((Get-ItemProperty `
-Path 'HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem' `
-Name 'LongPathsEnabled' `
-ErrorAction SilentlyContinue
).LongPathsEnabled -eq 1)
}

function Invoke-LongPathsCheck {
if (!(Test-WindowsLongPathsSupported)) {
warn 'This version of Windows does not support configuration of LongPaths.'
return $false
}
$key = Get-ItemProperty 'HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem' -ErrorAction SilentlyContinue -Name 'LongPathsEnabled'
if (!$key -or ($key.LongPathsEnabled -eq 0)) {

if (!(Test-WindowsLongPathsEnabled)) {
warn 'LongPaths support is not enabled.'
Write-Host " You can enable it by running:"
Write-Host " sudo Set-ItemProperty 'HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem' -Name 'LongPathsEnabled' -Value 1"
Expand All @@ -54,11 +70,15 @@ function check_long_paths {
return $true
}

function Get-WindowsDeveloperModeStatus {
$DevModRegistryPath = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\AppModelUnlock"
if (!(Test-Path -Path $DevModRegistryPath) -or (Get-ItemProperty -Path `
$DevModRegistryPath -Name AllowDevelopmentWithoutDevLicense -ErrorAction `
SilentlyContinue).AllowDevelopmentWithoutDevLicense -ne 1) {
function Test-WindowsDeveloperModeEnabled {
return ((Get-ItemProperty `
-Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\AppModelUnlock' `
-Name 'AllowDevelopmentWithoutDevLicense' `
-ErrorAction SilentlyContinue).AllowDevelopmentWithoutDevLicense -eq 1)
}

function Invoke-WindowsDeveloperModeCheck {
if (!(Test-WindowsDeveloperModeEnabled)) {
warn "Windows Developer Mode is not enabled. Operations relevant to symlinks may fail without proper rights."
Write-Host " You may read more about the symlinks support here:"
Write-Host " https://blogs.windows.com/windowsdeveloper/2016/12/02/symlinks-windows-10/"
Expand All @@ -67,3 +87,156 @@ function Get-WindowsDeveloperModeStatus {

return $true
}

function Show-Value {
[CmdletBinding()]
[OutputType([String])]
param(
[Parameter(Mandatory = $true, Position = 0)]
[ValidateNotNullOrEmpty()]
[String]
$Name,
[String]
$Value,
[Switch]
$Redacted,
[Switch]
$Color,
[Int]
$PadRight = 12
)

if ([String]::IsNullOrEmpty($Value)) {
return
}

$Red = "`e[31m"
$Green = "`e[32m"
$Yellow = "`e[33m"
$Cyan = "`e[36m"
$End = "`e[0m"
if (!$Color) {
$Red, $Green, $Yellow, $Cyan, $End = '', '', '', '', ''
}

if ($Redacted) {
$Value = "$Red<redacted>$End"
}

$Value = "$Value".Replace($env:USERPROFILE, "$Green`$env:USERPROFILE$End")
$Value = "$Value".Replace($env:USERNAME, "$Green<username>$End")

$Name = $Name.PadRight($PadRight, ' ')

if ($Value -eq $True) {
$Value = "$Green$Value$End"
} elseif ($Value -eq $False) {
$Value = "$Yellow$Value$End"
}
Write-Output "$Cyan$Name$End = $Value"
}

function Show-Header {
[CmdletBinding()]
[OutputType([String])]
param(
[Parameter(Mandatory = $true, Position = 0)]
[ValidateNotNullOrEmpty()]
[String]
$Value,
[Switch]
$Color
)

if ($Color) {
Write-Output "`e[35m[$Value]`e[0m"
} else {
Write-Output "[$Value]"
}
}

function Get-ParentProcess {
$parent = [System.Diagnostics.Process]::GetCurrentProcess()
while ($parent.MainModule.ModuleName -ieq 'pwsh.exe' -or $parent.MainModule.ModuleName -ieq 'powershell.exe') {
$parent = $parent.Parent
}
return $parent.MainModule.ModuleName
}

function Show-Diag {
[CmdletBinding()]
[OutputType([String])]
param(
[Switch]
$Markdown,
[Switch]
$Color
)

$redactedConfigValues = @(
'virustotal_api_key'
'private_hosts'
'gh_token'
'proxy'
'analytics_id'
'alias'
)

if ($Markdown) {
Write-Output "`n"
Write-Output '```ini'
}

Show-Header -Color:$Color -Value 'PowerShell'
Show-Value -Color:$Color -Name 'Path' -Value ([System.Diagnostics.Process]::GetCurrentProcess().MainModule.FileName)
Show-Value -Color:$Color -Name 'Version' -Value $PSversionTable.PSVersion.ToString()
Show-Value -Color:$Color -Name 'Edition' -Value $PSversionTable.PSEdition
Show-Value -Color:$Color -Name 'Architecture' -Value (Get-DefaultArchitecture)
Show-Value -Color:$Color -Name 'RunAsAdmin' -Value (Test-IsAdmin)
Show-Value -Color:$Color -Name 'Parent' -Value (Get-ParentProcess)

Show-Header -Color:$Color -Value 'Helpers'
Show-Value -Color:$Color -Name 'GitPath' -Value (Get-HelperPath -Helper Git)
Show-Value -Color:$Color -Name 'GitVersion' -Value (Invoke-Git -Path $PSScriptRoot -ArgumentList 'version')
Show-Value -Color:$Color -Name 'Zip' -Value (Test-HelperInstalled -Helper '7zip')
Show-Value -Color:$Color -Name 'Lessmsi' -Value (Test-HelperInstalled -Helper 'Lessmsi')
Show-Value -Color:$Color -Name 'Innounp' -Value (Test-HelperInstalled -Helper 'Innounp')
Show-Value -Color:$Color -Name 'Dark' -Value (Test-HelperInstalled -Helper 'Dark')
Show-Value -Color:$Color -Name 'Aria2' -Value (Test-HelperInstalled -Helper 'Aria2')
Show-Value -Color:$Color -Name 'Zstd' -Value (Test-HelperInstalled -Helper 'Zstd')

Show-Header -Color:$Color -Value 'Environment'
Show-Value -Color:$Color -Name 'SCOOP' -Value $env:SCOOP
Show-Value -Color:$Color -Name 'SCOOP_GLOBAL' -Value $env:SCOOP_GLOBAL
Show-Value -Color:$Color -Name 'SCOOP_CACHE' -Value $env:SCOOP_CACHE
Show-Value -Color:$Color -Name 'HTTPS_PROXY' -Value $env:HTTPS_PROXY -Redacted
Show-Value -Color:$Color -Name 'HTTP_PROXY' -Value $env:HTTP_PROXY -Redacted

Show-Header -Color:$Color -Value 'Scoop'
Show-Value -Color:$Color -Name 'Outdated' -Value (is_scoop_outdated)
Show-Value -Color:$Color -Name 'OnHold' -Value (Test-ScoopCoreOnHold)
Show-Value -Color:$Color -Name 'Config' -Value $configFile
Show-Value -Color:$Color -Name 'CoreRoot' -Value $coreRoot
Show-Value -Color:$Color -Name 'ScoopDir' -Value $scoopdir
Show-Value -Color:$Color -Name 'CacheDir' -Value $cachedir
Show-Value -Color:$Color -Name 'GlobalDir' -Value $globaldir

Show-Header -Color:$Color -Value 'Config'
$pad = ($scoopConfig.PSObject.Properties.Name | Measure-Object -Maximum -Property Length).Maximum
$scoopConfig.PSObject.Properties | ForEach-Object {
Show-Value -Color:$Color -Name $_.Name -Value $_.Value -PadRight $pad -Redacted:($redactedConfigValues.Contains($_.Name))
}

Show-Header -Color:$Color -Value 'Windows'
$pad = 16
Show-Value -Color:$Color -Name 'DeveloperMode' -PadRight $pad -Value (Test-WindowsDeveloperModeEnabled)
Show-Value -Color:$Color -Name 'LongPathsEnabled' -PadRight $pad -Value (Test-WindowsLongPathsEnabled)
Show-Value -Color:$Color -Name 'ScoopDirFormat' -PadRight $pad -Value ((New-Object System.IO.DriveInfo($scoopdir)).DriveFormat)
Show-Value -Color:$Color -Name 'GlobalDirFormat' -PadRight $pad -Value ((New-Object System.IO.DriveInfo($globaldir)).DriveFormat)
Show-Value -Color:$Color -Name 'WindowsDefender' -PadRight $pad -Value ((Get-Service -Name WinDefend -ErrorAction SilentlyContinue).Status)

if ($Markdown) {
Write-Output '```'
Write-Output "`n"
}
}
2 changes: 1 addition & 1 deletion lib/install.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -1205,7 +1205,7 @@ function unlink_persist_data($manifest, $dir) {

# check whether write permission for Users usergroup is set to global persist dir, if not then set
function persist_permission($manifest, $global) {
if($global -and $manifest.persist -and (is_admin)) {
if($global -and $manifest.persist -and (Test-IsAdmin)) {
$path = persistdir $null $global
$user = New-Object System.Security.Principal.SecurityIdentifier 'S-1-5-32-545'
$target_rule = New-Object System.Security.AccessControl.FileSystemAccessRule($user, 'Write', 'ObjectInherit', 'none', 'Allow')
Expand Down
13 changes: 6 additions & 7 deletions libexec/scoop-checkup.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,15 @@
$issues = 0
$defenderIssues = 0

$adminPrivileges = ([System.Security.Principal.WindowsPrincipal] [System.Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator)

if ($adminPrivileges -and $env:USERNAME -ne 'WDAGUtilityAccount') {
$defenderIssues += !(check_windows_defender $false)
$defenderIssues += !(check_windows_defender $true)
if (Test-IsAdmin -and $env:USERNAME -ne 'WDAGUtilityAccount') {
$defenderIssues += !(Invoke-WindowsDefenderCheck $false)
$defenderIssues += !(Invoke-WindowsDefenderCheck $true)
}

$issues += !(check_main_bucket)
$issues += !(check_long_paths)
$issues += !(Get-WindowsDeveloperModeStatus)
$issues += !(Invoke-MainBucketCheck)
$issues += !(Invoke-LongPathsCheck)
$issues += !(Invoke-WindowsDeveloperModeCheck)

if (!(Test-HelperInstalled -Helper 7zip)) {
warn "'7-Zip' is not installed! It's required for unpacking most programs. Please Run 'scoop install 7zip' or 'scoop install 7zip-zstd'."
Expand Down
2 changes: 1 addition & 1 deletion libexec/scoop-cleanup.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ $all = $opt.a -or $opt.all

if (!$apps -and !$all) { 'ERROR: <app> missing'; my_usage; exit 1 }

if ($global -and !(is_admin)) {
if ($global -and !(Test-IsAdmin)) {
'ERROR: you need admin rights to cleanup global apps'; exit 1
}

Expand Down
8 changes: 8 additions & 0 deletions libexec/scoop-diag.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Usage: scoop diag
# Summary: Returns information about the Scoop environment that can be posted on a GitHub issue

. "$PSScriptRoot\..\lib\diagnostic.ps1"

Show-Diag -Markdown -Color

exit 0
2 changes: 1 addition & 1 deletion libexec/scoop-hold.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ if (!$apps) {
exit 1
}

if ($global -and !(is_admin)) {
if ($global -and !(Test-IsAdmin)) {
error 'You need admin rights to hold a global app.'
exit 1
}
Expand Down
2 changes: 1 addition & 1 deletion libexec/scoop-install.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ try {

if (!$apps) { error '<app> missing'; my_usage; exit 1 }

if ($global -and !(is_admin)) {
if ($global -and !(Test-IsAdmin)) {
abort 'ERROR: you need admin rights to install global apps'
}

Expand Down
2 changes: 1 addition & 1 deletion libexec/scoop-reset.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ $apps | ForEach-Object {
return
}

if($global -and !(is_admin)) {
if($global -and !(Test-IsAdmin)) {
warn "'$app' ($version) is a global app. You need admin rights to reset it. Skipping."
return
}
Expand Down
2 changes: 1 addition & 1 deletion libexec/scoop-unhold.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ if (!$apps) {
exit 1
}

if ($global -and !(is_admin)) {
if ($global -and !(Test-IsAdmin)) {
error 'You need admin rights to unhold a global app.'
exit 1
}
Expand Down
2 changes: 1 addition & 1 deletion libexec/scoop-uninstall.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ if (!$apps) {
exit 1
}

if ($global -and !(is_admin)) {
if ($global -and !(Test-IsAdmin)) {
error 'You need admin rights to uninstall global apps.'
exit 1
}
Expand Down
2 changes: 1 addition & 1 deletion libexec/scoop-update.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,7 @@ if (-not ($apps -or $all)) {
set_config LAST_UPDATE ([System.DateTime]::Now.ToString('o')) | Out-Null
success 'Scoop was updated successfully!'
} else {
if ($global -and !(is_admin)) {
if ($global -and !(Test-IsAdmin)) {
'ERROR: You need admin rights to update global apps.'; exit 1
}

Expand Down