|
- [CmdletBinding(SupportsShouldProcess)]param(
- [switch]$sudo,
- [switch]$RemoveOnly,
- [switch]$ShowSkipped,
- [switch]$Force,
- [switch]$GitClone,
- [string]$GitURL = 'https://code.lksz.me/lksz/PowerShell_Scripts',
- [Parameter(DontShow)]
- [string]$MyPSScriptRoot = $MyPSScriptRoot
- )
-
- function _Setup {
- [CmdletBinding(SupportsShouldProcess)]param(
- [switch]$sudo,
- [switch]$RemoveOnly,
- [switch]$ShowSkipped,
- [switch]$Force,
- [switch]$GitClone,
- [string]$GitURL = 'https://code.lksz.me/lksz/PowerShell_Scripts',
- [Parameter(DontShow)]
- [string]$MyPSScriptRoot = $MyPSScriptRoot)
-
-
- #######################################################################
- ## ProfileCode function (source) will contain the code to be written
- #######################################################################
- function ProfileCode_pre_common {
- # # If TMUX isn't loaded, start byobu, then exit this script (and current shell)
- # if ( -not ( Test-Path env:TMUX ) ) { byobu; exit }
- }
- #######################################################################
- ## common Profile Code - receommended not to change this
- ## Code will be loaded from profile.d sub-directory after this.
- #######################################################################
- 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 }
- }
-
- function ProfileCode_common {
- function Get-PowerShellPath {
- Get-Process -PID $PID | ForEach-Object { $_.Path,$_.Parent.Path } | Where-Object { $_ -match 'powershell|pwsh' } | Select-Object -First 1
- }
-
- function ConvertTo-Base64 {
- param([string]$String)
- return [Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($String))
- }
-
- function Invoke-ExpressionEx() {
- [CmdletBinding(SupportsShouldProcess)]param(
- [switch]$sudo,
- [switch]$Force,
- [string]$Function,
- [Parameter(Position = 1, ValueFromRemainingArguments = $true)]
- [string[]]$expr
- )
-
- if( $sudo -and -not $(Test-IsAdmin) ) {
- $local:tmpFile = $null
- 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
- }
-
- $expr = @(
- '$WhatIfPreference', '=', "`$$WhatIfPreference", ';',
- '$VerbosePreference', '=', "'$VerbosePreference'", ";",
- '$ErrorActionPreference', '=', "'$ErrorActionPreference'", ";",
- '$ConfirmPreference', '=', "'$ConfirmPreference'", ";"
- ) + $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 }
- return
- }
-
- Write-Verbose "Perofrming the following expression in-line:`n{$($expr -join ' ')}"
- Invoke-Expression "$expr"
- }
-
- function Test-IsAdmin{
- [CmdletBinding(ConfirmImpact = 'None')]
- [OutputType([bool])]
- param ()
-
- switch($true){
- $( ($PSVersionTable.PSEdition -eq 'Desktop') -or
- ($PSVersionTable.Platform -eq 'Win32NT')
- ) {
- # Fastest way on Windows
- ([Security.Principal.WindowsPrincipal](
- [Security.Principal.WindowsIdentity]::GetCurrent()
- )).IsInRole(
- [Security.Principal.WindowsBuiltInRole]'Administrator'
- )
- }
- $( ($PSVersionTable.PSEdition -eq 'Core') -and
- ($PSVersionTable.Platform -eq 'Unix')
- ) {
- # On macOS and Linux we use ID to figure out if we run elevated (0 means superuser rights)
- return $((id -u) -eq 0)
- }
- default {
- # Unable to figure it out!
- Write-Warning -Message 'Unknown'
-
- return
- }
- }
-
- }
-
- function Export-FunctionSource {
- param(
- [switch]$NoHeader,
- [Parameter(Position = 0, ValueFromRemainingArguments = $true)]
- #[ValidateSet([Functions])]
- [string[]]$FunctionName
-
- )
-
- $local:src = ""
- foreach( $local:func in $FunctionName ) {
- if( -not $NoHeader ) { $src += "`nfunction $func {" }
- $src += "`n"
- $src += $((Get-Command -Type Function $func).Definition) ### .Replace(('$'+'_'),('$$'+'_'))
- if( -not $NoHeader ) { $src += "`n}" }
- $src += "`n"
- }
- return $src.Trim()
- }
-
- # Are we running in Unix or Windows?
- $global:PathEnvDelimiter = $(if( $PSVersionTable.Platform -match 'unix' ) {':'} else {';'})
- function Split-PathEnv {
- param([string]$EnvPath)
- $EnvPath -split $PathEnvDelimiter
- }
-
- # Establish Module Path
- $global:MyPSModulePath = Split-PathEnv $env:PSModulePath | Where-Object { $_ -match "^$($(Resolve-Path ~) -replace '\\',"\\")" }
-
- if( -not $MyPSModulePath ) {
- $MyPSModulePath = $(Join-Path $(Join-Path $(Resolve-Path ~) 'powershell') 'Modules')
- $env:PSModulePath = "$MyPSModulePath$PathEnvDelimiter$env:PSModulePath"
- }
- if( -not (Test-Path $MyPSModulePath) ) {
- New-Item -ItemType Directory -Path $MyPSModulePath -Force | Out-Null
- }
-
- Write-Verbose $(Get-Item $MyPSModulePath | Select-Object -ExpandProperty FullName)
-
- # Establish local/personal Script Root and make sure it's in $env:Path
- $local:p = Split-PathEnv $env:PATH
- $MyPSScriptRoot = Join-Path (Split-Path -Parent $MyPSModulePath) Scripts
- Write-Verbose "MyPSScriptRoot = $MyPSScriptRoot"
- if( -not (Test-Path $MyPSScriptRoot) ) {
- New-Item -ItemType Directory -Path $MyPSScriptRoot -Force | Out-Null
- New-Item -ItemType Directory -Path $MyPSScriptRoot/profile.d -Force | Out-Null
- }
- $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
|