Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <#
- .SYNOPSIS
- Thorough removal of Node.js, npm, global modules, shims, and n8n.
- .DESCRIPTION
- Removes all Node.js and npm-related components from Windows.
- Backs up ~/.n8n before removing it.
- Safe to run repeatedly. Fully idempotent.
- #>
- $ErrorActionPreference = "Stop"
- Write-Host "=== Full Uninstall: Node.js, npm, n8n ==="
- # ---------------------------------------------------------------
- # PRE-CLEANUP STATE REPORT
- # ---------------------------------------------------------------
- function Get-SystemState {
- Write-Host ""
- Write-Host "=== System State Before Cleanup ==="
- # 1. Node.js MSI entries
- $unKeys = @(
- "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*",
- "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*"
- )
- $msiEntries = Get-ItemProperty -Path $unKeys -ErrorAction SilentlyContinue |
- Where-Object { $_.DisplayName -like "*Node.js*" }
- Write-Host "Node MSI entries: $($msiEntries.Count)"
- # 2. Node folders
- $nodeFolders = @(
- "C:\Program Files\nodejs",
- "C:\Program Files (x86)\nodejs",
- "$env:LOCALAPPDATA\Programs\nodejs"
- ) | Where-Object { Test-Path $_ }
- Write-Host "Node folders: $($nodeFolders.Count)"
- # 3. npm folders
- $npmFolders = @(
- "$env:APPDATA\npm",
- "$env:APPDATA\npm-cache",
- "$env:USERPROFILE\.npm"
- ) | Where-Object { Test-Path $_ }
- Write-Host "npm folders: $($npmFolders.Count)"
- # 4. Shims in PATH
- $shimNames = @("npm.cmd","npm.ps1","npx.cmd","npx.ps1","corepack.cmd","corepack.ps1","n8n.cmd","n8n.ps1")
- $shimHits = @()
- foreach ($dir in ($env:PATH -split ";")) {
- foreach ($name in $shimNames) {
- $cand = Join-Path $dir $name
- if (Test-Path $cand) { $shimHits += $cand }
- }
- }
- Write-Host "Shims in PATH: $($shimHits.Count)"
- # 5. Stray executables
- $exeNames = @("node","npm","npx","corepack","n8n")
- $exeHits = @()
- foreach ($name in $exeNames) {
- $cmd = Get-Command $name -ErrorAction SilentlyContinue
- if ($cmd) { $exeHits += $cmd.Source }
- }
- Write-Host "Stray executables: $($exeHits.Count)"
- # 6. .n8n folder
- $n8nDir = Join-Path $env:USERPROFILE ".n8n"
- $exists = Test-Path $n8nDir
- Write-Host ".n8n directory: $([bool]$exists)"
- Write-Host "==================================="
- # If nothing requires removal, exit immediately.
- if (
- $msiEntries.Count -eq 0 -and
- $nodeFolders.Count -eq 0 -and
- $npmFolders.Count -eq 0 -and
- $shimHits.Count -eq 0 -and
- $exeHits.Count -eq 0 -and
- -not (Test-Path $n8nDir)
- ) {
- Write-Host "Nothing to remove. System is already clean."
- exit
- }
- # Otherwise ask user before performing destructive cleanup.
- $choice = Read-Host "Proceed with aggressive cleanup? (Y/N)"
- if ($choice -notmatch "^[Yy]$") {
- Write-Host "Aborted by user."
- exit
- }
- }
- # Run diagnostic before uninstall begins
- Get-SystemState
- # ---------------------------------------------------------------
- # BACKUP .n8n BEFORE REMOVAL
- # ---------------------------------------------------------------
- function Backup-N8N {
- $n8nDir = Join-Path $env:USERPROFILE ".n8n"
- if (-not (Test-Path $n8nDir)) {
- Write-Host "No .n8n directory found. Skipping backup."
- return
- }
- Write-Host "Backing up .n8n before removal..."
- $timestamp = Get-Date -Format "yyyy-MM-dd_HH-mm-ss"
- $backupRoot = Join-Path $env:USERPROFILE "Desktop\n8n-backups"
- $zipPath = Join-Path $backupRoot "n8n-backup-$timestamp.zip"
- $tempCopy = Join-Path $env:TEMP "n8n-backup-$timestamp"
- if (-not (Test-Path $backupRoot)) {
- New-Item -ItemType Directory -Path $backupRoot | Out-Null
- }
- if (Test-Path $tempCopy) {
- Remove-Item $tempCopy -Recurse -Force
- }
- New-Item -ItemType Directory -Path $tempCopy | Out-Null
- try {
- Copy-Item "$n8nDir\*" $tempCopy -Recurse -Force
- Compress-Archive -Path $tempCopy -DestinationPath $zipPath -Force
- }
- finally {
- if (Test-Path $tempCopy) {
- Remove-Item $tempCopy -Recurse -Force
- }
- }
- $sizeMB = [math]::Round((Get-Item $zipPath).Length / 1MB, 1)
- Write-Host "Backup complete ($sizeMB MB) --> $zipPath"
- Write-Host "Removing .n8n directory..."
- Remove-Item $n8nDir -Recurse -Force -ErrorAction SilentlyContinue
- }
- # ---------------------------------------------------------------
- # REMOVE n8n (GLOBAL MODULE + SHIMS)
- # ---------------------------------------------------------------
- function Remove-N8N {
- Write-Host ""
- Write-Host "Removing n8n..."
- $npm = Get-Command npm -ErrorAction SilentlyContinue
- if ($npm) {
- try { npm uninstall -g n8n 2>$null } catch {}
- }
- $paths = @(
- (Join-Path $env:APPDATA "npm\node_modules\n8n")
- (Join-Path $env:APPDATA "npm\n8n.cmd")
- (Join-Path $env:APPDATA "npm\n8n.ps1")
- )
- foreach ($p in $paths) {
- if (Test-Path $p) {
- Write-Host "Deleting: $p"
- Remove-Item $p -Recurse -Force -ErrorAction SilentlyContinue
- }
- }
- Write-Host "n8n removal complete."
- }
- # ---------------------------------------------------------------
- # REMOVE NODE.JS MSI INSTALLATIONS
- # ---------------------------------------------------------------
- function Remove-NodeMSI {
- Write-Host ""
- Write-Host "Removing Node.js MSI installations..."
- $unKeys = @(
- "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*",
- "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*"
- )
- $products = Get-ItemProperty -Path $unKeys -ErrorAction SilentlyContinue |
- Where-Object { $_.DisplayName -like "*Node.js*" }
- foreach ($p in $products) {
- $u = $p.UninstallString
- if ($u -match "{[0-9A-Fa-f\-]+}") {
- $guid = [regex]::Match($u, "{[0-9A-Fa-f\-]+}").Value
- Write-Host "Uninstalling Node.js MSI: $guid"
- Start-Process msiexec.exe -Wait -ArgumentList "/x $guid /quiet /norestart"
- }
- elseif ($u) {
- Write-Host "Running uninstall command: $u"
- Start-Process cmd.exe -Wait -ArgumentList "/c `"$u`""
- }
- }
- Write-Host "Node MSI removal complete."
- }
- # ---------------------------------------------------------------
- # REMOVE ALL NODE AND NPM FOLDERS
- # ---------------------------------------------------------------
- function Remove-NodeFolders {
- Write-Host ""
- Write-Host "Removing Node.js and npm folders..."
- $folders = @(
- "C:\Program Files\nodejs",
- "C:\Program Files (x86)\nodejs",
- "$env:LOCALAPPDATA\Programs\nodejs",
- "$env:APPDATA\npm",
- "$env:APPDATA\npm-cache",
- "$env:USERPROFILE\.npm",
- "$env:USERPROFILE\.node-gyp",
- "$env:USERPROFILE\.node_repl_history"
- )
- foreach ($f in $folders) {
- if (Test-Path $f) {
- Write-Host "Deleting folder: $f"
- Remove-Item $f -Recurse -Force -ErrorAction SilentlyContinue
- }
- }
- Write-Host "Folder cleanup complete."
- }
- # ---------------------------------------------------------------
- # REMOVE SHIMS (npm, npx, corepack, n8n)
- # ---------------------------------------------------------------
- function Remove-Shims {
- Write-Host ""
- Write-Host "Removing npm, npx, corepack, and n8n shims..."
- $names = @(
- "npm.cmd","npm.ps1",
- "npx.cmd","npx.ps1",
- "corepack.cmd","corepack.ps1",
- "n8n.cmd","n8n.ps1"
- )
- $searchDirs = ($env:PATH -split ";")
- foreach ($dir in $searchDirs) {
- foreach ($name in $names) {
- $cand = Join-Path $dir $name
- if (Test-Path $cand) {
- Write-Host "Removing shim: $cand"
- Remove-Item $cand -Force -ErrorAction SilentlyContinue
- }
- }
- }
- }
- # ---------------------------------------------------------------
- # CLEAN PATH ENTRIES
- # ---------------------------------------------------------------
- function Remove-PathEntries {
- Write-Host ""
- Write-Host "Cleaning PATH entries..."
- $patterns = @("nodejs","npm","node","corepack","n8n")
- $clean = {
- param($scope)
- $path = [Environment]::GetEnvironmentVariable("Path",$scope)
- if (-not $path) { return }
- $parts = $path -split ";"
- $filtered = $parts | Where-Object {
- $remove = $false
- foreach ($p in $patterns) {
- if ($_ -match $p) { $remove = $true }
- }
- -not $remove
- }
- $new = ($filtered -join ";")
- [Environment]::SetEnvironmentVariable("Path",$new,$scope)
- Write-Host "Cleaned $scope PATH."
- }
- $clean.Invoke("Machine")
- $clean.Invoke("User")
- $env:PATH = (
- [Environment]::GetEnvironmentVariable("Path","Machine") + ";" +
- [Environment]::GetEnvironmentVariable("Path","User")
- )
- }
- # ---------------------------------------------------------------
- # REMOVE STRAY EXECUTABLES ANYWHERE IN PATH
- # ---------------------------------------------------------------
- function Remove-StrayExecutables {
- Write-Host ""
- Write-Host "Checking for leftover executables..."
- $names = @("node","npm","npx","corepack","n8n")
- foreach ($exe in $names) {
- $cmd = Get-Command $exe -ErrorAction SilentlyContinue
- if ($cmd) {
- Write-Host "Deleting stray executable: $($cmd.Source)"
- try { Remove-Item $cmd.Source -Force -ErrorAction SilentlyContinue } catch {}
- }
- }
- }
- # ---------------------------------------------------------------
- # EXECUTE ALL STEPS
- # ---------------------------------------------------------------
- Backup-N8N
- Remove-N8N
- Remove-NodeMSI
- Remove-NodeFolders
- Remove-Shims
- Remove-PathEntries
- Remove-StrayExecutables
- Write-Host ""
- Write-Host "All components removed."
- Write-Host "System is clean and ready for fresh installation tests."
Advertisement