www

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

installer-exe.rkt (18844B)


      1 #lang at-exp racket/base
      2 (require racket/format
      3          racket/list
      4          racket/system
      5 	 racket/path
      6 	 racket/file
      7          racket/runtime-path
      8          setup/getinfo
      9          setup/cross-system)
     10 
     11 (provide installer-exe)
     12 
     13 (define-runtime-path installer-dir "windows-installer")
     14 
     15 (define (get-exe-actions src-dir filename combine)
     16   (define f (build-path src-dir "lib" filename))
     17   (for/list ([(k v) (if (file-exists? f)
     18                         (call-with-input-file* f read)
     19                         (hash))])
     20     (combine k v)))
     21 
     22 (define (get-extreg src-dir)
     23   (apply
     24    append
     25    (get-exe-actions src-dir "extreg.rktd"
     26                     (lambda (k v) 
     27                       (for/list ([v (in-list v)])
     28                         (append v (list k)))))))
     29 
     30 (define (get-startmenu src-dir)
     31   (get-exe-actions src-dir "startmenu.rktd"
     32                    (lambda (k v) k)))
     33 
     34 (define (get-auto-launch src-dir)
     35   (define l
     36     (filter (lambda (p) (real? (cdr p)))
     37             (get-exe-actions src-dir "startmenu.rktd"
     38                              cons)))
     39   (if (null? l)
     40       #f
     41       (path-replace-suffix (caar (sort l < #:key cdr)) #"")))
     42 
     43 (define (try-exe f)
     44   (and (file-exists? f) f))
     45 
     46 (define (nsis-generate dest distname version winplatform 
     47                        makensis
     48                        #:extension-registers [extregs null]
     49                        #:start-menus [startmenus null]
     50                        #:versionless [versionless? #t]
     51                        #:simple? [simple? #f]
     52                        #:auto-launch [auto-launch #f])
     53   (define distdir (regexp-replace* #rx" " distname "-"))
     54   (define destfilename (file-name-from-path dest))
     55   (define-values (version1 version2 version3 version4)
     56     (apply
     57      values
     58      (take (cdr (regexp-match #rx"^([0-9]*)[.]([0-9]*)[.]([0-9]*)[.]([0-9]*)"
     59                               (string-append version ".0.0.0")))
     60            4)))
     61   (define got-files (make-hash))
     62   (define (get-file s)
     63     (unless (hash-ref got-files s #f)
     64       (define dest (build-path "bundle" s))
     65       (unless (file-exists? dest)
     66 	(hash-set! got-files s #t)
     67         (copy-file (build-path installer-dir s) dest)))
     68     s)
     69   (define script
     70   @~a{
     71 !include "MUI2.nsh"
     72 !include "WinVer.nsh"
     73 !include "nsDialogs.nsh"
     74 
     75 ;; ==================== Configuration
     76 
     77 !define RKTVersion "@|version|"
     78 !define RKTVersionLong "@|version1|.@|version2|.@|version3|.@|version4|"
     79 ;; Full name for the package, and a short name for installer texts
     80 !define RKTHumanName "@|distname| v@|version| (@|winplatform|)"
     81 !define RKTShortName "@|distname|"
     82 !define RKTStartName "@|distname|@(if versionless? "" @~a{ v@|version|})"
     83 !define RKTDirName "@|distdir|@(if versionless? "" @~a{-@|version|})"
     84 !define RKTRegName "@|distdir|-@|winplatform|-@|version|"
     85 !define RKTProgFiles "$PROGRAMFILES@(if (equal? winplatform "x86_64") "64" "")"
     86 @(if simple? @~a{!define SimpleInstaller} "")
     87 @(if auto-launch @~a{!define RKTLaunchProgram "@|auto-launch|"} "")
     88 
     89 Name "${RKTHumanName}"
     90 OutFile "@|destfilename|"
     91 
     92 BrandingText "${RKTHumanName}"
     93 BGGradient off
     94 
     95 SetCompressor /SOLID "LZMA"
     96 
     97 InstallDir "${RKTProgFiles}\${RKTDirName}"
     98 !ifndef SimpleInstaller
     99   InstallDirRegKey HKLM "Software\${RKTRegName}" ""
    100 !endif
    101 !define MUI_STARTMENUPAGE_DEFAULTFOLDER "${RKTStartName}"
    102 !define MUI_ICON   "@(get-file "installer.ico")"
    103 !define MUI_UNICON "@(get-file "uninstaller.ico")"
    104 !define MUI_HEADERIMAGE
    105 !define MUI_HEADERIMAGE_BITMAP     "@(get-file "header.bmp")"
    106 !define MUI_HEADERIMAGE_BITMAP_RTL "@(get-file "header-r.bmp")"
    107 !define MUI_HEADERIMAGE_RIGHT
    108 
    109 !define MUI_WELCOMEFINISHPAGE_BITMAP "@(get-file "welcome.bmp")"
    110 !define MUI_UNWELCOMEFINISHPAGE_BITMAP "@(get-file "welcome.bmp")"
    111 
    112 !define MUI_WELCOMEPAGE_TITLE "${RKTHumanName} Setup"
    113 !define MUI_UNWELCOMEPAGE_TITLE "${RKTHumanName} Uninstall"
    114 !ifdef SimpleInstaller
    115   !define MUI_WELCOMEPAGE_TEXT "This is a simple installer for ${RKTShortName}.$\r$\n$\r$\nIt will only create the @|distname| folder.  To uninstall, simply remove the folder.$\r$\n$\r$\n$_CLICK"
    116 !else
    117   !define MUI_WELCOMEPAGE_TEXT "This wizard will guide you through the installation of ${RKTShortName}.$\r$\n$\r$\nPlease close any running Racket applications so the installer can update the relevant system files.$\r$\n$\r$\n$_CLICK"
    118 !endif
    119 !define MUI_UNWELCOMEPAGE_TEXT "This wizard will guide you through the removal of ${RKTShortName}.$\r$\n$\r$\nBefore starting, make sure no Racket applications are running.$\r$\n$\r$\n$_CLICK"
    120 
    121 !define MUI_FINISHPAGE_TITLE "${RKTHumanName}"
    122 !ifdef SimpleInstaller
    123   !define MUI_FINISHPAGE_RUN
    124   !define MUI_FINISHPAGE_RUN_FUNCTION OpenInstDir
    125   Function OpenInstDir
    126     ExecShell "" "$INSTDIR"
    127   FunctionEnd
    128   !define MUI_FINISHPAGE_RUN_TEXT "Open the installation folder"
    129 @(if auto-launch
    130      @~a{
    131          !else
    132            !define MUI_FINISHPAGE_RUN "$INSTDIR\${RKTLaunchProgram}.exe"
    133            !define MUI_FINISHPAGE_RUN_TEXT "Run ${RKTLaunchProgram}"}
    134      "")
    135 !endif
    136 !define MUI_FINISHPAGE_LINK "Visit the Racket web site"
    137 !define MUI_FINISHPAGE_LINK_LOCATION "https://racket-lang.org/"
    138 
    139 ; !define MUI_UNFINISHPAGE_NOAUTOCLOSE ; to allow users see what was erased
    140 
    141 !define MUI_STARTMENUPAGE_REGISTRY_ROOT "HKLM"
    142 !define MUI_STARTMENUPAGE_REGISTRY_KEY "Software\${RKTRegName}"
    143 !define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "Start Menu Folder"
    144 
    145 ; Doesn't work on some non-xp machines
    146 ; !define MUI_INSTFILESPAGE_PROGRESSBAR colored
    147 
    148 VIProductVersion "${RKTVersionLong}"
    149 VIAddVersionKey "ProductName" "Racket"
    150 VIAddVersionKey "Comments" "This is the Racket language, see https://racket-lang.org/."
    151 VIAddVersionKey "CompanyName" "PLT Design Inc."
    152 VIAddVersionKey "LegalCopyright" "© PLT Design Inc."
    153 VIAddVersionKey "FileDescription" "Racket Installer"
    154 VIAddVersionKey "FileVersion" "${RKTVersion}"
    155 
    156 ;; ==================== Variables
    157 
    158 !ifndef SimpleInstaller
    159   Var MUI_TEMP
    160   Var STARTMENU_FOLDER
    161 !endif
    162 
    163 ;; ==================== Interface
    164 
    165 !define MUI_ABORTWARNING
    166 
    167 ; Install
    168 !insertmacro MUI_PAGE_WELCOME
    169 !define MUI_PAGE_CUSTOMFUNCTION_LEAVE myTestInstDir
    170 !insertmacro MUI_PAGE_DIRECTORY
    171 !ifndef SimpleInstaller
    172   !insertmacro MUI_PAGE_STARTMENU Application $STARTMENU_FOLDER
    173 !endif
    174 !insertmacro MUI_PAGE_INSTFILES
    175 
    176 ; Uncheck and hide the "run" checkbox on vista, since it will run with
    177 ; elevated permissions (see also ../nsis-vista-note.txt)
    178 !define MUI_PAGE_CUSTOMFUNCTION_SHOW DisableRunCheckBoxIfOnVista
    179 !insertmacro MUI_PAGE_FINISH
    180 Function DisableRunCheckBoxIfOnVista
    181   ${If} ${AtLeastWinVista}
    182     ; use EnableWindow instead of ShowWindow to just disable it
    183     ShowWindow $mui.FinishPage.Run 0
    184     ${NSD_Uncheck} $mui.FinishPage.Run
    185   ${EndIf}
    186 FunctionEnd
    187 
    188 !ifndef SimpleInstaller
    189   ; Uninstall
    190   !define MUI_WELCOMEPAGE_TITLE "${MUI_UNWELCOMEPAGE_TITLE}"
    191   !define MUI_WELCOMEPAGE_TEXT "${MUI_UNWELCOMEPAGE_TEXT}"
    192   ; !insertmacro MUI_UNPAGE_WELCOME
    193   !insertmacro MUI_UNPAGE_CONFIRM
    194   !insertmacro MUI_UNPAGE_INSTFILES
    195   ; !insertmacro MUI_UNPAGE_FINISH
    196 !endif
    197 
    198 !ifndef SimpleInstaller
    199   !define MUI_CUSTOMFUNCTION_UNGUIINIT un.myGUIInit
    200 !endif
    201 
    202 !insertmacro MUI_LANGUAGE "English"
    203 
    204 !ifndef SimpleInstaller
    205   !define UNINSTEXE "$INSTDIR\Uninstall.exe"
    206 !endif
    207 
    208 ;; ==================== Installer
    209 
    210 !ifdef SimpleInstaller
    211 Function myTestInstDir
    212   IfFileExists "$INSTDIR\*.*" +1 inst_dir_exists
    213     MessageBox MB_YESNO "The directory '$INSTDIR' already exists, continue?" /SD IDYES IDYES inst_dir_exists
    214     Abort
    215   inst_dir_exists:
    216 FunctionEnd
    217 !else
    218 Function myTestInstDir
    219   ; The assumption is that users might have all kinds of ways to get a Racket
    220   ; tree, plus, they might have an old wise-based installation, so it is better
    221   ; to rely on files rather than test registry keys.  Note: no version check.
    222   ; if any of these exist, then we assume it's an old installation
    223   IfFileExists "$INSTDIR\Racket.exe" racket_is_installed
    224   @(if auto-launch @~a{IfFileExists "$INSTDIR\${RKTLaunchProgram}.exe" racket_is_installed} "")
    225   IfFileExists "$INSTDIR\collects"     racket_is_installed
    226   Goto racket_is_not_installed
    227   racket_is_installed:
    228     IfFileExists "${UNINSTEXE}" we_have_uninstall
    229       MessageBox MB_YESNO "It appears that there is an existing Racket installation in '$INSTDIR', but no Uninstaller was found.$\r$\nContinue anyway (not recommended)?" /SD IDYES IDYES maybe_remove_tree
    230       Abort
    231     we_have_uninstall:
    232       MessageBox MB_YESNO "It appears that there is an existing Racket installation in '$INSTDIR'.$\r$\nDo you want to uninstall it first (recommended)?" /SD IDNO IDNO maybe_remove_tree
    233         HideWindow
    234         ClearErrors
    235         ExecWait '"${UNINSTEXE}" _?=$INSTDIR'
    236         IfErrors uninstaller_problematic
    237         IfFileExists "$INSTDIR\Racket.exe" uninstaller_problematic
    238           BringToFront
    239           Goto racket_is_not_installed
    240         uninstaller_problematic:
    241           MessageBox MB_YESNO "Errors in uninstallation!$\r$\nDo you want to quit and sort things out now (highly recommended)?" /SD IDNO IDNO maybe_remove_tree
    242           Quit
    243     maybe_remove_tree:
    244       MessageBox MB_YESNO "Since you insist, do you want to simply remove the previous directory now?$\r$\n(It is really better if you sort this out manually.)" /SD IDYES IDNO racket_is_not_installed
    245         RMDir /r $INSTDIR
    246   racket_is_not_installed:
    247 FunctionEnd
    248 !endif
    249 
    250 Section ""
    251   SetShellVarContext all
    252 
    253   SetDetailsPrint both
    254   DetailPrint "Installing Racket..."
    255   SetDetailsPrint listonly
    256   SetOutPath "$INSTDIR"
    257   File /a /r "racket\*.*"
    258   !ifndef SimpleInstaller
    259     WriteUninstaller "${UNINSTEXE}" ; Create uninstaller
    260   !endif
    261 
    262   !ifndef SimpleInstaller
    263     SetDetailsPrint both
    264     DetailPrint "Creating Shortcuts..."
    265     SetDetailsPrint listonly
    266     !insertmacro MUI_STARTMENU_WRITE_BEGIN Application
    267       SetOutPath "$INSTDIR" ; Make installed links run in INSTDIR
    268       CreateDirectory "$SMPROGRAMS\$STARTMENU_FOLDER"
    269       @apply[~a
    270              #:separator "\n"
    271              (for/list ([exe-str (in-list startmenus)])
    272                (define exe exe-str)
    273                (define lnk (path->string (path-replace-suffix exe-str #".lnk")))
    274                @~a{      CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\@|lnk|" "$INSTDIR\@|exe|"})]
    275       CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\Racket.lnk" "$INSTDIR\Racket.exe"
    276       CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\Racket Folder.lnk" "$INSTDIR"
    277       CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\Uninstall.lnk" "${UNINSTEXE}"
    278     !insertmacro MUI_STARTMENU_WRITE_END
    279 
    280     SetDetailsPrint both
    281     DetailPrint "Setting Registry Keys..."
    282     SetDetailsPrint listonly
    283       WriteRegStr HKLM "Software\${RKTRegName}" "" "$INSTDIR" ; Save folder location
    284       @apply[~a 
    285              #:separator "\n"
    286              (apply
    287               append
    288               (for/list ([extreg (in-list extregs)])
    289                 (define kind (list-ref extreg 1))
    290                 (define icon (list-ref extreg 3))
    291                 (define cmd (list-ref extreg 4))
    292                 (define exe-name (list-ref extreg 5))
    293                 (append
    294                  (for/list ([ext (in-list (list-ref extreg 2))])
    295                    @~a{    WriteRegStr HKCR ".@|ext|"   "" "@|kind|"})
    296                  (list
    297                   @~a{    WriteRegStr HKCR "@|kind|" "" "@(list-ref extreg 0)"}
    298                   @~a{    WriteRegStr HKCR "@|kind|\DefaultIcon" "" "$INSTDIR\lib\@|icon|"})
    299                  (if cmd
    300                      (list
    301                       @~a{    WriteRegStr HKCR "@|kind|\shell\open\command" "" '"$INSTDIR\@|exe-name|" @|cmd|'})
    302                      null))))]
    303       ; Example, in case we want some things like this in the future
    304       ; WriteRegStr HKCR "Racket.Document\shell\racket" "" "Run with Racket"
    305       ; WriteRegStr HKCR "Racket.Document\shell\racket\command" "" '"$INSTDIR\Racket.exe" "-r" "%1"'
    306 
    307       WriteRegExpandStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${RKTRegName}" "UninstallString" '"${UNINSTEXE}"'
    308       WriteRegExpandStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${RKTRegName}" "InstallLocation" "$INSTDIR"
    309       WriteRegStr       HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${RKTRegName}" "DisplayName" "${RKTHumanName}"
    310       WriteRegStr       HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${RKTRegName}" "DisplayIcon" "$INSTDIR\DrRacket.exe,0"
    311       WriteRegStr       HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${RKTRegName}" "DisplayVersion" "${RKTVersion}"
    312       ; used to also have "VersionMajor" & "VersionMinor" but looks like it's not needed
    313       WriteRegStr       HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${RKTRegName}" "HelpLink" "https://racket-lang.org/"
    314       WriteRegStr       HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${RKTRegName}" "URLInfoAbout" "https://racket-lang.org/"
    315       WriteRegStr       HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${RKTRegName}" "Publisher" "PLT Design Inc."
    316       WriteRegDWORD     HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${RKTRegName}" "NoModify" "1"
    317       WriteRegDWORD     HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${RKTRegName}" "NoRepair" "1"
    318   !endif
    319 
    320   SetDetailsPrint both
    321   DetailPrint "Installation complete."
    322 SectionEnd
    323 
    324 ;; ==================== Uninstaller
    325 
    326 !ifndef SimpleInstaller
    327 
    328 Function un.myGUIInit
    329   ; if any of these exist, then we're fine
    330   IfFileExists "$INSTDIR\Racket.exe"   racket_is_installed_un
    331   IfFileExists "$INSTDIR\lib\GRacket.exe"  racket_is_installed_un
    332   @(if auto-launch @~a{IfFileExists "$INSTDIR\${RKTLaunchProgram}.exe" racket_is_installed_un} "")
    333   IfFileExists "$INSTDIR\collects" racket_is_installed_un
    334     MessageBox MB_YESNO "It does not appear that Racket is installed in '$INSTDIR'.$\r$\nContinue anyway (not recommended)?" /SD IDYES IDYES racket_is_installed_un
    335     Abort "Uninstall aborted by user"
    336   racket_is_installed_un:
    337 FunctionEnd
    338 
    339 Section "Uninstall"
    340   SetShellVarContext all
    341 
    342   SetDetailsPrint both
    343   DetailPrint "Removing the Racket installation..."
    344   SetDetailsPrint listonly
    345     Delete "$INSTDIR\*.exe"
    346     Delete "$INSTDIR\README*.*"
    347     RMDir /r "$INSTDIR\include"
    348     RMDir /r "$INSTDIR\collects"
    349     RMDir /r "$INSTDIR\lib"
    350     RMDir /r "$INSTDIR\share"
    351     RMDir /r "$INSTDIR\etc"
    352     RMDir /r "$INSTDIR\doc"
    353     ;; these exist in Racket-Full installations
    354     RMDir /r "$INSTDIR\man"
    355     ; RMDir /r "$INSTDIR\src"
    356     Delete "${UNINSTEXE}"
    357     RMDir "$INSTDIR"
    358     ;; if the directory is opened, it will take some time to remove
    359     Sleep 1000
    360     IfErrors +1 uninstall_inst_dir_ok
    361       MessageBox MB_YESNO "The Racket installation at '$INSTDIR' was not completely removed.$\r$\nForce deletion?$\r$\n(Make sure no Racket applications are running.)" /SD IDYES IDNO uninstall_inst_dir_ok
    362         RMDir /r "$INSTDIR"
    363         IfErrors +1 uninstall_inst_dir_ok
    364           MessageBox MB_OK "Forced deletion did not work either, you will need to clean up '$INSTDIR' manually." /SD IDOK
    365     uninstall_inst_dir_ok:
    366 
    367   SetDetailsPrint both
    368   DetailPrint "Removing Shortcuts..."
    369   SetDetailsPrint listonly
    370     !insertmacro MUI_STARTMENU_GETFOLDER Application $MUI_TEMP
    371     Delete "$SMPROGRAMS\$MUI_TEMP\*.lnk"
    372     ;; Delete empty start menu parent diretories
    373     StrCpy $MUI_TEMP "$SMPROGRAMS\$MUI_TEMP"
    374     startMenuDeleteLoop:
    375       RMDir $MUI_TEMP
    376       GetFullPathName $MUI_TEMP "$MUI_TEMP\.."
    377       IfErrors startMenuDeleteLoopDone
    378       StrCmp $MUI_TEMP $SMPROGRAMS startMenuDeleteLoopDone startMenuDeleteLoop
    379     startMenuDeleteLoopDone:
    380 
    381   SetDetailsPrint both
    382   DetailPrint "Removing Registry Keys..."
    383   SetDetailsPrint listonly
    384     DeleteRegKey /ifempty HKLM "Software\${RKTRegName}\Start Menu Folder"
    385     DeleteRegKey /ifempty HKLM "Software\${RKTRegName}"
    386     @apply[~a
    387            #:separator "\n"
    388            (append
    389             (for*/list ([extreg (in-list extregs)]
    390                         [ext (in-list (list-ref extreg 2))])
    391               @~a{    DeleteRegKey HKCR ".@|ext|"})
    392             (for/list ([extreg (in-list extregs)])
    393               @~a{    DeleteRegKey HKCR ".@(list-ref extreg 1)"}))]
    394     DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${RKTRegName}"
    395 
    396   SetDetailsPrint both
    397   DetailPrint "Uninstallation complete."
    398 SectionEnd
    399 
    400 !endif
    401 })
    402   (call-with-output-file*
    403    "bundle/installer.nsi"
    404    #:mode 'text
    405    #:exists 'truncate
    406    (lambda (o)
    407      (display script o)
    408      (newline o)))
    409   (parameterize ([current-directory "bundle"])
    410     (define verbose (if (eq? 'windows (system-type))
    411                         "/V3"
    412                         "-V3"))
    413     (system* makensis verbose "installer.nsi")))
    414 
    415 (define (installer-exe human-name base-name versionless? dist-suffix readme osslsigncode-args)
    416   (define makensis (or (case (system-type)
    417                          [(windows)
    418                           (or (find-executable-path "makensis.exe")
    419                               (try-exe "c:\\Program Files\\NSIS\\makensis.exe")
    420                               (try-exe "c:\\Program Files (x86)\\NSIS\\makensis.exe"))]
    421                          [else (find-executable-path "makensis")])
    422                        (error 'installer-exe "cannot find \"makensis.exe\"")))
    423   (define platform (let-values ([(base name dir?) (split-path (cross-system-library-subpath #f))])
    424                      (bytes->string/utf-8 (path-element->bytes name))))
    425   (define exe-path (format "bundle/~a-~a-win32~a.exe" base-name platform dist-suffix))
    426   (when readme
    427     (call-with-output-file*
    428      #:exists 'truncate
    429      (build-path "bundle" "racket" "README.txt")
    430      (lambda (o)
    431        (display (regexp-replace* #rx"\n" readme "\r\n") o))))
    432   (nsis-generate exe-path
    433                  human-name
    434                  (version)
    435                  platform
    436                  makensis
    437                  #:versionless versionless?
    438                  #:extension-registers (get-extreg "bundle/racket")
    439                  #:start-menus (get-startmenu "bundle/racket")
    440                  #:auto-launch (get-auto-launch "bundle/racket"))
    441   (when osslsigncode-args
    442     (define unsigned-exe-path (let-values ([(base name dir?) (split-path exe-path)])
    443                                 (build-path base "unsigned" name)))
    444     (make-directory* "bundle/unsigned")
    445     (rename-file-or-directory exe-path unsigned-exe-path #t)
    446     (unless (apply system*
    447                    (or (find-executable-path (case (system-type)
    448                                                [(windows) "osslsigncode.exe"]
    449                                                [else "osslsigncode"]))
    450                        (error "cannot find `osslsigncode`"))
    451                    (append osslsigncode-args
    452                            (list "-n" human-name
    453                                  "-t" "http://timestamp.verisign.com/scripts/timstamp.dll"
    454                                  "-in" unsigned-exe-path "-out" exe-path)))
    455       (error "signing failed")))
    456   exe-path)