' Date: 2025-06-26
' Version: 1.0.0
' License: MIT License
'
' Copyright (c) 2025
'
' Permission is hereby granted, free of charge, to any person obtaining a copy
' of this software and associated documentation files (the "Software"), to deal
' in the Software without restriction, including without limitation the rights
' to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
' copies of the Software, and to permit persons to whom the Software is
' furnished to do so, subject to the following conditions:
'
' The above copyright notice and this permission notice shall be included in all
' copies or substantial portions of the Software.
'
' THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
' IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
' FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
' AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
' LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
' OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
' SOFTWARE.
' Description:
' This VBScript is a wrapper to launch a PowerShell script that installs/is a watcher for exiting SolidWorks.
' It creates a Scheduled Task that runs watcher script at user logon, which activates once SolidWorks is closed.
' The watcher script will automatically deactivate the license.
' It takes a few seconds to detect the shutdown.
' The Activation Wizard will be left on the "Deactivation Successful" page afterwards, so the user can use this as license deactivation confirmation.
' This will not run if Windows is being shut down/crashing while SolidWorks is running however!
' Usage:
' Double-click the VBScript file to run it.
' It will prompt for the main SOLIDWORKS Corp installation folder. Copy paste this.
' Edit pollSeconds and windowDelay in SWActivationWatcher.ps1 if on a slow computer or if you want to speed up the process (then reboot).
Set objShell = CreateObject("Shell.Application")
' Create the PowerShell script alongside the VBScript if it doesn't exist
Set fso = CreateObject("Scripting.FileSystemObject")
' Determine the PowerShell script path based on this VBScript’s folder
Dim scriptFolder
scriptFolder = fso.GetParentFolderName(WScript.ScriptFullName)
psPath = scriptFolder & "\SWActivationWatcher.ps1"
If Not fso.FileExists(psPath) Then
Set file = fso.CreateTextFile(psPath, True)
file.WriteLine "#Requires -RunAsAdministrator"
file.WriteLine "<#"
file.WriteLine ".SYNOPSIS"
file.WriteLine " Installs and runs a watcher to automatically handle the SolidWorks activation prompt on close."
file.WriteLine " This script is self-relocating and designed to be launched by an admin batch file."
file.WriteLine ""
file.WriteLine ".DESCRIPTION"
file.WriteLine " INSTALLER MODE:"
file.WriteLine " - Asks for the main SOLIDWORKS Corp installation folder."
file.WriteLine " - Creates a 'Scripts' subfolder inside the SOLIDWORKS Corp directory."
file.WriteLine " - Copies itself to this new, permanent location."
file.WriteLine " - Creates a Scheduled Task that runs the *copied* script at user logon."
file.WriteLine " - Starts the Scheduled Task immediately after creation."
file.WriteLine ""
file.WriteLine " WATCHER MODE (Executed by the Scheduled Task):"
file.WriteLine " - Runs silently in the background, monitoring for the SolidWorks process to close."
file.WriteLine "#>"
file.WriteLine "[CmdletBinding()]"
file.WriteLine "param ("
file.WriteLine " [string]$RunWatcherWithActivatorPath"
file.WriteLine ")"
file.WriteLine ""
file.WriteLine "# Configuration Parameters"
file.WriteLine "$pollSeconds = 5 # How often to check if SolidWorks is running"
file.WriteLine "$windowDelay = 3 # How long to wait for the activation wizard window to appear"
file.WriteLine ""
file.WriteLine "# --- WATCHER MODE ---"
file.WriteLine "if (-not [string]::IsNullOrEmpty($RunWatcherWithActivatorPath)) {"
file.WriteLine " Add-Type -AssemblyName System.Windows.Forms -ErrorAction SilentlyContinue"
file.WriteLine " Add-Type -TypeDefinition @"""
file.WriteLine " using System;"
file.WriteLine " using System.Runtime.InteropServices;"
file.WriteLine " public static class NativeMethods {"
file.WriteLine " [DllImport(""user32.dll"", SetLastError = false)]"
file.WriteLine " public static extern bool SetForegroundWindow(IntPtr hWnd);"
file.WriteLine ""
file.WriteLine " [DllImport(""user32.dll"", SetLastError = true, CharSet = CharSet.Auto)]"
file.WriteLine " public static extern IntPtr FindWindowEx("
file.WriteLine " IntPtr hwndParent,"
file.WriteLine " IntPtr hwndChildAfter,"
file.WriteLine " string lpszClass,"
file.WriteLine " string lpszWindow);"
file.WriteLine ""
file.WriteLine " [DllImport(""user32.dll"", CharSet = CharSet.Auto)]"
file.WriteLine " public static extern IntPtr SendMessage("
file.WriteLine " IntPtr hWnd,"
file.WriteLine " uint Msg,"
file.WriteLine " IntPtr wParam,"
file.WriteLine " IntPtr lParam);"
file.WriteLine " }"
file.WriteLine """@ -ErrorAction SilentlyContinue"
file.WriteLine ""
file.WriteLine " # Constants"
file.WriteLine " $BM_CLICK = 0x00F5"
file.WriteLine " $swProcessName = 'SLDWORKS'"
file.WriteLine " $activationExe = $RunWatcherWithActivatorPath"
file.WriteLine " # Log file path"
file.WriteLine " $wasRunning = $false"
file.WriteLine ""
file.WriteLine " if (-not (Test-Path $activationExe)) { exit }"
file.WriteLine ""
file.WriteLine " while ($true) {"
file.WriteLine " $running = Get-Process -Name $swProcessName -ErrorAction SilentlyContinue"
file.WriteLine " if (-not $running -and $wasRunning) {"
file.WriteLine " try {"
file.WriteLine " # Launch the GUI wizard"
file.WriteLine " $wizProc = Start-Process -FilePath $activationExe -PassThru"
file.WriteLine " Start-Sleep -Seconds $windowDelay"
file.WriteLine ""
file.WriteLine " # Bring it to foreground (in case it’s hidden behind)"
file.WriteLine " if ($wizProc.MainWindowHandle -ne [IntPtr]::Zero) {"
file.WriteLine " [NativeMethods]::SetForegroundWindow($wizProc.MainWindowHandle) | Out-Null"
file.WriteLine " }"
file.WriteLine ""
file.WriteLine " # Find and click “Next >” twice"
file.WriteLine " for ($i = 1; $i -le 2; $i++) {"
file.WriteLine " $btn = [NativeMethods]::FindWindowEx("
file.WriteLine " $wizProc.MainWindowHandle,"
file.WriteLine " [IntPtr]::Zero,"
file.WriteLine " ""Button"","
file.WriteLine " ""&Next; >"""
file.WriteLine " )"
file.WriteLine " if ($btn -eq [IntPtr]::Zero) {"
file.WriteLine " throw ""Could not find 'Next >' button on attempt #$i"""
file.WriteLine " }"
file.WriteLine " [NativeMethods]::SendMessage($btn, $BM_CLICK, [IntPtr]::Zero, [IntPtr]::Zero) | Out-Null"
file.WriteLine " Start-Sleep -Milliseconds 100"
file.WriteLine " }"
file.WriteLine " }"
file.WriteLine " catch {"
file.WriteLine " Add-Content -Path ""$env:ProgramData\SWActivationWatcher.log"" `"
file.WriteLine " -Value ""$(Get-Date -Format o) ERROR: $($_.Exception.Message)"""
file.WriteLine " }"
file.WriteLine " }"
file.WriteLine ""
file.WriteLine " $wasRunning = [bool]$running"
file.WriteLine " Start-Sleep -Seconds $pollSeconds"
file.WriteLine " }"
file.WriteLine " exit"
file.WriteLine "}"
file.WriteLine ""
file.WriteLine "# --- INSTALLER MODE ---"
file.WriteLine "if (-NOT ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] ""Administrator"")) {"
file.WriteLine " Write-Host ""ERROR: This script must be run with Administrator rights."" -ForegroundColor Red"
file.WriteLine " Write-Host ""Please run the 'run-installer.bat' file as an Administrator."" -ForegroundColor Yellow"
file.WriteLine " Read-Host ""Press Enter to exit"""
file.WriteLine " exit"
file.WriteLine "}"
file.WriteLine ""
file.WriteLine "function Write-HostColored { param($Message, $Color); Write-Host $Message -ForegroundColor $Color }"
file.WriteLine "Clear-Host"
file.WriteLine "Write-HostColored ""=========================================="" -Color Green"
file.WriteLine "Write-HostColored "" SolidWorks Activation Watcher Installer"" -Color Green"
file.WriteLine "Write-HostColored ""=========================================="" -Color Green"
file.WriteLine "Write-Host """""
file.WriteLine "Write-HostColored ""Administrator rights detected. Ready to install."" -Color Green"
file.WriteLine "Write-Host """""
file.WriteLine ""
file.WriteLine "$swParentFolder = Read-Host ""Enter path to the main SOLIDWORKS Corp folder (e.g., 'C:\Program Files\SOLIDWORKS Corp')"""
file.WriteLine "if (-not (Test-Path -Path $swParentFolder -PathType Container)) {"
file.WriteLine " Write-HostColored "" ERROR: The folder '$swParentFolder' does not exist."" -Color Red"
file.WriteLine " Read-Host ""Press Enter to exit""; exit"
file.WriteLine "}"
file.WriteLine ""
file.WriteLine "$installDir = Join-Path -Path $swParentFolder -ChildPath ""Scripts"""
file.WriteLine "$installPath = Join-Path -Path $installDir -ChildPath ""SWActivationWatcher.ps1"""
file.WriteLine "$scriptCurrentPath = $MyInvocation.MyCommand.Path"
file.WriteLine ""
file.WriteLine "Write-Host """""
file.WriteLine "Write-HostColored ""Preparing installation..."" -Color Cyan"
file.WriteLine "if (-not (Test-Path -Path $installDir)) { New-Item -Path $installDir -ItemType Directory | Out-Null }"
file.WriteLine "Copy-Item -Path $scriptCurrentPath -Destination $installPath -Force"
file.WriteLine "Write-Host "" -> Script copied to permanent location: $installPath"""
file.WriteLine ""
file.WriteLine "Write-Host "" -> Searching for swactwiz.exe..."""
file.WriteLine "$activator = Get-ChildItem -Path $swParentFolder -Filter ""swactwiz.exe"" -Recurse -ErrorAction SilentlyContinue | Select-Object -First 1"
file.WriteLine "if (-not $activator) {"
file.WriteLine " Write-HostColored "" ERROR: Could not find swactwiz.exe."" -Color Red"
file.WriteLine " Read-Host ""Press Enter to exit""; exit"
file.WriteLine "}"
file.WriteLine "$activatorPath = $activator.FullName"
file.WriteLine "Write-HostColored ""Found activator at: $activatorPath"" -Color Green"
file.WriteLine ""
file.WriteLine "Write-Host "" -> Creating Scheduled Task to run on login..."""
file.WriteLine "$taskName = ""SWActivationWatcher"""
file.WriteLine "$taskAction = New-ScheduledTaskAction -Execute ""powershell.exe"" -Argument ""-NoProfile -ExecutionPolicy Bypass -WindowStyle Hidden -File `""$installPath`"" -RunWatcherWithActivatorPath `""$activatorPath`"""""
file.WriteLine "$taskTrigger = New-ScheduledTaskTrigger -AtLogOn"
file.WriteLine "$taskPrincipal = New-ScheduledTaskPrincipal -UserId (whoami) -LogonType Interactive -RunLevel Highest"
file.WriteLine "Register-ScheduledTask -TaskName $taskName -Action $taskAction -Trigger $taskTrigger -Principal $taskPrincipal -Description ""Monitors for SolidWorks closing and handles the activation prompt."" -Force | Out-Null"
file.WriteLine ""
file.WriteLine "# Start the task immediately so the user doesn't have to wait for a reboot."
file.WriteLine "Write-Host "" -> Starting the watcher task now for the current session..."""
file.WriteLine "try {"
file.WriteLine " Start-ScheduledTask -TaskName $taskName"
file.WriteLine " Write-HostColored ""Watcher task is now running in the background."" -Color Green"
file.WriteLine "} catch {"
file.WriteLine " Write-HostColored ""Could not start the task immediately. It will start automatically on the next login."" -Color Yellow"
file.WriteLine "}"
file.WriteLine ""
file.WriteLine "Write-Host """""
file.WriteLine "Write-HostColored ""Success! Installation is complete."" -Color Green"
file.WriteLine "Try { Remove-Item -Path $MyInvocation.MyCommand.Path -Force -ErrorAction SilentlyContinue } Catch {}"
file.WriteLine "Write-Host """""
file.WriteLine "Write-Host ""The installed task script is located at:"""
file.WriteLine "Write-Host $installPath -ForegroundColor White"
file.Close
End If
' Launch PowerShell as administrator and bypass execution policy, run via cmd.exe with /k to keep console open
objShell.ShellExecute "cmd.exe", "/k powershell.exe -NoProfile -ExecutionPolicy Bypass -File """ & psPath & """", "", "runas", 1