aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.config/powershell/Microsoft.PowerShell_profile.ps19
-rw-r--r--.config/powershell/bootstrap.ps1372
-rw-r--r--.config/powershell/initialize.ps1226
-rw-r--r--.config/powershell/onedrive.ps168
-rw-r--r--.config/powershell/ownership.ps1109
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)
+}