J2897

Uninstall-n8n-Nodejs-Thoroughly.ps1

Dec 10th, 2025
150
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. <#
  2. .SYNOPSIS
  3.     Thorough removal of Node.js, npm, global modules, shims, and n8n.
  4.  
  5. .DESCRIPTION
  6.     Removes all Node.js and npm-related components from Windows.
  7.     Backs up ~/.n8n before removing it.
  8.     Safe to run repeatedly. Fully idempotent.
  9. #>
  10.  
  11. $ErrorActionPreference = "Stop"
  12.  
  13. Write-Host "=== Full Uninstall: Node.js, npm, n8n ==="
  14.  
  15. # ---------------------------------------------------------------
  16. # PRE-CLEANUP STATE REPORT
  17. # ---------------------------------------------------------------
  18. function Get-SystemState {
  19.  
  20.     Write-Host ""
  21.     Write-Host "=== System State Before Cleanup ==="
  22.  
  23.     # 1. Node.js MSI entries
  24.     $unKeys = @(
  25.         "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*",
  26.         "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*"
  27.     )
  28.  
  29.     $msiEntries = Get-ItemProperty -Path $unKeys -ErrorAction SilentlyContinue |
  30.                   Where-Object { $_.DisplayName -like "*Node.js*" }
  31.  
  32.     Write-Host "Node MSI entries: $($msiEntries.Count)"
  33.  
  34.     # 2. Node folders
  35.     $nodeFolders = @(
  36.         "C:\Program Files\nodejs",
  37.         "C:\Program Files (x86)\nodejs",
  38.         "$env:LOCALAPPDATA\Programs\nodejs"
  39.     ) | Where-Object { Test-Path $_ }
  40.  
  41.     Write-Host "Node folders: $($nodeFolders.Count)"
  42.  
  43.     # 3. npm folders
  44.     $npmFolders = @(
  45.         "$env:APPDATA\npm",
  46.         "$env:APPDATA\npm-cache",
  47.         "$env:USERPROFILE\.npm"
  48.     ) | Where-Object { Test-Path $_ }
  49.  
  50.     Write-Host "npm folders: $($npmFolders.Count)"
  51.  
  52.     # 4. Shims in PATH
  53.     $shimNames = @("npm.cmd","npm.ps1","npx.cmd","npx.ps1","corepack.cmd","corepack.ps1","n8n.cmd","n8n.ps1")
  54.     $shimHits = @()
  55.  
  56.     foreach ($dir in ($env:PATH -split ";")) {
  57.         foreach ($name in $shimNames) {
  58.             $cand = Join-Path $dir $name
  59.             if (Test-Path $cand) { $shimHits += $cand }
  60.         }
  61.     }
  62.  
  63.     Write-Host "Shims in PATH: $($shimHits.Count)"
  64.  
  65.     # 5. Stray executables
  66.     $exeNames = @("node","npm","npx","corepack","n8n")
  67.     $exeHits = @()
  68.  
  69.     foreach ($name in $exeNames) {
  70.         $cmd = Get-Command $name -ErrorAction SilentlyContinue
  71.         if ($cmd) { $exeHits += $cmd.Source }
  72.     }
  73.  
  74.     Write-Host "Stray executables: $($exeHits.Count)"
  75.  
  76.     # 6. .n8n folder
  77.     $n8nDir = Join-Path $env:USERPROFILE ".n8n"
  78.     $exists = Test-Path $n8nDir
  79.     Write-Host ".n8n directory: $([bool]$exists)"
  80.  
  81.     Write-Host "==================================="
  82.  
  83.     # If nothing requires removal, exit immediately.
  84.     if (
  85.         $msiEntries.Count -eq 0 -and
  86.         $nodeFolders.Count -eq 0 -and
  87.         $npmFolders.Count -eq 0 -and
  88.         $shimHits.Count -eq 0 -and
  89.         $exeHits.Count -eq 0 -and
  90.         -not (Test-Path $n8nDir)
  91.     ) {
  92.         Write-Host "Nothing to remove. System is already clean."
  93.         exit
  94.     }
  95.  
  96.     # Otherwise ask user before performing destructive cleanup.
  97.     $choice = Read-Host "Proceed with aggressive cleanup? (Y/N)"
  98.     if ($choice -notmatch "^[Yy]$") {
  99.         Write-Host "Aborted by user."
  100.         exit
  101.     }
  102. }
  103.  
  104. # Run diagnostic before uninstall begins
  105. Get-SystemState
  106.  
  107. # ---------------------------------------------------------------
  108. # BACKUP .n8n BEFORE REMOVAL
  109. # ---------------------------------------------------------------
  110. function Backup-N8N {
  111.     $n8nDir = Join-Path $env:USERPROFILE ".n8n"
  112.     if (-not (Test-Path $n8nDir)) {
  113.         Write-Host "No .n8n directory found. Skipping backup."
  114.         return
  115.     }
  116.  
  117.     Write-Host "Backing up .n8n before removal..."
  118.  
  119.     $timestamp  = Get-Date -Format "yyyy-MM-dd_HH-mm-ss"
  120.     $backupRoot = Join-Path $env:USERPROFILE "Desktop\n8n-backups"
  121.     $zipPath    = Join-Path $backupRoot "n8n-backup-$timestamp.zip"
  122.     $tempCopy   = Join-Path $env:TEMP "n8n-backup-$timestamp"
  123.  
  124.     if (-not (Test-Path $backupRoot)) {
  125.         New-Item -ItemType Directory -Path $backupRoot | Out-Null
  126.     }
  127.  
  128.     if (Test-Path $tempCopy) {
  129.         Remove-Item $tempCopy -Recurse -Force
  130.     }
  131.     New-Item -ItemType Directory -Path $tempCopy | Out-Null
  132.  
  133.     try {
  134.         Copy-Item "$n8nDir\*" $tempCopy -Recurse -Force
  135.         Compress-Archive -Path $tempCopy -DestinationPath $zipPath -Force
  136.     }
  137.     finally {
  138.         if (Test-Path $tempCopy) {
  139.             Remove-Item $tempCopy -Recurse -Force
  140.         }
  141.     }
  142.  
  143.     $sizeMB = [math]::Round((Get-Item $zipPath).Length / 1MB, 1)
  144.     Write-Host "Backup complete ($sizeMB MB) --> $zipPath"
  145.  
  146.     Write-Host "Removing .n8n directory..."
  147.     Remove-Item $n8nDir -Recurse -Force -ErrorAction SilentlyContinue
  148. }
  149.  
  150. # ---------------------------------------------------------------
  151. # REMOVE n8n (GLOBAL MODULE + SHIMS)
  152. # ---------------------------------------------------------------
  153. function Remove-N8N {
  154.     Write-Host ""
  155.     Write-Host "Removing n8n..."
  156.  
  157.     $npm = Get-Command npm -ErrorAction SilentlyContinue
  158.     if ($npm) {
  159.         try { npm uninstall -g n8n 2>$null } catch {}
  160.     }
  161.  
  162.     $paths = @(
  163.         (Join-Path $env:APPDATA "npm\node_modules\n8n")
  164.         (Join-Path $env:APPDATA "npm\n8n.cmd")
  165.         (Join-Path $env:APPDATA "npm\n8n.ps1")
  166.     )
  167.  
  168.     foreach ($p in $paths) {
  169.         if (Test-Path $p) {
  170.             Write-Host "Deleting: $p"
  171.             Remove-Item $p -Recurse -Force -ErrorAction SilentlyContinue
  172.         }
  173.     }
  174.  
  175.     Write-Host "n8n removal complete."
  176. }
  177.  
  178. # ---------------------------------------------------------------
  179. # REMOVE NODE.JS MSI INSTALLATIONS
  180. # ---------------------------------------------------------------
  181. function Remove-NodeMSI {
  182.     Write-Host ""
  183.     Write-Host "Removing Node.js MSI installations..."
  184.  
  185.     $unKeys = @(
  186.         "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*",
  187.         "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*"
  188.     )
  189.  
  190.     $products = Get-ItemProperty -Path $unKeys -ErrorAction SilentlyContinue |
  191.         Where-Object { $_.DisplayName -like "*Node.js*" }
  192.  
  193.     foreach ($p in $products) {
  194.         $u = $p.UninstallString
  195.         if ($u -match "{[0-9A-Fa-f\-]+}") {
  196.             $guid = [regex]::Match($u, "{[0-9A-Fa-f\-]+}").Value
  197.             Write-Host "Uninstalling Node.js MSI: $guid"
  198.             Start-Process msiexec.exe -Wait -ArgumentList "/x $guid /quiet /norestart"
  199.         }
  200.         elseif ($u) {
  201.             Write-Host "Running uninstall command: $u"
  202.             Start-Process cmd.exe -Wait -ArgumentList "/c `"$u`""
  203.         }
  204.     }
  205.  
  206.     Write-Host "Node MSI removal complete."
  207. }
  208.  
  209. # ---------------------------------------------------------------
  210. # REMOVE ALL NODE AND NPM FOLDERS
  211. # ---------------------------------------------------------------
  212. function Remove-NodeFolders {
  213.     Write-Host ""
  214.     Write-Host "Removing Node.js and npm folders..."
  215.  
  216.     $folders = @(
  217.         "C:\Program Files\nodejs",
  218.         "C:\Program Files (x86)\nodejs",
  219.         "$env:LOCALAPPDATA\Programs\nodejs",
  220.         "$env:APPDATA\npm",
  221.         "$env:APPDATA\npm-cache",
  222.         "$env:USERPROFILE\.npm",
  223.         "$env:USERPROFILE\.node-gyp",
  224.         "$env:USERPROFILE\.node_repl_history"
  225.     )
  226.  
  227.     foreach ($f in $folders) {
  228.         if (Test-Path $f) {
  229.             Write-Host "Deleting folder: $f"
  230.             Remove-Item $f -Recurse -Force -ErrorAction SilentlyContinue
  231.         }
  232.     }
  233.  
  234.     Write-Host "Folder cleanup complete."
  235. }
  236.  
  237. # ---------------------------------------------------------------
  238. # REMOVE SHIMS (npm, npx, corepack, n8n)
  239. # ---------------------------------------------------------------
  240. function Remove-Shims {
  241.     Write-Host ""
  242.     Write-Host "Removing npm, npx, corepack, and n8n shims..."
  243.  
  244.     $names = @(
  245.         "npm.cmd","npm.ps1",
  246.         "npx.cmd","npx.ps1",
  247.         "corepack.cmd","corepack.ps1",
  248.         "n8n.cmd","n8n.ps1"
  249.     )
  250.  
  251.     $searchDirs = ($env:PATH -split ";")
  252.  
  253.     foreach ($dir in $searchDirs) {
  254.         foreach ($name in $names) {
  255.             $cand = Join-Path $dir $name
  256.             if (Test-Path $cand) {
  257.                 Write-Host "Removing shim: $cand"
  258.                 Remove-Item $cand -Force -ErrorAction SilentlyContinue
  259.             }
  260.         }
  261.     }
  262. }
  263.  
  264. # ---------------------------------------------------------------
  265. # CLEAN PATH ENTRIES
  266. # ---------------------------------------------------------------
  267. function Remove-PathEntries {
  268.     Write-Host ""
  269.     Write-Host "Cleaning PATH entries..."
  270.  
  271.     $patterns = @("nodejs","npm","node","corepack","n8n")
  272.  
  273.     $clean = {
  274.         param($scope)
  275.  
  276.         $path = [Environment]::GetEnvironmentVariable("Path",$scope)
  277.         if (-not $path) { return }
  278.  
  279.         $parts = $path -split ";"
  280.         $filtered = $parts | Where-Object {
  281.             $remove = $false
  282.             foreach ($p in $patterns) {
  283.                 if ($_ -match $p) { $remove = $true }
  284.             }
  285.             -not $remove
  286.         }
  287.  
  288.         $new = ($filtered -join ";")
  289.         [Environment]::SetEnvironmentVariable("Path",$new,$scope)
  290.         Write-Host "Cleaned $scope PATH."
  291.     }
  292.  
  293.     $clean.Invoke("Machine")
  294.     $clean.Invoke("User")
  295.  
  296.     $env:PATH = (
  297.         [Environment]::GetEnvironmentVariable("Path","Machine") + ";" +
  298.         [Environment]::GetEnvironmentVariable("Path","User")
  299.     )
  300. }
  301.  
  302. # ---------------------------------------------------------------
  303. # REMOVE STRAY EXECUTABLES ANYWHERE IN PATH
  304. # ---------------------------------------------------------------
  305. function Remove-StrayExecutables {
  306.     Write-Host ""
  307.     Write-Host "Checking for leftover executables..."
  308.  
  309.     $names = @("node","npm","npx","corepack","n8n")
  310.  
  311.     foreach ($exe in $names) {
  312.         $cmd = Get-Command $exe -ErrorAction SilentlyContinue
  313.         if ($cmd) {
  314.             Write-Host "Deleting stray executable: $($cmd.Source)"
  315.             try { Remove-Item $cmd.Source -Force -ErrorAction SilentlyContinue } catch {}
  316.         }
  317.     }
  318. }
  319.  
  320. # ---------------------------------------------------------------
  321. # EXECUTE ALL STEPS
  322. # ---------------------------------------------------------------
  323. Backup-N8N
  324. Remove-N8N
  325. Remove-NodeMSI
  326. Remove-NodeFolders
  327. Remove-Shims
  328. Remove-PathEntries
  329. Remove-StrayExecutables
  330.  
  331. Write-Host ""
  332. Write-Host "All components removed."
  333. Write-Host "System is clean and ready for fresh installation tests."
  334.  
Advertisement