Fixing Windows Setup

This commit is contained in:
Gal Szkolnik 2020-09-29 19:51:48 -04:00
parent a4bdd9c9a5
commit 586f187346
1 changed files with 206 additions and 150 deletions

View File

@ -36,6 +36,144 @@ function ProfileCode_post_common {
# This loads the personal profile section from the $MyPSScriptRoot/profile.d directory
Get-Command Reload-MyScripts -ErrorAction SilentlyContinue | ForEach-Object { . $_.Name }
}
#######################################################################
## Setup-Profile code continues below
#######################################################################
if ( $GitClone -and -not (Test-Path $(Join-Path $MyPSScriptRoot '.git')) ) {
if( -not [bool]$(Get-Command git -ErrorAction SilentlyContinue) ) {
throw "No git command found, you may either omit the -GitClone switch or install git and try again."
}
if( $PSCmdlet.ShouldProcess("Pull git repo from $GitURL into $MyPSScriptRoot ?") ) {
git clone $GitURL $MyPSScriptRoot
}
}
$local:ProfileSignature = [PSCustomObject]([ordered]@{
Begin = '#### SZ Auto Profile Setup - BEGIN ####'
End = '#### SZ Auto Profile Setup - END ####'
})
function New-ProfileSetupStatus{
param($Name,$Path,$Status,$Exist)
return [PSCustomObject]([ordered]@{
Name = $Name
Path = $Path
Status = $Status
Exist = $Exist
})
}
$local:_profiles= $PROFILE | fl * -Force | Out-String -Stream | ForEach-Object {
$local:p = $($_ -split ' : [/A-Z\\]');
if( $p[0] -match 'User' ) {
$p[0].Trim()
}
}
$local:_profile = $profile.CurrentUserAllHosts;
$local:randomSeed = "####$(Get-Random)####";
if( $RemoveOnly -and $ConfirmPreference -eq 'High' -and (-not $PSBoundParameters -or -not $PSBoundParameters.ContainsKey('Confirm')) ) {
$script:ConfirmPreference = 'Low'
}
if( $sudo -or $(Test-IsAdmin) ) { $_profile = $profile.AllUsersAllHosts }
$_profiles | Foreach-Object {
$local:p = Invoke-Expression "`$profile.$_"
$local:profileContent = $randomSeed;
$local:exists = Test-Path $p
$local:userFile = $($_ -match 'CurrentUser')
$local:cleanupValue = ''
if ( $exists -and ((Get-Content -Path $p | Out-String ) -match $ProfileSignature.Begin ) ) {
Write-Verbose "Found code in [$_]'$p', preparing..."
$local:gate = $true;
$profileContent = Get-Content $p | ForEach-Object {
if( -not $gate ) {
if ( $_ -match $ProfileSignature.End ) {
$gate = $true;
}
} else {
if ( $_ -match $ProfileSignature.Begin ) {
$gate = $false;
$cleanupValue = ' '
return $randomSeed;
}
return $_
}
}
}
if( ($p -eq $_profile) -and -not $RemoveOnly ) {
Write-Verbose "Inserting ProfileCode into $($_)..."
$profileContent = $profileContent -replace $randomSeed,$((@(
'',
$ProfileSignature.Begin,
'',
$(Export-FunctionSource -NoHeader ProfileCode_pre_common),
'',
'',
$(Export-FunctionSource -NoHeader ProfileCode_common),
'',
'',
$(Export-FunctionSource -NoHeader ProfileCode_post_common),
'',
$ProfileSignature.End
) -join "`n" ).Trim().Replace(('$'+'_'),('$$'+'_')))
}
$profileContent = $($profileContent -replace $randomSeed,$cleanupValue).Trim()
$local:shouldSudo = $sudo -and -not $userFile
$local:status = 'Skipped'
if( $VerbosePreference -eq 'Continue' ) { $ShowSkipped = $true }
if( -not ([string]::IsNullOrWhiteSpace($profileContent)) ) {
$status = "Need $(if($cleanupValue){'Setup'}else{'Cleanup'})"
if( $sudo -or $userFile ) {
Write-Verbose "Writing content to $($_)..."
$local:tmpOutput = New-TemporaryFile -WhatIf:$false
$profileContent | Out-File $tmpOutput.FullName -WhatIf:$false
if( $shouldSudo -and $( $PSVersionTable.Platform -eq 'Unix' ) ) {
Invoke-ExpressionEx -sudo:$shouldSudo chmod 'a+r' $tmpOutput.FullName
}
try {
function BreakPointHere{} BreakPointHere;
$local:errMsg = $(Invoke-ExpressionEx -sudo:$shouldSudo "Move-Item $($tmpOutput.FullName) $p -Force:`$$Force -ErrorAction Stop | Out-Null" 2>&1)
if( $errMsg ) {
Write-Error "$errMsg"
$status = $status -replace 'Need ','Failed '
} else {
$status = $status -replace 'Need ',''
}
} catch {
Write-Error "Writing $p failed!"
}
} else {
$status = "Need $status"
Write-Error "Cannot write into [$_]'$p'! Please re-run with sudo."
}
} elseif( ($Force -or $RemoveOnly) -and $exists ) {
$status = 'Need Removal'
if( $sudo -or $userFile ) {
Write-Verbose "Removing [$_]'$p'..."
try {
Invoke-ExpressionEx -sudo:$shouldSudo Remove-Item $p
if( -not (Test-Path $p) ) { $status = 'Removed' }
} catch {
Write-Error "Removal of $p failed!"
}
} else {
Write-Error "Cannot remove [$_]'$p'! Please re-run with sudo."
}
}
if( $status -ne 'Skipped' -or $ShowSkipped ) {
if( $shouldSudo -and $status -ne 'Skipped' ) { $status = "$status via sudo" }
New-ProfileSetupStatus -Name $_ -Path $p -Status $status -Exist $(Test-Path $p)
}
}
Remove-Item function:ProfileCode* -Confirm:$false
}
function ProfileCode_common {
function Get-PowerShellPath {
@ -47,36 +185,95 @@ param([string]$String)
return [Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($String))
}
function Invoke-ExpressionEx() {
function Invoke-ExpressionEx {
[CmdletBinding(SupportsShouldProcess)]param(
[switch]$sudo,
[switch]$Force,
[string]$Function,
[switch]$MarshalOutput,
[Parameter(Position = 1, ValueFromRemainingArguments = $true)]
[string[]]$expr
)
function do_sudo {
[CmdletBinding()]param (
[string]$sudo_cmd
)
function do_sudo_win {
[CmdletBinding()]param (
[string]$sudo_cmd
)
$local:sudo_exec = [string]::Empty
if( (Get-Command scoop -ErrorAction SilentlyContinue) ) {
$sudo_exec = $(scoop which gsudo *>&1)
if( $sudo_exec -match 'not found' ) {
$sudo_exec = $(scoop which sudo *>&1)
}
if( $sudo_exec -match 'not found' ) { $sudo_exec = [string]::Empty }
}
if( $sudo_exec ) {
& $sudo_exec $sudo_cmd
} else {
Write-Error "Didn't find a known sudo command"
}
}
if( $PSVersionTable.Platform -eq 'Unix' ) {
/usr/bin/env sudo $(Get-PowerShellPath) "-noprofile" "-EncodedCommand" $(ConvertTo-Base64 $sudo_cmd)
} else {
$local:currentIdenity = [System.Security.Principal.WindowsIdentity]::GetCurrent()
if( $currentIdenity.UserClaims.Value -contains 'S-1-5-32-544' ) {
do_sudo_win $sudo_cmd
} else {
Write-Error "User [$($currentIdenity.Name)]does not have permissions to run as admin."
}
}
}
if( $sudo -and -not $(Test-IsAdmin) ) {
$local:tmpFile = $null
$local:tmpOutputFile = $null
$local:tmpScriptFile = $null
$local:sudo_cmd = "$($expr -join ' ')".Trim()
if( $Function ) {
$tmpFile = New-TemporaryFile -WhatIf:$false
$tmpFile = Move-Item $tmpFile.FullName "$($tmpFile.FullName).ps1" -PassThru -WhatIf:$false
Export-FunctionSource $Function | Out-File $tmpFile.FullName -WhatIf:$false
$expr = @( ".", $tmpFile.FullName, ";", $Function ) + $expr
$tmpScriptFile = New-TemporaryFile -WhatIf:$false -Confirm:$false
$tmpScriptFile = Move-Item $tmpScriptFile.FullName "$($tmpScriptFile.FullName).ps1" -PassThru -WhatIf:$false -Confirm:$false
$local:tmpScriptContent = Export-FunctionSource $Function
$sudo_cmd = "$Function $sudo_cmd"
$tmpScriptContent | Out-File $tmpScriptFile.FullName -WhatIf:$false
$expr = @( ".", $tmpScriptFile.FullName, ";", "`n$Function" ) + $expr
}
$expr = @(
'$WhatIfPreference', '=', "`$$WhatIfPreference", ';',
'$VerbosePreference', '=', "'$VerbosePreference'", ";",
'$ErrorActionPreference', '=', "'$ErrorActionPreference'", ";",
'$ConfirmPreference', '=', "'$ConfirmPreference'", ";"
"`n`$WhatIfPreference=`$$WhatIfPreference;",
"`n`$VerbosePreference='$VerbosePreference';",
"`n`$ErrorActionPreference='$ErrorActionPreference';",
"`n`$ConfirmPreference='$ConfirmPreference';`n"
) + $expr
$local:sudo_params = $expr -join ' '
Write-Verbose "Perofrming the following command line via SUDO:`n{$sudo_params}"
$local:base64command = ConvertTo-Base64 $sudo_params
/usr/bin/env sudo $(Get-PowerShellPath) -EncodedCommand $base64command
if( $tmpFile ) { Remove-Item $tmpFile }
if( $MarshalOutput ) {
$tmpOutputFile = New-TemporaryFile -WhatIf:$false -Confirm:$false
$expr += @( "| Export-CliXml -Path '$($tmpOutputFile.FullName)'" )
}
$expr += @( ";`n exit `$LastExitCode" )
## $tmpScriptContent += "$($expr -join ' ')".Trim()
Write-Verbose "Performing the following command line via SUDO:`n{$sudo_cmd}"
$sudo_cmd = "$($expr -join ' ')".Trim()
do_sudo $sudo_cmd
## do_sudo 'Get-Content' $tmpScriptFile.FullName '|' 'Invoke-Expression' '|' 'Export-Clixml' '-Path' $tmpOutputFile.FullName
#do_sudo $sudo_cmd
if( $tmpScriptFile ) { Remove-Item $tmpScriptFile }
if( $tmpOutputFile ) { Import-Clixml $tmpOutputFile; Remove-Item $tmpOutputFile }
return
}
@ -144,7 +341,11 @@ param([string]$EnvPath)
}
# Establish Module Path
$global:MyPSModulePath = Split-PathEnv $env:PSModulePath | Where-Object { $_ -match "^$($(Resolve-Path ~) -replace '\\',"\\")" }
$global:MyPSModulePath = Split-PathEnv $env:PSModulePath |
Where-Object { $_ -match "^$($(Resolve-Path ~) -replace '\\',"\\")" } |
Where-Object { Test-Path $_ } |
Get-Item | Sort-Object -Property LastWriteTime -Descending |
Select-Object -ExpandProperty FullName -First 1
if( -not $MyPSModulePath ) {
$MyPSModulePath = $(Join-Path $(Join-Path $(Resolve-Path ~) 'powershell') 'Modules')
@ -169,160 +370,15 @@ $global:MyPSScriptRoot = $MyPSScriptRoot
$p = @($p[0], $MyPSScriptRoot) + $($p | Select-Object -Skip 1)
$env:PATH = $p -join $PathEnvDelimiter
}
#######################################################################
## Setup-Profile code continues below
#######################################################################
if ( -not $MyPSScriptRoot -or (Test-Path function:Test-IsAdmin,function:ConvertTo-Base64,function:Invoke-ExpressionEx,function:Get-PowerShellPath,function:Export-FunctionSource | Where-Object { -not $_ } | Measure-Object | Select-Object -ExpandProperty Count) ) {
Write-Verbose "Calling ProfileCode inline..."
. ProfileCode_common
}
if ( $GitClone -and -not (Test-Path $(Join-Path $MyPSScriptRoot '.git')) ) {
if( -not [bool]$(Get-Command git -ErrorAction SilentlyContinue) ) {
throw "No git command found, you may either omit the -GitClone switch or install git and try again."
}
if( $PSCmdlet.ShouldProcess("Pull git repo from $GitURL into $MyPSScriptRoot ?") ) {
git clone $GitURL $MyPSScriptRoot
}
}
# if( $sudo -and -not $(Test-IsAdmin) ) {
# $local:sudo_args = @('-MyPSScriptRoot',$MyPSScriptRoot)
# $ScriptPSBoundParams.Keys | Where-Object {
# ($ScriptPSBoundParams[$_] -is [Switch]) -and $ScriptPSBoundParams[$_] -and ($_ -notin ('sudo','GitClone','GitURL'))
# } | ForEach-Object { $sudo_args += "-$_" }
#
# return Invoke-ExpressionEx -sudo -Function 'Setup-ProfileInternal' $sudo_args
# }
$local:ProfileSignature = [PSCustomObject]([ordered]@{
Begin = '#### SZ Auto Profile Setup - BEGIN ####'
End = '#### SZ Auto Profile Setup - END ####'
})
function New-ProfileSetupStatus{
param($Name,$Path,$Status,$Exist)
return [PSCustomObject]([ordered]@{
Name = $Name
Path = $Path
Status = $Status
Exist = $Exist
})
}
$local:_profiles= $PROFILE | fl * -Force | Out-String -Stream | ForEach-Object {
$local:p = $($_ -split '( : /)|(:\\)');
if( $p[0] -match 'User' ) {
$p[0].Trim()
}
}
$local:_profile = $profile.CurrentUserAllHosts;
$local:randomSeed = "####$(Get-Random)####";
$local:written = $false;
if( $RemoveOnly -and $ConfirmPreference -eq 'High' -and (-not $PSBoundParameters -or -not $PSBoundParameters.ContainsKey('Confirm')) ) {
$script:ConfirmPreference = 'Low'
}
if( $sudo -or $(Test-IsAdmin) ) { $_profile = $profile.AllUsersAllHosts }
$_profiles | Foreach-Object {
$local:p = Invoke-Expression "`$profile.$_"
$local:profileContent = $randomSeed;
$local:exists = Test-Path $p
$local:userFile = $($_ -match 'CurrentUser')
$local:cleanupValue = ''
if ( $exists -and ((Get-Content -Path $p | Out-String ) -match $ProfileSignature.Begin ) ) {
Write-Verbose "Found code in [$_]'$p', preparing..."
$local:gate = $true;
$profileContent = Get-Content $p | ForEach-Object {
if( -not $gate ) {
if ( $_ -match $ProfileSignature.End ) {
$gate = $true;
}
} else {
if ( $_ -match $ProfileSignature.Begin ) {
$gate = $false;
$cleanupValue = ' '
return $randomSeed;
}
return $_
}
}
}
if( ($p -eq $_profile) -and -not $RemoveOnly ) {
Write-Verbose "Inserting ProfileCode into $($_)..."
$profileContent = $profileContent -replace $randomSeed,$((@(
'',
$ProfileSignature.Begin,
'',
$(Export-FunctionSource -NoHeader ProfileCode_pre_common),
'',
'',
$(Export-FunctionSource -NoHeader ProfileCode_common),
'',
'',
$(Export-FunctionSource -NoHeader ProfileCode_post_common),
'',
$ProfileSignature.End
) -join "`n" ).Trim().Replace(('$'+'_'),('$$'+'_')))
}
$profileContent = $($profileContent -replace $randomSeed,$cleanupValue).Trim()
$local:shouldSudo = $sudo -and -not $userFile
$local:status = 'Skipped'
if( $VerbosePreference -eq 'Continue' ) { $ShowSkipped = $true }
if( -not ([string]::IsNullOrWhiteSpace($profileContent)) ) {
$status = "Need $(if($cleanupValue){'Setup'}else{'Cleanup'})"
if( $sudo -or $userFile ) {
Write-Verbose "Writing content to $($_)..."
$local:tmpOutput = New-TemporaryFile -WhatIf:$false
$profileContent | Out-File $tmpOutput.FullName -WhatIf:$false
if( $shouldSudo -and $( $PSVersionTable.Platform -eq 'Unix' ) ) {
Invoke-ExpressionEx -sudo:$shouldSudo chmod 'a+r' $tmpOutput.FullName
}
try {
$local:errMsg = $(Invoke-ExpressionEx -sudo:$shouldSudo "Move-Item $($tmpOutput.FullName) $p -Force:`$$Force -ErrorAction Stop | Out-Null" 2>&1)
if( $errMsg ) {
Write-Error "$errMsg"
$status = $status -replace 'Need ','Failed '
} else {
$status = $status -replace 'Need ',''
}
} catch {
Write-Error "Writing $p failed!"
}
} else {
$status = "Need $status"
Write-Error "Cannot write into [$_]'$p'! Please re-run with sudo."
}
} elseif( ($Force -or $RemoveOnly) -and $exists ) {
$status = 'Need Removal'
if( $sudo -or $userFile ) {
Write-Verbose "Removing [$_]'$p'..."
try {
Invoke-ExpressionEx -sudo:$shouldSudo Remove-Item $p
if( -not (Test-Path $p) ) { $status = 'Removed' }
} catch {
Write-Error "Removal of $p failed!"
}
} else {
Write-Error "Cannot remove [$_]'$p'! Please re-run with sudo."
}
}
if( $status -ne 'Skipped' -or $ShowSkipped ) {
if( $shouldSudo -and $status -ne 'Skipped' ) { $status = "$status via sudo" }
New-ProfileSetupStatus -Name $_ -Path $p -Status $status -Exist $(Test-Path $p)
}
}
Remove-Item function:ProfileCode* -Confirm:$false
}
if( -not $SetupFromWeb ) {
_setup @PSBoundParameters
Get-Item function:_setup | Remove-Item
}
Remove-Variable SetupFromWeb
Remove-Variable SetupFromWeb -ErrorAction SilentlyContinue