11# -------------------------------------------------
2- # This script sets the "UwU" cursor scheme by:
3- # 1) Copying cursor files from the "Cursor" folder
4- # (in the same directory as the script) to
5- # "C:\Windows\Cursors\MyCustomCursors"
6- # 2) Updating the Registry to apply them
7- # 3) Forcing a refresh so the cursors apply immediately
2+ # Custom Cursor Installer - UwU scheme
83# -------------------------------------------------
4+ # 1) Copies cursor files from .\Cursor (script directory) to:
5+ # C:\Windows\Cursors\MyCustomCursors
6+ # 2) Updates Registry to apply them
7+ # 3) Forces a refresh so the cursors apply immediately
8+ # -------------------------------------------------
9+
10+ [CmdletBinding ()]
11+ param (
12+ # Keep old behavior: open Mouse Control Panel by default
13+ [switch ]$OpenControlPanel = $true
14+ )
915
16+ $ErrorActionPreference = " Stop"
17+
18+ # [0] Admin check (README says admin required, so fail fast)
19+ # -------------------------------------------------
20+ $principal = New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity ]::GetCurrent())
21+ if (-not $principal.IsInRole ([Security.Principal.WindowsBuiltinRole ]::Administrator)) {
22+ Write-Error " Run PowerShell as Administrator."
23+ exit 1
24+ }
1025
1126# [1] Copy cursor files
1227# -------------------------------------------------
13- $sourceFolder = " $ ( Get-Location ) \ Cursor"
28+ $sourceFolder = Join-Path $PSScriptRoot " Cursor"
1429$targetFolder = " C:\Windows\Cursors\MyCustomCursors"
1530
31+ if (-not (Test-Path $sourceFolder )) {
32+ Write-Error " Source folder not found: $sourceFolder "
33+ exit 1
34+ }
35+
1636if (-Not (Test-Path $targetFolder )) {
1737 New-Item - ItemType Directory - Path $targetFolder | Out-Null
1838}
1939
20- Write-Host " Copying cursors to $targetFolder ..."
21- Copy-Item - Path " $sourceFolder \*" - Destination $targetFolder - Recurse - Force
22-
40+ Write-Host " Copying cursors from $sourceFolder to $targetFolder ..."
41+ Copy-Item - Path (Join-Path $sourceFolder " *" ) - Destination $targetFolder - Force
2342
2443# [2] Map cursors and set Registry values
2544# -------------------------------------------------
2645$cursorMappings = @ {
27- " Arrow" = " $targetFolder \1 Normal Select.ani"
28- " Help" = " $targetFolder \2 Help Select.ani"
29- " AppStarting" = " $targetFolder \3 Working in Background.ani"
30- " Wait" = " $targetFolder \4 Busy.ani"
31- " Crosshair" = " $targetFolder \5 Precision Select.ani"
32- " IBeam" = " $targetFolder \6 Text Select.ani"
33- " NWPen" = " $targetFolder \7 Handwriting.ani"
34- " No" = " $targetFolder \8 Unavailable.ani"
35- " SizeNS" = " $targetFolder \9 Vertical Resize.ani"
36- " SizeWE" = " $targetFolder \10 Horizontal Resize.ani"
37- " SizeNWSE" = " $targetFolder \11 Diagonal Resize 1.ani"
38- " SizeNESW" = " $targetFolder \12 Diagonal Resize 2.ani"
39- " SizeAll" = " $targetFolder \13 Move.ani"
40- " Hand" = " $targetFolder \15 Link Select.ani"
41- " UpArrow" = " $targetFolder \14 Alternate Select.ani"
42- " Pin" = " $targetFolder \16 pin.ani"
43- " Person" = " $targetFolder \17 person.ani"
46+ " Arrow" = (Join-Path $targetFolder " 1 Normal Select.ani" )
47+ " Help" = (Join-Path $targetFolder " 2 Help Select.ani" )
48+ " AppStarting" = (Join-Path $targetFolder " 3 Working in Background.ani" )
49+ " Wait" = (Join-Path $targetFolder " 4 Busy.ani" )
50+ " Crosshair" = (Join-Path $targetFolder " 5 Precision Select.ani" )
51+ " IBeam" = (Join-Path $targetFolder " 6 Text Select.ani" )
52+ " NWPen" = (Join-Path $targetFolder " 7 Handwriting.ani" )
53+ " No" = (Join-Path $targetFolder " 8 Unavailable.ani" )
54+ " SizeNS" = (Join-Path $targetFolder " 9 Vertical Resize.ani" )
55+ " SizeWE" = (Join-Path $targetFolder " 10 Horizontal Resize.ani" )
56+ " SizeNWSE" = (Join-Path $targetFolder " 11 Diagonal Resize 1.ani" )
57+ " SizeNESW" = (Join-Path $targetFolder " 12 Diagonal Resize 2.ani" )
58+ " SizeAll" = (Join-Path $targetFolder " 13 Move.ani" )
59+ " UpArrow" = (Join-Path $targetFolder " 14 Alternate Select.ani" )
60+ " Hand" = (Join-Path $targetFolder " 15 Link Select.ani" )
61+ " Pin" = (Join-Path $targetFolder " 16 pin.ani" )
62+ " Person" = (Join-Path $targetFolder " 17 person.ani" )
63+ }
64+
65+ # Validate files exist BEFORE touching registry
66+ $missing = foreach ($k in $cursorMappings.Keys ) {
67+ if (-not (Test-Path $cursorMappings [$k ])) { " $k -> $ ( $cursorMappings [$k ]) " }
68+ }
69+ if ($missing ) {
70+ Write-Error " Missing cursor files:`n $ ( $missing -join " `n " ) "
71+ exit 1
4472}
4573
4674Write-Host " Setting system cursor paths..."
4775foreach ($cursor in $cursorMappings.Keys ) {
4876 Set-ItemProperty - Path " HKCU:\Control Panel\Cursors" - Name $cursor - Value $cursorMappings [$cursor ]
4977}
5078
51-
5279# [3] Create and save the "UwU" scheme
5380# -------------------------------------------------
5481Write-Host " Creating the 'UwU' scheme..."
@@ -57,49 +84,36 @@ if (-Not (Test-Path $schemePath)) {
5784 New-Item - Path $schemePath - Force | Out-Null
5885}
5986
87+ # WYCZYŚĆ STARY WPIS (żeby Windows nie trzymał starego, zepsutego stringa)
88+ Remove-ItemProperty - Path $schemePath - Name " UwU" - ErrorAction SilentlyContinue
89+
6090# Windows expects a specific order of these 17 entries
61- $schemeValue = (
62- $cursorMappings [" Arrow" ] + " ," +
63- $cursorMappings [" Help" ] + " ," +
64- $cursorMappings [" AppStarting" ] + " ," +
65- $cursorMappings [" Wait" ] + " ," +
66- $cursorMappings [" Crosshair" ] + " ," +
67- $cursorMappings [" IBeam" ] + " ," +
68- $cursorMappings [" NWPen" ] + " ," +
69- $cursorMappings [" No" ] + " ," +
70- $cursorMappings [" SizeNS" ] + " ," +
71- $cursorMappings [" SizeWE" ] + " ," +
72- $cursorMappings [" SizeNWSE" ] + " ," +
73- $cursorMappings [" SizeNESW" ] + " ," +
74- $cursorMappings [" SizeAll" ] + " ," +
75- $cursorMappings [" UpArrow" ] + " ," +
76- $cursorMappings [" Hand" ] + " ," +
77- $cursorMappings [" Pin" ] + " ," +
78- $cursorMappings [" Person" ]
91+ $order = @ (
92+ " Arrow" , " Help" , " AppStarting" , " Wait" , " Crosshair" , " IBeam" , " NWPen" , " No" ,
93+ " SizeNS" , " SizeWE" , " SizeNWSE" , " SizeNESW" , " SizeAll" , " UpArrow" , " Hand" , " Pin" , " Person"
7994)
8095
96+ # IMPORTANT: Do NOT quote paths in Schemes value. Windows may treat quotes as part of the path.
97+ $schemeValue = ($order | ForEach-Object { $cursorMappings [$_ ] }) -join " ,"
8198Set-ItemProperty - Path $schemePath - Name " UwU" - Value $schemeValue
8299
83- # Set the active scheme to "UwU"
100+ # Set active scheme to "UwU" (use reg.exe for default value reliability)
84101Write-Host " Activating the 'UwU' scheme..."
85- Set-ItemProperty - Path " HKCU:\Control Panel\Cursors" - Name " (Default)" - Value " UwU"
86-
102+ reg.exe add " HKCU\Control Panel\Cursors" / ve / d " UwU" / f | Out-Null
87103
88- # [4] Re-sync with the UI (sometimes not necessary, but safer)
104+ # [4] Re-sync with the UI (safer)
89105# -------------------------------------------------
90106Write-Host " Synchronizing cursor settings again..."
91107foreach ($cursor in $cursorMappings.Keys ) {
92108 Set-ItemProperty - Path " HKCU:\Control Panel\Cursors" - Name $cursor - Value $cursorMappings [$cursor ]
93109}
94110
95-
96111# [5] Refresh settings – multiple variants
97112# -------------------------------------------------
98113Write-Host " Refreshing cursor settings (rundll32)..."
99114Rundll32.exe user32.dll, UpdatePerUserSystemParameters
100115
101- # --- [Optional 1 - But here we keep it active] Stronger refresh via P/Invoke SPI_SETCURSORS ---
102- # This forces a more thorough system update on some machines
116+ # Stronger refresh via P/Invoke SPI_SETCURSORS
103117Add-Type - TypeDefinition @"
104118using System;
105119using System.Runtime.InteropServices;
@@ -110,26 +124,20 @@ public class NativeMethods {
110124
111125 public static bool RefreshCursors() {
112126 // SPI_SETCURSORS = 0x57
113- // SPIF_SENDWININICHANGE = 0x02 (sends a system-wide notification)
127+ // SPIF_SENDWININICHANGE = 0x02
114128 return SystemParametersInfo(0x57, 0, null, 0x02);
115129 }
116130}
117- "@
131+ "@ | Out-Null
118132
119133Write-Host " Refreshing cursor settings (SPI_SETCURSORS)..."
120- [NativeMethods ]::RefreshCursors()
121-
122-
123- # --- [Optional 2] Opening the Mouse Control Panel window ---
124- # Sometimes just opening the mouse control panel helps Windows
125- # notice the new scheme (instead of showing None).
126- Write-Host " Opening Control Panel (optional)..."
127- Start-Process " rundll32.exe" - ArgumentList " shell32.dll,Control_RunDLL main.cpl @0,1"
128-
129- # --- [Optional 3] A short pause and another rundll32, if needed ---
130- # Start-Sleep -Seconds 3
131- # Rundll32.exe user32.dll, UpdatePerUserSystemParameters
134+ [NativeMethods ]::RefreshCursors() | Out-Null
132135
136+ # Optional: open Mouse Control Panel
137+ if ($OpenControlPanel ) {
138+ Write-Host " Opening Control Panel (optional)..."
139+ Start-Process " rundll32.exe" - ArgumentList " shell32.dll,Control_RunDLL main.cpl @0,1"
140+ }
133141
134142# [6] Final message
135143# -------------------------------------------------
0 commit comments