Files
GamesDows/blackscreenoverlay.ps1
2025-10-17 17:03:30 -07:00

422 lines
16 KiB
PowerShell

#Requires -RunAsAdministrator
<#
.SYNOPSIS
Installs black screen overlay to hide Windows logon animations.
.DESCRIPTION
Creates and installs a fullscreen black overlay that covers the logon UI
animations, combined with registry tweaks for maximum suppression.
The overlay automatically dismisses when the desktop shell loads.
.NOTES
- Requires Administrator privileges
- Creates overlay executable and scheduled task
- Combines with registry animation suppression
- Completely safe - no system file modifications
#>
function Write-Success { param($msg) Write-Host $msg -ForegroundColor Green }
function Write-Info { param($msg) Write-Host $msg -ForegroundColor Cyan }
function Write-Warning { param($msg) Write-Host $msg -ForegroundColor Yellow }
function Write-Failure { param($msg) Write-Host $msg -ForegroundColor Red }
Write-Info "`n=== BLACK SCREEN OVERLAY INSTALLER ===`n"
# Check for admin rights
if (-NOT ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) {
Write-Failure "This script requires Administrator privileges!"
exit 1
}
$installPath = "$env:ProgramData\LogonOverlay"
$exePath = "$installPath\LogonOverlay.exe"
$csPath = "$installPath\LogonOverlay.cs"
# Create installation directory
Write-Info "[1] Creating installation directory..."
if (-not (Test-Path $installPath)) {
New-Item -Path $installPath -ItemType Directory -Force | Out-Null
}
Write-Success " [✓] Directory: $installPath"
# Create the C# overlay program source
Write-Info "`n[2] Creating black screen overlay program..."
$csharpCode = @'
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Drawing;
using System.Diagnostics;
using System.Threading;
using System.Linq;
namespace LogonOverlay
{
public class OverlayForm : Form
{
[DllImport("user32.dll")]
private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);
[DllImport("user32.dll")]
private static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
[DllImport("user32.dll")]
private static extern int GetWindowLong(IntPtr hWnd, int nIndex);
private static readonly IntPtr HWND_TOPMOST = new IntPtr(-1);
private const uint SWP_NOSIZE = 0x0001;
private const uint SWP_NOMOVE = 0x0002;
private const uint SWP_SHOWWINDOW = 0x0040;
private const int GWL_EXSTYLE = -20;
private const int WS_EX_TOOLWINDOW = 0x00000080;
private const int WS_EX_NOACTIVATE = 0x08000000;
private System.Windows.Forms.Timer checkTimer;
private DateTime startTime;
public OverlayForm()
{
// Set up form properties
this.FormBorderStyle = FormBorderStyle.None;
this.WindowState = FormWindowState.Maximized;
this.BackColor = Color.Black;
this.TopMost = true;
this.ShowInTaskbar = false;
this.StartPosition = FormStartPosition.Manual;
// Calculate bounds to cover ALL screens (handles both horizontal and vertical layouts)
Rectangle totalBounds = Screen.AllScreens
.Select(s => s.Bounds)
.Aggregate((current, next) => Rectangle.Union(current, next));
this.Location = new Point(totalBounds.X, totalBounds.Y);
this.Size = new Size(totalBounds.Width, totalBounds.Height);
startTime = DateTime.Now;
}
protected override void OnShown(EventArgs e)
{
base.OnShown(e);
// Set extended window styles to keep it on top and prevent activation
int exStyle = GetWindowLong(this.Handle, GWL_EXSTYLE);
SetWindowLong(this.Handle, GWL_EXSTYLE, exStyle | WS_EX_TOOLWINDOW | WS_EX_NOACTIVATE);
// Force topmost
SetWindowPos(this.Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
// Start monitoring for explorer.exe
checkTimer = new System.Windows.Forms.Timer();
checkTimer.Interval = 100; // Check every 100ms
checkTimer.Tick += CheckForExplorer;
checkTimer.Start();
}
private void CheckForExplorer(object sender, EventArgs e)
{
// Check if explorer.exe is running
Process[] explorerProcesses = Process.GetProcessesByName("explorer");
// Also check for timeout (max 10 seconds)
TimeSpan elapsed = DateTime.Now - startTime;
if (explorerProcesses.Length > 0 || elapsed.TotalSeconds > 10)
{
// Give explorer more time to fully render (1000ms for slower systems)
Thread.Sleep(1000);
checkTimer.Stop();
this.Close();
Application.Exit();
}
}
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle |= WS_EX_TOOLWINDOW | WS_EX_NOACTIVATE;
return cp;
}
}
protected override bool ShowWithoutActivation
{
get { return true; }
}
}
static class Program
{
[STAThread]
static void Main()
{
// Check if we're in the logon session
// Only run if explorer.exe is NOT already running
Process[] explorerProcesses = Process.GetProcessesByName("explorer");
if (explorerProcesses.Length > 0)
{
// Explorer already running, don't show overlay
return;
}
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new OverlayForm());
}
}
}
'@
# Save C# source file
$csharpCode | Out-File -FilePath $csPath -Encoding UTF8 -Force
# Find csc.exe for better compilation control
Write-Info " Locating C# compiler..."
$cscPath = $null
# Try multiple .NET Framework versions
$frameworkPaths = @(
"${env:SystemRoot}\Microsoft.NET\Framework64\v4.0.30319\csc.exe",
"${env:SystemRoot}\Microsoft.NET\Framework\v4.0.30319\csc.exe",
"${env:SystemRoot}\Microsoft.NET\Framework64\v3.5\csc.exe",
"${env:SystemRoot}\Microsoft.NET\Framework\v3.5\csc.exe"
)
foreach ($path in $frameworkPaths) {
if (Test-Path $path) {
$cscPath = $path
break
}
}
if ($cscPath) {
Write-Success " [✓] Using csc.exe: $cscPath"
Write-Info " Compiling overlay executable..."
# Compile with csc.exe for better error handling
$compileArgs = @(
"/target:winexe",
"/out:$exePath",
"/reference:System.Windows.Forms.dll",
"/reference:System.Drawing.dll",
"/reference:System.Core.dll",
"/reference:System.Linq.dll",
"/nologo",
"/optimize+",
$csPath
)
$compileOutput = & $cscPath $compileArgs 2>&1
if ($LASTEXITCODE -ne 0) {
Write-Failure " [✗] Compilation failed:"
Write-Host $compileOutput -ForegroundColor Red
exit 1
}
Write-Success " [✓] Compilation successful using csc.exe"
} else {
# Fallback to Add-Type
Write-Warning " [!] csc.exe not found, using Add-Type fallback"
Write-Info " Compiling overlay executable..."
try {
Add-Type -TypeDefinition $csharpCode -ReferencedAssemblies @(
'System.Windows.Forms',
'System.Drawing',
'System.Core',
'System.Linq'
) -OutputAssembly $exePath -OutputType WindowsApplication -ErrorAction Stop
Write-Success " [✓] Compilation successful using Add-Type"
} catch {
Write-Failure " [✗] Failed to compile overlay program: $($_.Exception.Message)"
exit 1
}
}
if (-not (Test-Path $exePath)) {
Write-Failure " [✗] Executable was not created!"
exit 1
}
Write-Success " [✓] Overlay program created: $exePath"
# Set file permissions (only SYSTEM and Admins)
Write-Info "`n[3] Setting security permissions..."
try {
$acl = Get-Acl $exePath
$acl.SetAccessRuleProtection($true, $false)
$adminRule = New-Object System.Security.AccessControl.FileSystemAccessRule(
"BUILTIN\Administrators", "FullControl", "Allow"
)
$systemRule = New-Object System.Security.AccessControl.FileSystemAccessRule(
"NT AUTHORITY\SYSTEM", "FullControl", "Allow"
)
$acl.SetAccessRule($adminRule)
$acl.SetAccessRule($systemRule)
Set-Acl $exePath $acl
Write-Success " [✓] Security permissions configured"
} catch {
Write-Warning " [!] Could not set permissions: $($_.Exception.Message)"
}
# Create scheduled task to run at system startup (before logon)
Write-Info "`n[4] Creating scheduled task..."
$taskName = "LogonOverlayBlackScreen"
$taskPath = "\Microsoft\Windows\Shell\"
# Remove existing task if present
$existingTask = Get-ScheduledTask -TaskName $taskName -TaskPath $taskPath -ErrorAction SilentlyContinue
if ($existingTask) {
Unregister-ScheduledTask -TaskName $taskName -TaskPath $taskPath -Confirm:$false
}
try {
# Create action
$action = New-ScheduledTaskAction -Execute $exePath
# Create trigger - At system startup
$trigger = New-ScheduledTaskTrigger -AtStartup
# Create principal - Run as SYSTEM with highest privileges
$principal = New-ScheduledTaskPrincipal -UserId "NT AUTHORITY\SYSTEM" -LogonType ServiceAccount -RunLevel Highest
# Create settings - optimized for laptops and priority execution
$settings = New-ScheduledTaskSettingsSet `
-AllowStartIfOnBatteries `
-DontStopIfGoingOnBatteries `
-DontStopOnIdleEnd `
-ExecutionTimeLimit (New-TimeSpan -Minutes 1) `
-Priority 0 `
-StartWhenAvailable `
-RestartCount 3 `
-RestartInterval (New-TimeSpan -Minutes 1)
# Register task
Register-ScheduledTask `
-TaskName $taskName `
-TaskPath $taskPath `
-Action $action `
-Trigger $trigger `
-Principal $principal `
-Settings $settings `
-Force | Out-Null
Write-Success " [✓] Scheduled task created: $taskPath$taskName"
Write-Info " Priority: Highest (0)"
Write-Info " Battery: Will run on battery power"
Write-Info " Restart: Auto-restart on failure (3 attempts)"
} catch {
Write-Failure " [✗] Failed to create scheduled task: $($_.Exception.Message)"
exit 1
}
# Apply registry tweaks for maximum suppression
Write-Info "`n[5] Applying registry animation suppression..."
function Set-RegValue {
param($Path, $Name, $Value, $Type = "DWord")
try {
if (-not (Test-Path $Path)) { New-Item -Path $Path -Force | Out-Null }
New-ItemProperty -Path $Path -Name $Name -Value $Value -PropertyType $Type -Force | Out-Null
return $true
} catch {
return $false
}
}
# Core suppression keys
$suppressionKeys = @(
@{Path="HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System"; Name="EnableFirstLogonAnimation"; Value=0},
@{Path="HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System"; Name="DisableAnimations"; Value=1},
@{Path="HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\LogonUI"; Name="AnimationDisabled"; Value=1},
@{Path="HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\LogonUI"; Name="EnableTransitions"; Value=0},
@{Path="HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System"; Name="DisableStatusMessages"; Value=1},
@{Path="HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon"; Name="DelayedDesktopSwitchTimeout"; Value=0},
@{Path="HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon"; Name="AutoLogonDelay"; Value=0}
)
$appliedCount = 0
foreach ($key in $suppressionKeys) {
if (Set-RegValue -Path $key.Path -Name $key.Name -Value $key.Value) {
$appliedCount++
}
}
Write-Success " [✓] Applied $appliedCount registry tweaks"
# Summary
Write-Info "`n" + "="*70
Write-Success "`n✓ BLACK SCREEN OVERLAY INSTALLED SUCCESSFULLY!"
Write-Info "="*70
Write-Host "`n📋 WHAT WAS INSTALLED:" -ForegroundColor Cyan
Write-Host " ✓ C# source code: $csPath"
Write-Host " ✓ Overlay executable: $exePath"
Write-Host " ✓ Scheduled task: Runs at system startup (highest priority)"
Write-Host " ✓ Registry tweaks: Core animation suppression applied"
Write-Host " ✓ Security: SYSTEM-level execution with highest priority"
Write-Host "`n💡 HOW IT WORKS:" -ForegroundColor Green
Write-Host " 1. At boot, black overlay launches before LogonUI"
Write-Host " 2. Covers ALL screens with solid black window (multi-monitor aware)"
Write-Host " 3. Uses Rectangle.Union for proper multi-monitor coverage"
Write-Host " 4. Stays on top of all animations and UI elements"
Write-Host " 5. Monitors for explorer.exe (desktop shell)"
Write-Host " 6. Waits 1000ms after shell detected (slow system support)"
Write-Host " 7. Dismisses itself gracefully"
Write-Host " 8. Result: Completely black transition to desktop"
Write-Host "`n🎯 WHAT YOU'LL SEE:" -ForegroundColor Green
Write-Host " • Windows logo during boot (normal)"
Write-Host " • Solid black screen (instead of animations)"
Write-Host " • Your desktop appears smoothly"
Write-Host " • NO profile picture, username, spinning wheel, or status text"
Write-Host "`n🖥️ MULTI-MONITOR SUPPORT:" -ForegroundColor Green
Write-Host " • Covers horizontal screen layouts"
Write-Host " • Covers vertical screen layouts"
Write-Host " • Covers mixed/irregular layouts"
Write-Host " • Uses Rectangle.Union for proper bounds calculation"
Write-Warning "`n⚠️ IMPORTANT NOTES:"
Write-Host " • Overlay has 10-second timeout (safety mechanism)"
Write-Host " • 1000ms delay after explorer.exe for slow systems"
Write-Host " • Auto-restart on failure (3 attempts)"
Write-Host " • Works with auto-login and password-protected accounts"
Write-Host " • Battery-friendly (runs on laptop battery)"
Write-Host " • Restart required to see it in action"
Write-Success "`n✅ ADVANTAGES:"
Write-Host " • Compiled with csc.exe for better compatibility"
Write-Host " • Fallback to Add-Type if csc.exe unavailable"
Write-Host " • No system file modifications"
Write-Host " • No security compromises"
Write-Host " • Update-proof (survives all Windows Updates)"
Write-Host " • Fully reversible (use uninstall script)"
Write-Host " • Zero performance impact"
Write-Info "`n📝 TO UNINSTALL:"
Write-Host " Run the companion uninstall script to completely remove"
Write-Host " all components and revert registry changes."
Write-Info "`n" + "="*70
$restart = Read-Host "`nRestart computer now to test? (Y/N)"
if ($restart -eq 'Y') {
Write-Info "Restarting in 10 seconds... (Ctrl+C to cancel)"
Start-Sleep -Seconds 10
Restart-Computer -Force
} else {
Write-Warning "`nRestart your computer to see the black screen overlay in action!`n"
}