; Script generated by the Inno Setup Script Wizard. ; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES! #include "environment.iss" #define MyAppPublisher "Denver Technologies, Inc." #define MyAppURL "https://www.warp.dev/" #ifndef MyAppName #define MyAppName "GalaxyDev" #endif #ifndef MyAppVersion #define MyAppVersion "0.1.0" #endif #ifndef MyAppExeName #define MyAppExeName "dev.exe" #endif #ifndef ReleaseChannel #define ReleaseChannel "dev" #endif #ifndef TargetProfileDir #define TargetProfileDir "target\release-lto-debug_assertions" #endif #define AssetsDir "..\..\app\assets\windows" // The mutex name must match what the Rust app creates in single_instance_manager.rs: #define ChannelPascalCase \ (ReleaseChannel == "stable") ? "Stable" : \ ((ReleaseChannel == "dev") ? "Dev" : \ ((ReleaseChannel == "preview") ? "Preview" : \ ((ReleaseChannel == "local") ? "Local" : \ ((ReleaseChannel == "integration") ? "Integration" : \ ((ReleaseChannel == "oss") ? "Oss" : \ "Unknown"))))) #define AppMutexName "Local\Warp" + ChannelPascalCase + "_SingleInstance" [Setup] ; NOTE: The value of AppId uniquely identifies this application. Do not use the same AppId value in installers for other applications. ; (To generate a new GUID, click Tools | Generate GUID inside the IDE.) AppId=warp-terminal-{#ReleaseChannel} AppName={#MyAppName} AppVersion={#MyAppVersion} AppVerName={#MyAppName} {#MyAppVersion} UninstallDisplayName={#MyAppName} AppPublisher={#MyAppPublisher} AppPublisherURL={#MyAppURL} AppSupportURL={#MyAppURL} AppUpdatesURL={#MyAppURL} DefaultDirName={autopf}\{#MyAppName} ArchitecturesAllowed={#Arch} ArchitecturesInstallIn64BitMode={#Arch} DisableProgramGroupPage=yes ; The following line defaults the installer to use non administrative install mode (install for current user only). PrivilegesRequired=lowest ; Allow the user to choose administrative install mode (install for all users). PrivilegesRequiredOverridesAllowed=dialog OutputBaseFilename={#OutputName} Compression=lzma SolidCompression=yes WizardStyle=modern WizardSmallImageFile="installer-images\warp-logo.bmp" WizardImageFile="installer-images\warp-banner.bmp" SetupIconFile="..\..\app\channels\{#ReleaseChannel}\icon\no-padding\icon.ico" UninstallDisplayIcon="{app}\icon.ico" ; Force close previous Warp if it hasn't shut down yet. ; In the update flow we already warn the user if they have something running and make them confirm ; before running this installer. Therefore, we are good to force close Warp without fear of losing ; unsaved work. ; VSCode does something similar: ; https://github.com/microsoft/vscode/blob/aac9914f93551f894b8df1e4680bd847e7636be3/build/win32/code.iss#L41 CloseApplications=force ; For manual installs: if Warp is running, show a dialog prompting the user to close it ; before Setup proceeds. Returned empty for background updates so the check is skipped. AppMutex={code:GetAppMutex} SetupMutex={#AppMutexName}Setup ; Version 1809 / Build 18362 is required for ConPTY. See https://github.com/microsoft/vscode-docs/blob/9d736b662fdde3fed17d8bc2ed70bfea4ae20636/docs/supporting/troubleshoot-terminal-launch.md?plain=1#L66/ MinVersion=10.0.18362 ; Tell Windows Explorer to reload the environment so that path changes take effect. ChangesEnvironment=true RedirectionGuard=no ; Sign the setup engine and uninstaller so that the temporary bootstrapper ; extracted to %TEMP% is Authenticode-signed. This prevents Microsoft Defender ; ASR rule D4F940AB from blocking the installer in enterprise environments. ; The sign tool command is supplied via ISCC /S on the command line; when not ; defined (e.g. local dev builds) signing is skipped. #ifdef SIGN_TOOL SignTool=codesign SignedUninstaller=yes #endif [Languages] Name: "english"; MessagesFile: "compiler:Default.isl" [Tasks] Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}" [Files] ; NOTE: Don't use "Flags: ignoreversion" on any shared system files Source: "{#TargetProfileDir}\{#MyAppExeName}"; DestDir: "{app}"; Flags: ignoreversion Source: "{#AssetsDir}\{#Arch}\conpty.dll"; DestDir: "{app}"; Flags: ignoreversion Source: "{#AssetsDir}\{#Arch}\OpenConsole.exe"; DestDir: "{app}\{#Arch}"; Flags: ignoreversion Source: "..\..\app\channels\{#ReleaseChannel}\icon\no-padding\icon.ico"; DestDir: "{app}"; Flags: ignoreversion Source: "{#AssetsDir}\{#Arch}\vcruntime140.dll"; DestDir: "{app}" Source: "{#AssetsDir}\{#Arch}\vcruntime140_1.dll"; DestDir: "{app}" Source: "{#AssetsDir}\{#Arch}\msvcp140.dll"; DestDir: "{app}" Source: "..\..\app\assets\bundled\bootstrap\pwsh.ps1"; DestDir: "{app}" Source: "{#AssetsDir}\{#Arch}\dxcompiler.dll"; DestDir: "{app}" Source: "{#AssetsDir}\{#Arch}\dxil.dll"; DestDir: "{app}" Source: "{#TargetProfileDir}\resources\*"; DestDir: "{app}\resources"; Flags: ignoreversion recursesubdirs [Registry] Root: HKCU; Subkey: "SOFTWARE\Warp.dev\{#MyAppName}"; Flags: uninsdeletekey Root: HKCU; Subkey: "SOFTWARE\Warp.dev\{#MyAppName}"; ValueType: string; ValueName: "InstallationPath"; ValueData: "{app}\{#MyAppExeName}"; Flags: uninsdeletevalue Root: HKA; Subkey: "Software\Microsoft\Windows\CurrentVersion\App Paths\{#MyAppExeName}"; ValueType: string; ValueName: ""; ValueData: "{app}\{#MyAppExeName}"; Flags: uninsdeletekey ; cleanup "Open Warp Here" registry entries Root: HKA; Subkey: "Software\Classes\Directory\shell\{#MyAppName}"; Flags: deletekey Root: HKA; Subkey: "Software\Classes\Directory\Background\shell\{#MyAppName}"; Flags: deletekey ; Add "Open Warp in new tab" to directory context menu Root: HKA; Subkey: "Software\Classes\Directory\shell\{#MyAppName}Tab"; ValueType: string; ValueName: ""; ValueData: "Open {#MyAppName} in new tab"; Flags: uninsdeletekey Root: HKA; Subkey: "Software\Classes\Directory\shell\{#MyAppName}Tab"; ValueType: string; ValueName: "Icon"; ValueData: "{app}\icon.ico" Root: HKA; Subkey: "Software\Classes\Directory\shell\{#MyAppName}Tab\command"; ValueType: string; ValueName: ""; ValueData: """{app}\{#MyAppExeName}"" ""{#MyAppName}://action/new_tab?path=%1""" ; Add "Open Warp in new tab" to directory background context menu Root: HKA; Subkey: "Software\Classes\Directory\Background\shell\{#MyAppName}Tab"; ValueType: string; ValueName: ""; ValueData: "Open {#MyAppName} in new tab"; Flags: uninsdeletekey Root: HKA; Subkey: "Software\Classes\Directory\Background\shell\{#MyAppName}Tab"; ValueType: string; ValueName: "Icon"; ValueData: "{app}\icon.ico" Root: HKA; Subkey: "Software\Classes\Directory\Background\shell\{#MyAppName}Tab\command"; ValueType: string; ValueName: ""; ValueData: """{app}\{#MyAppExeName}"" ""{#MyAppName}://action/new_tab?path=%V""" ; Add "Open Warp in new window" to directory context menu Root: HKA; Subkey: "Software\Classes\Directory\shell\{#MyAppName}Window"; ValueType: string; ValueName: ""; ValueData: "Open {#MyAppName} in new window"; Flags: uninsdeletekey Root: HKA; Subkey: "Software\Classes\Directory\shell\{#MyAppName}Window"; ValueType: string; ValueName: "Icon"; ValueData: "{app}\icon.ico" Root: HKA; Subkey: "Software\Classes\Directory\shell\{#MyAppName}Window\command"; ValueType: string; ValueName: ""; ValueData: """{app}\{#MyAppExeName}"" ""{#MyAppName}://action/new_window?path=%1""" ; Add "Open Warp in new window" to directory background context menu Root: HKA; Subkey: "Software\Classes\Directory\Background\shell\{#MyAppName}Window"; ValueType: string; ValueName: ""; ValueData: "Open {#MyAppName} in new window"; Flags: uninsdeletekey Root: HKA; Subkey: "Software\Classes\Directory\Background\shell\{#MyAppName}Window"; ValueType: string; ValueName: "Icon"; ValueData: "{app}\icon.ico" Root: HKA; Subkey: "Software\Classes\Directory\Background\shell\{#MyAppName}Window\command"; ValueType: string; ValueName: ""; ValueData: """{app}\{#MyAppExeName}"" ""{#MyAppName}://action/new_window?path=%V""" [Tasks] Name: addToPath; Description: "Add Galaxy to PATH" [UninstallDelete] Type: filesandordirs; Name: "{userappdata}\warp\{#MyAppName}" Type: filesandordirs; Name: "{localappdata}\warp\{#MyAppName}" Type: filesandordirs; Name: "{app}\bin" [Icons] Name: "{autoprograms}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; IconFilename: "{app}\icon.ico"; AppUserModelID: "dev.warp.{#MyAppName}" Name: "{autodesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; IconFilename: "{app}\icon.ico"; AppUserModelID: "dev.warp.{#MyAppName}"; Tasks: desktopicon [Run] Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: postinstall runhidden nowait [Code] function IsNotStable(): Boolean; begin #if ReleaseChannel == "stable" Result := False; #else Result := True; #endif end; { Returns true when the installer was launched by Warp's auto-update code. The auto-update path passes /update=1 on the command line and /NOCLOSEAPPLICATIONS so that the installer does not forcibly kill the running Warp process. Instead we wait for Warp to exit naturally by polling the app mutex below. } function IsBackgroundUpdate(): Boolean; begin Result := ExpandConstant('{param:update|false}') <> 'false'; end; { For background updates, return an empty mutex name so that Inno Setup skips its built-in "application is running" dialog - we handle the wait ourselves. For manual installs, return the real mutex name so the user is prompted to close Warp first. } function GetAppMutex(Value: string): string; begin if IsBackgroundUpdate() then Result := '' else Result := '{#AppMutexName}'; end; procedure CurStepChanged(CurStep: TSetupStep); var BinDir: string; CmdScriptName: string; CmdScriptPath: string; CmdScriptContent: string; WaitCounter: Integer; ResultCode: Integer; begin { Background update: the installer was launched while Warp was still running. We passed /NOCLOSEAPPLICATIONS so Inno won't kill it. Wait here - before any files are touched - for Warp to release its single-instance mutex, which happens as part of normal process exit. } if CurStep = ssInstall then begin if IsBackgroundUpdate() then begin Log('Background update: waiting for Warp to exit (mutex: {#AppMutexName})...'); WaitCounter := 0; while CheckForMutexes('{#AppMutexName}') and (WaitCounter < 30) do begin Sleep(500); WaitCounter := WaitCounter + 1; end; if CheckForMutexes('{#AppMutexName}') then begin Log('Warp mutex still held after timeout; force-killing remaining processes.'); { Kill by image name. {#MyAppExeName} (e.g. warp.exe, dev.exe) is unique enough that collateral damage is not a concern. OpenConsole.exe is NOT killed by name because it is shared with Windows Terminal; instead we rely on Warp's Job Object (JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE) to cascade-kill any child OpenConsole.exe processes when warp.exe dies. } Exec('taskkill.exe', '/f /im {#MyAppExeName}', '', SW_HIDE, ewWaitUntilTerminated, ResultCode); if ResultCode <> 0 then Log('force-kill failed for {#MyAppExeName} (exit code: ' + IntToStr(ResultCode) + ')'); Sleep(1000); end else begin Log('Warp has exited; proceeding with file installation.'); { The minidump crash-reporter is a child process (same exe name) that may outlive the main Warp process. It holds the executable file open, which causes the file-copy step to fail with "Access is denied". We identify it by the "minidump-server" argument in its command line. } Exec('powershell.exe', '-NoProfile -NoLogo -Command "$stopError = 0; Get-CimInstance Win32_Process -Filter \"Name=''{#MyAppExeName}'' and CommandLine like ''%minidump-server%''\" | ForEach-Object { Stop-Process -Id $_.ProcessId -Force -ErrorVariable e -ErrorAction SilentlyContinue; if ($e) { $stopError = $e[0].Exception.HResult } }; exit $stopError"', '', SW_HIDE, ewWaitUntilTerminated, ResultCode); if ResultCode <> 0 then Log('minidump-server cleanup failed (exit code: ' + IntToStr(ResultCode) + ')'); Sleep(500); end; end; end; { After a successful install, write a helper script for running the Warp CLI. } { We use this to add a "warp-" prefix (e.g. "warp-preview.cmd" vs. "preview.exe") } if CurStep = ssPostInstall then begin { Add Warp to PATH if requested } if IsTaskSelected('addToPath') then EnvAddPath(ExpandConstant('{app}\bin')); BinDir := ExpandConstant('{app}\bin'); if not DirExists(BinDir) then CreateDir(BinDir); { Determine the channel-specific script name. These values must match `Channel::cli_command_name` in the Rust source. } #if ReleaseChannel == "stable" CmdScriptName := 'oz.cmd' #elif ReleaseChannel == "oss" CmdScriptName := 'warp-oss.cmd'; #else CmdScriptName := 'oz-{#ReleaseChannel}.cmd'; #endif { Create the helper CMD script } CmdScriptPath := BinDir + '\' + CmdScriptName; CmdScriptContent := '@echo off' + #13#10 + 'set "WARP_CLI_MODE=1"' + #13#10 + '"' + ExpandConstant('{app}\{#MyAppExeName}') + '" %*' + #13#10; SaveStringToFile(CmdScriptPath, CmdScriptContent, False); end; end; procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep); begin if CurUninstallStep = usPostUninstall then EnvRemovePath(ExpandConstant('{app}\bin')); end;