diff options
| author | srdusr <trevorgray@srdusr.com> | 2024-06-04 15:14:39 +0200 |
|---|---|---|
| committer | srdusr <trevorgray@srdusr.com> | 2024-06-04 15:14:39 +0200 |
| commit | dc43267c2d6fe0725b45e59344c54f45a14dfd33 (patch) | |
| tree | 5ecc0a5b8fc508842f4d64da46ef8f9b23c12326 /.config/powershell | |
| parent | 6131362047153525f66b43d2aabaaabf3d5af50a (diff) | |
| download | dotfiles-dc43267c2d6fe0725b45e59344c54f45a14dfd33.tar.gz dotfiles-dc43267c2d6fe0725b45e59344c54f45a14dfd33.zip | |
Testing
Diffstat (limited to '.config/powershell')
| -rw-r--r-- | .config/powershell/Microsoft.PowerShell_profile.ps1 | 9 | ||||
| -rw-r--r-- | .config/powershell/bootstrap.ps1 | 372 | ||||
| -rw-r--r-- | .config/powershell/initialize.ps1 | 226 | ||||
| -rw-r--r-- | .config/powershell/onedrive.ps1 | 68 | ||||
| -rw-r--r-- | .config/powershell/ownership.ps1 | 109 |
5 files changed, 548 insertions, 236 deletions
diff --git a/.config/powershell/Microsoft.PowerShell_profile.ps1 b/.config/powershell/Microsoft.PowerShell_profile.ps1 index db4d580..ed276ad 100644 --- a/.config/powershell/Microsoft.PowerShell_profile.ps1 +++ b/.config/powershell/Microsoft.PowerShell_profile.ps1 @@ -11,6 +11,15 @@ function global:config { git --git-dir="$env:USERPROFILE\.cfg" --work-tree="$env:USERPROFILE" $args } +# Shows navigable menu of all options when hitting Tab +Set-PSReadlineKeyHandler -Key Tab -Function MenuComplete + +# Autocompletion for arrow keys +Set-PSReadlineKeyHandler -Key UpArrow -Function HistorySearchBackward +Set-PSReadlineKeyHandler -Key DownArrow -Function HistorySearchForward + +New-Alias vi nvim.exe + # Chocolatey profile $ChocolateyProfile = "$env:ChocolateyInstall\helpers\chocolateyProfile.psm1" if (Test-Path $ChocolateyProfile) { diff --git a/.config/powershell/bootstrap.ps1 b/.config/powershell/bootstrap.ps1 index 4ae88e6..98c291d 100644 --- a/.config/powershell/bootstrap.ps1 +++ b/.config/powershell/bootstrap.ps1 @@ -1,10 +1,19 @@ # Requires -RunAsAdministrator +# Set execution policy to remote signed +Set-ExecutionPolicy RemoteSigned + +# Set network category to private +Set-NetConnectionProfile -NetworkCategory Private + # Variables -#$newUsername = "srdusr" $dotfiles_url = 'https://github.com/srdusr/dotfiles.git' $dotfiles_dir = "$HOME\.cfg" -$oldUsername = $env:USERNAME + +# Imports +. .\initialize.ps1 +. .\ownership.ps1 +. .\onedrive.ps1 # Function to handle errors function handle_error { @@ -48,123 +57,11 @@ $bloatware = @( # Helper functions ------------------------ function force-mkdir($path) { if (!(Test-Path $path)) { - #Write-Host "-- Creating full path to: " $path -ForegroundColor White -BackgroundColor DarkGreen + Write-Host "-- Creating full path to: " $path -ForegroundColor White -BackgroundColor DarkGreen New-Item -ItemType Directory -Force -Path $path } } -function Takeown-Registry($key) { - # TODO does not work for all root keys yet - switch ($key.split('\')[0]) { - "HKEY_CLASSES_ROOT" { - $reg = [Microsoft.Win32.Registry]::ClassesRoot - $key = $key.substring(18) - } - "HKEY_CURRENT_USER" { - $reg = [Microsoft.Win32.Registry]::CurrentUser - $key = $key.substring(18) - } - "HKEY_LOCAL_MACHINE" { - $reg = [Microsoft.Win32.Registry]::LocalMachine - $key = $key.substring(19) - } - } - - # get administraor group - $admins = New-Object System.Security.Principal.SecurityIdentifier("S-1-5-32-544") - $admins = $admins.Translate([System.Security.Principal.NTAccount]) - - # set owner - $key = $reg.OpenSubKey($key, "ReadWriteSubTree", "TakeOwnership") - $acl = $key.GetAccessControl() - $acl.SetOwner($admins) - $key.SetAccessControl($acl) - - # set FullControl - $acl = $key.GetAccessControl() - $rule = New-Object System.Security.AccessControl.RegistryAccessRule($admins, "FullControl", "Allow") - $acl.SetAccessRule($rule) - $key.SetAccessControl($acl) -} - -function Takeown-File($path) { - takeown.exe /A /F $path - $acl = Get-Acl $path - - # get administraor group - $admins = New-Object System.Security.Principal.SecurityIdentifier("S-1-5-32-544") - $admins = $admins.Translate([System.Security.Principal.NTAccount]) - - # add NT Authority\SYSTEM - $rule = New-Object System.Security.AccessControl.FileSystemAccessRule($admins, "FullControl", "None", "None", "Allow") - $acl.AddAccessRule($rule) - - Set-Acl -Path $path -AclObject $acl -} - -function Takeown-Folder($path) { - Takeown-File $path - foreach ($item in Get-ChildItem $path) { - if (Test-Path $item -PathType Container) { - Takeown-Folder $item.FullName - } - else { - Takeown-File $item.FullName - } - } -} - -function Elevate-Privileges { - param($Privilege) - $Definition = @" - using System; - using System.Runtime.InteropServices; - - public class AdjPriv { - [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)] - internal static extern bool AdjustTokenPrivileges(IntPtr htok, bool disall, ref TokPriv1Luid newst, int len, IntPtr prev, IntPtr rele); - - [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)] - internal static extern bool OpenProcessToken(IntPtr h, int acc, ref IntPtr phtok); - - [DllImport("advapi32.dll", SetLastError = true)] - internal static extern bool LookupPrivilegeValue(string host, string name, ref long pluid); - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - internal struct TokPriv1Luid { - public int Count; - public long Luid; - public int Attr; - } - - internal const int SE_PRIVILEGE_ENABLED = 0x00000002; - internal const int TOKEN_QUERY = 0x00000008; - internal const int TOKEN_ADJUST_PRIVILEGES = 0x00000020; - - public static bool EnablePrivilege(long processHandle, string privilege) { - bool retVal; - TokPriv1Luid tp; - IntPtr hproc = new IntPtr(processHandle); - IntPtr htok = IntPtr.Zero; - retVal = OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok); - tp.Count = 1; - tp.Luid = 0; - tp.Attr = SE_PRIVILEGE_ENABLED; - retVal = LookupPrivilegeValue(null, privilege, ref tp.Luid); - retVal = AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero); - return retVal; - } - } -"@ - $ProcessHandle = (Get-Process -id $pid).Handle - $type = Add-Type $definition -PassThru - $type[0]::EnablePrivilege($processHandle, $Privilege) -} - -# Elevate so I can run everything ------------------------ -Write-Output "Elevating priviledges for this process" -do { } until (Elevate-Privileges SeTakeOwnershipPrivilege) - # Remove Features ------------------------ foreach ($bloat in $bloatware) { Write-Output "Removing packages containing $bloat" @@ -182,7 +79,6 @@ foreach ($bloat in $bloatware) { } } - # Remove default apps and bloat ------------------------ Write-Output "Uninstalling default apps" foreach ($app in $apps) { @@ -197,74 +93,72 @@ foreach ($app in $apps) { force-mkdir "HKLM:\SOFTWARE\Policies\Microsoft\Windows\Cloud Content" Set-ItemProperty "HKLM:\SOFTWARE\Policies\Microsoft\Windows\Cloud Content" "DisableWindowsConsumerFeatures" 1 -# Kill OneDrive with fire ------------------------ -Write-Output "Kill OneDrive process" -taskkill.exe /F /IM "OneDrive.exe" -taskkill.exe /F /IM "explorer.exe" - -Write-Output "Remove OneDrive" -if (Test-Path "$env:systemroot\System32\OneDriveSetup.exe") { - & "$env:systemroot\System32\OneDriveSetup.exe" /uninstall -} -if (Test-Path "$env:systemroot\SysWOW64\OneDriveSetup.exe") { - & "$env:systemroot\SysWOW64\OneDriveSetup.exe" /uninstall -} - -Write-Output "Removing OneDrive leftovers" -Remove-Item -Recurse -Force -ErrorAction SilentlyContinue "$env:localappdata\Microsoft\OneDrive" -Remove-Item -Recurse -Force -ErrorAction SilentlyContinue "$env:programdata\Microsoft OneDrive" -Remove-Item -Recurse -Force -ErrorAction SilentlyContinue "$env:systemdrive\OneDriveTemp" -# check if directory is empty before removing: -If ((Get-ChildItem "$env:userprofile\OneDrive" -Recurse | Measure-Object).Count -eq 0) { - Remove-Item -Recurse -Force -ErrorAction SilentlyContinue "$env:userprofile\OneDrive" -} - -Write-Output "Disable OneDrive via Group Policies" -force-mkdir "HKLM:\SOFTWARE\Wow6432Node\Policies\Microsoft\Windows\OneDrive" -Set-ItemProperty "HKLM:\SOFTWARE\Wow6432Node\Policies\Microsoft\Windows\OneDrive" "DisableFileSyncNGSC" 1 +# Install Chocolatey if not installed +Write-Host "Installing Chocolatey" +Write-Host "----------------------------------------" -Write-Output "Remove Onedrive from explorer sidebar" -New-PSDrive -PSProvider "Registry" -Root "HKEY_CLASSES_ROOT" -Name "HKCR" -force-mkdir "HKCR:\CLSID\{018D5C66-4533-4307-9B53-224DE2ED1FE6}" -Set-ItemProperty "HKCR:\CLSID\{018D5C66-4533-4307-9B53-224DE2ED1FE6}" "System.IsPinnedToNameSpaceTree" 0 -force-mkdir "HKCR:\Wow6432Node\CLSID\{018D5C66-4533-4307-9B53-224DE2ED1FE6}" -Set-ItemProperty "HKCR:\Wow6432Node\CLSID\{018D5C66-4533-4307-9B53-224DE2ED1FE6}" "System.IsPinnedToNameSpaceTree" 0 -Remove-PSDrive "HKCR" +Set-ExecutionPolicy Bypass -Scope Process -Force -# Thank you Matthew Israelsson -Write-Output "Removing run hook for new users" -reg load "hku\Default" "C:\Users\Default\NTUSER.DAT" -reg delete "HKEY_USERS\Default\SOFTWARE\Microsoft\Windows\CurrentVersion\Run" /v "OneDriveSetup" /f -reg unload "hku\Default" +if (-not (Get-Command choco -ErrorAction SilentlyContinue)) { + [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072 + Invoke-Expression ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1')) -Write-Output "Removing startmenu entry" -Remove-Item -Force -ErrorAction SilentlyContinue "$env:userprofile\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\OneDrive.lnk" + # Check if Chocolatey installed successfully + if (-not (Get-Command choco -ErrorAction SilentlyContinue)) { + handle_error "Chocolatey installation failed." + } +} else { + Write-Host "Chocolatey is already installed." +} -Write-Output "Removing scheduled task" -Get-ScheduledTask -TaskPath '\' -TaskName 'OneDrive*' -ea SilentlyContinue | Unregister-ScheduledTask -Confirm:$false +# Install Applications +Write-Host "Installing Applications" +Write-Host "----------------------------------------" -Write-Output "Restarting explorer" -Start-Process "explorer.exe" +# List of applications to install +$apps = @( + "git", + "ripgrep", + "fd", + "sudo", + "win32yank", + "neovim", + "microsoft-windows-terminal", + "wsl", + "firefox", + #"spotify", + #"discord", + #"vscode", + "nodejs", + "bat", + "coreutils", + "delta", + "fnm", + "gh", + "less", + "lua", + "make", + "tokei", + "zoxide", +) -Write-Output "Waiting for explorer to complete loading" -Start-Sleep 10 +foreach ($app in $apps) { + # Check if the application is already installed + if (-not (choco list --local-only | Select-String -Pattern "^$app\s")) { + Write-Host "Installing $app" + choco install $app -y -Write-Output "Removing additional OneDrive leftovers" -foreach ($item in (Get-ChildItem "$env:WinDir\WinSxS\*onedrive*")) { - Takeown-Folder $item.FullName - Remove-Item -Recurse -Force $item.FullName + if ($LASTEXITCODE -ne 0) { + handle_error "Installation of $app failed." + } else { + Write-Host "$app installed successfully." + } + } else { + Write-Host "$app is already installed." + } } -# As a last step, disable UAC ------------------------ -#New-ItemProperty -Path HKLM:Software\Microsoft\Windows\CurrentVersion\policies\system -Name EnableLUA -PropertyType DWord -Value 0 -Force - - -# Remove OneDrive directory -Write-Host "Removing OneDrive directory" -cd $HOME -rm OneDrive -r -force - - Configure PowerShell +# Configure PowerShell Write-Host "Configuring PowerShell" Write-Host "----------------------------------------" @@ -325,6 +219,23 @@ Add-Content -Path "$HOME\.gitignore" -Value ".config/powershell/bootstrap.ps1" #echo '. "$HOME\Documents\PowerShell\Microsoft.PowerShell_profile.ps1"' >> $PROFILE +# Create symbolik links +Write-Host "Create symbolik links" +Write-Host "----------------------------------------" + +# Visual Studio Code settings.json +New-Item -Force -ItemType SymbolicLink $HOME\AppData\Roaming\Code\User\ -Name settings.json -Value $HOME\.config\Code\User\settings.json + +# Visual Studio Code keybindings +New-Item -Force -ItemType SymbolicLink $HOME\AppData\Roaming\Code\User\ -Name keybindings.json -Value $HOME\.config\Code\User\keybindings.json + + +# Update the current session environment variables +Write-Host "Setting environment variables" -ForegroundColor Cyan +[Environment]::SetEnvironmentVariable("HOME", "$env:USERPROFILE", "User") +[Environment]::SetEnvironmentVariable("LC_ALL", "C.UTF-8", "User") +Update-SessionEnvironment + # Function to install dotfiles function install_dotfiles { if (Test-Path -Path $dotfiles_dir) { @@ -364,50 +275,25 @@ install_dotfiles #. $PROFILE -# Install Chocolatey if not installed -Write-Host "Installing Chocolatey" -Write-Host "----------------------------------------" - -Set-ExecutionPolicy Bypass -Scope Process -Force - -if (-not (Get-Command choco -ErrorAction SilentlyContinue)) { - [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072 - Invoke-Expression ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1')) - - # Check if Chocolatey installed successfully - if (-not (Get-Command choco -ErrorAction SilentlyContinue)) { - handle_error "Chocolatey installation failed." - } -} else { - Write-Host "Chocolatey is already installed." -} - -# Install Applications -Write-Host "Installing Applications" -Write-Host "----------------------------------------" - -# Define the list of applications to install -$apps = @("ripgrep", "fd", "sudo", "win32yank", "neovim", "microsoft-windows-terminal") +# Install python +Write-Host "Updating python packages" -ForegroundColor Cyan +python -m pip install --upgrade pip +pip install --upgrade black flake8 -foreach ($app in $apps) { - # Check if the application is already installed - if (-not (choco list --local-only | Select-String -Pattern "^$app\s")) { - Write-Host "Installing $app" - choco install $app -y +# Enable WSL feature +dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart +Write-Host "Enable WSL feature" - if ($LASTEXITCODE -ne 0) { - handle_error "Installation of $app failed." - } else { - Write-Host "$app installed successfully." - } - } else { - Write-Host "$app is already installed." - } -} +# Enable Virtual Machine feature +dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart +Write-Host "Enable Virtual Machine feature" -## WSL -#Write-Host "Configuring WSL" +# WSL +Write-Host "Configuring WSL" #wsl --install -d Ubuntu +# setup wsl +wsl --set-default-version 2 +wsl -s Ubuntu ## Function to install SSH #function install_ssh { @@ -466,7 +352,6 @@ if (Test-Path -Path $windowsTerminalSettingsPath) { # Create a hard link to the settings.json file in .config\windows-terminal New-Item -ItemType HardLink -Force -Path $windowsTerminalSettingsPath -Target $windowsTerminalConfigPath - # Registry Tweaks Write-Host "Registry Tweaks" Write-Host "----------------------------------------" @@ -486,26 +371,41 @@ Set-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer # Set Windows to use UTC time instead of local time for system clock Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\TimeZoneInformation" -Name RealTimeIsUniversal -Value 1 -## Function to disable the Windows key -#function Disable-WindowsKey { -# $scancodeMap = @( -# 0x00000000, 0x00000000, 0x00000003, 0xE05B0000, 0xE05C0000, 0x00000000 -# ) -# -# $binaryValue = New-Object byte[] ($scancodeMap.Length * 4) -# [System.Buffer]::BlockCopy($scancodeMap, 0, $binaryValue, 0, $binaryValue.Length) -# -# Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Keyboard Layout" -Name "Scancode Map" -Value $binaryValue -# -# Write-Output "Windows key has been disabled. Please restart your computer for the changes to take effect." -#} -# -## Check if running as Administrator and call the function -#if (Test-IsAdmin) { -# Disable-WindowsKey -#} else { -# Write-Output "You need to run this script as Administrator to disable the Windows key." -#} +# Function to disable the Windows key +function Disable-WindowsKey { + $regPath = "HKLM:\SYSTEM\CurrentControlSet\Control\Keyboard Layout" + $regName = "Scancode Map" + + # Binary data to disable the Windows key + $binaryValue = [byte[]]( + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x5B, 0xE0, + 0x00, 0x00, 0x5C, 0xE0, + 0x00, 0x00, 0x00, 0x00 + ) + + # Create the registry key if it doesn't exist + if (-not (Test-Path $regPath)) { + New-Item -Path $regPath -Force | Out-Null + } + + # Set the Scancode Map value + Set-ItemProperty -Path $regPath -Name $regName -Value $binaryValue + + Write-Output "Windows key has been disabled. Please restart your computer for the changes to take effect." +} + +# Check if running as Administrator and call the function +if (Test-IsAdmin) { + Disable-WindowsKey +} else { + Write-Output "You need to run this script as Administrator to disable the Windows key." +} + +Write-Host "Bootstrap script completed." + # Restart to apply changes #Write-Host "Restarting system to apply changes..." #Restart-Computer -Force diff --git a/.config/powershell/initialize.ps1 b/.config/powershell/initialize.ps1 new file mode 100644 index 0000000..eaed874 --- /dev/null +++ b/.config/powershell/initialize.ps1 @@ -0,0 +1,226 @@ +<# + .SYNOPSIS + Bootstrap Windows command prompts (cmd, PS, PSCore) with my dotfiles and apps. + + .DESCRIPTION + to bootstrap directly from github, run these 2 cmdlets in a PowerShell prompt: + > Set-ExecutionPolicy RemoteSigned -Scope CurrentUser -Force + > irm 'https://raw.githubusercontent.com/davidjenni/dotfiles/main/bootstrap.ps1' | iex +#> +[CmdletBinding()] +param ( + [ValidateSet('clone', 'setup', 'apps', 'env', IgnoreCase = $true)] + [Parameter(Position = 0)] [string] + # verb that indicates stage: + # clone: clone the dotfiles repo and continue with 'setup' etc. + # setup: setup PS, package managers, git. Includes 'apps' and 'env'. + # apps: install apps via winget and scoop + # env: setups consoles and configurations for git, neovim, PowerShell etc. + $verb = 'clone', + [Parameter()] [string] + # user name for git commits, defaults to '$env:USERNAME@$env:COMPUTERNAME' + $userName = $null, + [Parameter()] [string] + # email address for git commits, defaults to existing git config or prompts for input + $email = $null, + [Parameter()] [switch] + # in most cases, do not run this script elevated; mostly needed in automation like PR loop + $runAsAdmin = $false +) + +$ErrorActionPreference = 'Stop' + +$originGitHub='https://github.com/srdusr/dotfiles.git' +$dotPath=(Join-Path $env:USERPROFILE 'dotfiles') + +# should be the default on all Win10+, but just in case... +[Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor + [Net.SecurityProtocolType]::Tls12 + +function ensureLocalGit { + if (Get-Command 'git' -ErrorAction SilentlyContinue) { + return + } + + # bootstrap with a local git to avoid early elevating for winget and the git installer: + $localGitFolder = (Join-Path $env:USERPROFILE (Join-Path "Downloads" "localGit")) + Write-Host "Installing ad-hoc git into $localGitFolder..." + + $gitUrl = Invoke-RestMethod 'https://api.github.com/repos/git-for-windows/git/releases/latest' | + Select-Object -ExpandProperty 'assets' | + Where-Object { $_.name -Match 'MinGit' -and $_.name -Match '64-bit' -and $_.name -notmatch 'busybox' } | + Select-Object -ExpandProperty 'browser_download_url' + $localGitZip = (Join-Path $localGitFolder "MinGit.zip") + New-Item -ItemType Directory -Path $localGitFolder -Force | Out-Null + # Invoke-RestMethod with its progress bar is about 10x slower than WebClient.DownloadFile... + (New-Object Net.WebClient).DownloadFile($gitUrl, $localGitZip) + Expand-Archive -Path $localGitZip -DestinationPath $localGitFolder -Force + + $gitPath = (Join-Path $localGitFolder 'cmd') + $env:Path += ";$gitPath" +} + +function cloneDotfiles { + Write-Host "Cloning $originGitHub -> $dotPath" + Write-Host -NoNewline "OK to proceed with setup? [Y/n] " + $answer = (Read-Host).ToUpper() + if ($answer -ne 'Y' -and $answer -ne '') { + Write-Warning "Aborting." + return 4 + } + + ensureLocalGit + + if (-not $userName -or $userName -eq '') { + $userName = (& git config --global --get user.name) + } + if (-not $username -or $username -eq '') { + $username = "$env:USERNAME@$env:COMPUTERNAME" + } + + if (-not $email -or $email -eq '') { + $email = (& git config --global --get user.email) + } + if (-not $email -or $email -eq '') { + $email = Read-Host "Enter your email address for git commits" + if ($email -eq '') { + Write-Warning "Need email address, aborting." + return 3 + } + } + + & git.exe config --global user.name $userName + # https://docs.github.com/en/account-and-profile/setting-up-and-managing-your-personal-account-on-github/managing-email-preferences/setting-your-commit-email-address + & git.exe config --global user.email $email + + & git clone $originGitHub $dotPath + return 0 +} + +function setup { + ensureLocalGit +} + +function installApps { + ensureLocalGit +} + +function writeGitConfig { + param ( + [Parameter(Mandatory = $true)] [string] $configIniFile + ) + + # do a one-off save for the formerly symlinked .gitconfig: + if ((Test-Path (Join-Path $env:USERPROFILE '.gitconfig')) -and -not (Test-Path (Join-Path $env:USERPROFILE '.gitconfig.bak'))) { + $userName = (& git config --global --get user.name) + $email = (& git config --global --get user.email) + + Move-Item -Path (Join-Path $env:USERPROFILE '.gitconfig') -Destination (Join-Path $env:USERPROFILE '.gitconfig.bak') + + if ($userName -and $userName -ne '') { + & git.exe config --global user.name $userName + } + if ($email -and $email -ne '') { + & git.exe config --global user.email $email + } + } + + Get-Content $configIniFile | ForEach-Object { + if ($_.TrimStart().StartsWith('#')) { return } + $key, $value = $_.Split('=', 2) + Write-Verbose "git config --global $key $value" + & git.exe config --global $key "$value" + } +} + +function setupShellEnvs { + Write-Host "setting cmd console properties:" + $consolePath='HKCU\Console' + & reg add $consolePath /v QuickEdit /d 0x1 /t REG_DWORD /f | Out-Null + & reg add $consolePath /v WindowSize /d 0x00320078 /t REG_DWORD /f | Out-Null + & reg add $consolePath /v ScreenBufferSize /d 0x23280078 /t REG_DWORD /f | Out-Null + & reg add $consolePath /v FontFamily /d 0x36 /t REG_DWORD /f | Out-Null + & reg add $consolePath /v HistoryBufferSize /d 0x64 /t REG_DWORD /f | Out-Null + & reg add $consolePath /v FaceName /d "Hack Nerd Font Mono" /t REG_SZ /f | Out-Null + & reg add $consolePath /v FontSize /d 0x00100000 /t REG_DWORD /f | Out-Null + + $win32rc=(Join-Path $PSScriptRoot (Join-Path 'win' 'win32-rc.cmd')) + Write-Host "setting up cmd autorun: $win32rc" + & reg add "HKCU\Software\Microsoft\Command Processor" /v AutoRun /t REG_SZ /d $win32rc /f | Out-Null + + # TODO: needs elevation + # Write-Host "remap CapsLock to LeftCtrl key:" + # # see http://www.experts-exchange.com/OS/Microsoft_Operating_Systems/Windows/A_2155-Keyboard-Remapping-CAPSLOCK-to-Ctrl-and-Beyond.html + # # http://msdn.microsoft.com/en-us/windows/hardware/gg463447.aspx + # & reg add "HKLM\SYSTEM\CurrentControlSet\Control\Keyboard Layout" /v "Scancode Map" /d 0000000000000000020000001D003A0000000000 /t REG_BINARY /f | Out-Null + # Write-Host "CapsLock remapped, will be effective after next system reboot." + + # TODO: initialize Terminal, but its .json file won't exist until after the first launch + # $env:LOCALAPPDATA\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState\settings.json + + # can't use on WinPS, too many at-work scripts fail + # $psProfile = (& powershell -NoProfile -Command '$PROFILE.CurrentUserAllHosts') + # copyFile (Join-Path 'win' 'profile.ps1') $psProfile + + Write-Host "configuring user home dir..." + $configDir = (Join-Path $env:USERPROFILE '.config') + New-Item -ItemType Directory -Path $configDir -ErrorAction SilentlyContinue | Out-Null + + writeGitConfig (Join-Path $PSScriptRoot 'gitconfig.ini') + + $sshDir = (Join-Path $env:USERPROFILE '.ssh') + # ensure 1Password's identity agent is visible to OpenSSH; cannot have both config and socket on Windows + # https://developer.1password.com/docs/ssh/agent/advanced#windows + # https://developer.1password.com/docs/ssh/get-started/#step-4-configure-your-ssh-or-git-client + Remove-Item (Join-Path $sshDir 'config') -ErrorAction SilentlyContinue -Force | Out-Null + $openSsh=((Join-Path $env:windir 'System32\OpenSSH\ssh.exe').Replace("\", "/")) + & git config --global core.sshCommand $openSsh +} + +function main { + param ( + [Parameter(Mandatory = $true)] [string] $verbAction + ) + + Write-Verbose "PS: $($PSVersionTable.PSVersion)-$($PSVersionTable.PSEdition)" + switch ($verbAction) { + 'clone' { + Write-Host + if (Test-Path (Join-Path $dotPath '.git')) { + Write-Host "local git repo already exists, skipping." + # continue in-proc: + main setup + return + } + + $rc = cloneDotfiles + if ($rc -ne 0) { + Write-Error "Cloning dotfiles failed, aborting." + return + } + # continue with now-local bootstrap.ps1 from cloned repo: + # still stick with desktop PS since PSCore is not necessarily installed yet + $script= (Join-Path $dotPath 'bootstrap.ps1') + Write-Host "Continue $script in child process" + Start-Process -PassThru -NoNewWindow -FilePath "powershell.exe" -ArgumentList "-NoProfile -File $script setup" | + Wait-Process + } + + 'setup' { + Write-Host "Setting up..." + setup + installApps + setupShellEnvs + Write-Host "Done (setup)." + exit + } + + 'apps' { installApps } + + 'env' { setupShellEnvs } + } + + Write-Host "Done." +} + +main $verb diff --git a/.config/powershell/onedrive.ps1 b/.config/powershell/onedrive.ps1 new file mode 100644 index 0000000..625c315 --- /dev/null +++ b/.config/powershell/onedrive.ps1 @@ -0,0 +1,68 @@ +# onedrive.ps1 + +# Kill OneDrive with fire ------------------------ +Write-Output "Kill OneDrive process" +taskkill.exe /F /IM "OneDrive.exe" +taskkill.exe /F /IM "explorer.exe" + +Write-Output "Remove OneDrive" +if (Test-Path "$env:systemroot\System32\OneDriveSetup.exe") { + & "$env:systemroot\System32\OneDriveSetup.exe" /uninstall +} +if (Test-Path "$env:systemroot\SysWOW64\OneDriveSetup.exe") { + & "$env:systemroot\SysWOW64\OneDriveSetup.exe" /uninstall +} + +Write-Output "Removing OneDrive leftovers" +Remove-Item -Recurse -Force -ErrorAction SilentlyContinue "$env:localappdata\Microsoft\OneDrive" +Remove-Item -Recurse -Force -ErrorAction SilentlyContinue "$env:programdata\Microsoft OneDrive" +Remove-Item -Recurse -Force -ErrorAction SilentlyContinue "$env:systemdrive\OneDriveTemp" +# check if directory is empty before removing: +If ((Get-ChildItem "$env:userprofile\OneDrive" -Recurse | Measure-Object).Count -eq 0) { + Remove-Item -Recurse -Force -ErrorAction SilentlyContinue "$env:userprofile\OneDrive" +} + +Write-Output "Disable OneDrive via Group Policies" +force-mkdir "HKLM:\SOFTWARE\Wow6432Node\Policies\Microsoft\Windows\OneDrive" +Set-ItemProperty "HKLM:\SOFTWARE\Wow6432Node\Policies\Microsoft\Windows\OneDrive" "DisableFileSyncNGSC" 1 + +Write-Output "Remove Onedrive from explorer sidebar" +New-PSDrive -PSProvider "Registry" -Root "HKEY_CLASSES_ROOT" -Name "HKCR" +force-mkdir "HKCR:\CLSID\{018D5C66-4533-4307-9B53-224DE2ED1FE6}" +Set-ItemProperty "HKCR:\CLSID\{018D5C66-4533-4307-9B53-224DE2ED1FE6}" "System.IsPinnedToNameSpaceTree" 0 +force-mkdir "HKCR:\Wow6432Node\CLSID\{018D5C66-4533-4307-9B53-224DE2ED1FE6}" +Set-ItemProperty "HKCR:\Wow6432Node\CLSID\{018D5C66-4533-4307-9B53-224DE2ED1FE6}" "System.IsPinnedToNameSpaceTree" 0 +Remove-PSDrive "HKCR" + +# Thank you Matthew Israelsson +Write-Output "Removing run hook for new users" +reg load "hku\Default" "C:\Users\Default\NTUSER.DAT" +reg delete "HKEY_USERS\Default\SOFTWARE\Microsoft\Windows\CurrentVersion\Run" /v "OneDriveSetup" /f +reg unload "hku\Default" + +Write-Output "Removing startmenu entry" +Remove-Item -Force -ErrorAction SilentlyContinue "$env:userprofile\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\OneDrive.lnk" + +Write-Output "Removing scheduled task" +Get-ScheduledTask -TaskPath '\' -TaskName 'OneDrive*' -ea SilentlyContinue | Unregister-ScheduledTask -Confirm:$false + +Write-Output "Restarting explorer" +Start-Process "explorer.exe" + +Write-Output "Waiting for explorer to complete loading" +Start-Sleep 10 + +Write-Output "Removing additional OneDrive leftovers" +foreach ($item in (Get-ChildItem "$env:WinDir\WinSxS\*onedrive*")) { + Takeown-Folder $item.FullName + Remove-Item -Recurse -Force $item.FullName +} + +# As a last step, disable UAC ------------------------ +New-ItemProperty -Path HKLM:Software\Microsoft\Windows\CurrentVersion\policies\system -Name EnableLUA -PropertyType DWord -Value 0 -Force + +# Remove OneDrive directory +Write-Host "Removing OneDrive directory" +cd $HOME +rm OneDrive -r -force + diff --git a/.config/powershell/ownership.ps1 b/.config/powershell/ownership.ps1 new file mode 100644 index 0000000..acd1e70 --- /dev/null +++ b/.config/powershell/ownership.ps1 @@ -0,0 +1,109 @@ +# ownership.ps1 + +function Takeown-Registry($key) { + # TODO does not work for all root keys yet + switch ($key.split('\')[0]) { + "HKEY_CLASSES_ROOT" { + $reg = [Microsoft.Win32.Registry]::ClassesRoot + $key = $key.substring(18) + } + "HKEY_CURRENT_USER" { + $reg = [Microsoft.Win32.Registry]::CurrentUser + $key = $key.substring(18) + } + "HKEY_LOCAL_MACHINE" { + $reg = [Microsoft.Win32.Registry]::LocalMachine + $key = $key.substring(19) + } + } + + # get administrator group + $admins = New-Object System.Security.Principal.SecurityIdentifier("S-1-5-32-544") + $admins = $admins.Translate([System.Security.Principal.NTAccount]) + + # set owner + $key = $reg.OpenSubKey($key, "ReadWriteSubTree", "TakeOwnership") + $acl = $key.GetAccessControl() + $acl.SetOwner($admins) + $key.SetAccessControl($acl) + + # set FullControl + $acl = $key.GetAccessControl() + $rule = New-Object System.Security.AccessControl.RegistryAccessRule($admins, "FullControl", "Allow") + $acl.SetAccessRule($rule) + $key.SetAccessControl($acl) +} + +function Takeown-File($path) { + takeown.exe /A /F $path + $acl = Get-Acl $path + + # get administrator group + $admins = New-Object System.Security.Principal.SecurityIdentifier("S-1-5-32-544") + $admins = $admins.Translate([System.Security.Principal.NTAccount]) + + # add NT Authority\SYSTEM + $rule = New-Object System.Security.AccessControl.FileSystemAccessRule($admins, "FullControl", "None", "None", "Allow") + $acl.AddAccessRule($rule) + + Set-Acl -Path $path -AclObject $acl +} + +function Takeown-Folder($path) { + Takeown-File $path + foreach ($item in Get-ChildItem $path) { + if (Test-Path $item -PathType Container) { + Takeown-Folder $item.FullName + } + else { + Takeown-File $item.FullName + } + } +} + +function Elevate-Privileges { + param($Privilege) + $Definition = @" + using System; + using System.Runtime.InteropServices; + + public class AdjPriv { + [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)] + internal static extern bool AdjustTokenPrivileges(IntPtr htok, bool disall, ref TokPriv1Luid newst, int len, IntPtr prev, IntPtr rele); + + [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)] + internal static extern bool OpenProcessToken(IntPtr h, int acc, ref IntPtr phtok); + + [DllImport("advapi32.dll", SetLastError = true)] + internal static extern bool LookupPrivilegeValue(string host, string name, ref long pluid); + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + internal struct TokPriv1Luid { + public int Count; + public long Luid; + public int Attr; + } + + internal const int SE_PRIVILEGE_ENABLED = 0x00000002; + internal const int TOKEN_QUERY = 0x00000008; + internal const int TOKEN_ADJUST_PRIVILEGES = 0x00000020; + + public static bool EnablePrivilege(long processHandle, string privilege) { + bool retVal; + TokPriv1Luid tp; + IntPtr hproc = new IntPtr(processHandle); + IntPtr htok = IntPtr.Zero; + retVal = OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok); + tp.Count = 1; + tp.Luid = 0; + tp.Attr = SE_PRIVILEGE_ENABLED; + retVal = LookupPrivilegeValue(null, privilege, ref tp.Luid); + retVal = AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero); + return retVal; + } + } +"@ + $ProcessHandle = (Get-Process -id $pid).Handle + $type = Add-Type $definition -PassThru + $type[0]::EnablePrivilege($processHandle, $Privilege) +} |
