' 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