← Back to Blog Tutorial

Code Signing for Delphi and Inno Setup Apps

September 8, 2026 ยท 8 min read
Signed certificate between a Delphi app icon and an installer package on Windows

Delphi developers ship some of the longest-lived Windows software there is: point of sale systems, accounting packages, clinic and workshop tools, utilities that have been in daily use for fifteen years. Most of it is distributed as a single installer built with Inno Setup, sent to customers who are not technical.

That is exactly the audience that gets stopped cold by "Windows protected your PC". A developer knows to click More info and Run anyway. A shop owner installing your invoicing program does not, and an unsigned installer marked "Unknown publisher" looks to them like the thing they were warned about.

Most signing tutorials assume Visual Studio or Electron. This one is for Delphi and Inno Setup.

What needs a signature

Three files, not one:

  1. Your application exe (and any DLLs you build). This is what runs every day, and what antivirus engines look at after install.
  2. The installer that Inno Setup produces. This is what SmartScreen judges at download time.
  3. The uninstaller. Inno Setup generates it during compile. If it is unsigned, Windows shows an unknown publisher prompt when your customer removes or upgrades the program.

The order matters. Sign the exe first, then build the installer so it packs the signed exe, then sign the installer. If you sign the installer and rebuild the exe afterwards, the installer contains an unsigned program.

The traditional route, and why it got harder

The classic setup is a code signing certificate plus signtool.exe in a post-build step. Since 2023 the private key for any publicly trusted certificate has to live on a hardware token or a cloud HSM. For a one or two person Delphi shop that means a purchase of a few hundred dollars a year, a business identity check, and a USB token that must be plugged into whichever machine builds the release. If your build machine is a VM or a CI runner, the token becomes a real obstacle.

It is also worth knowing that an EV certificate no longer buys instant SmartScreen trust. Microsoft's documentation now states that EV and OV behave the same on first download. We covered that in EV certificates no longer skip SmartScreen.

Signing from Inno Setup

Inno Setup has first-class support for an external sign tool. It will call your tool for the installer, for the uninstaller, and for any file you flag in [Files]. With the Bamboo Deploy command line tool the script looks like this:

[Setup]
SignTool=bamboo
SignedUninstaller=yes

[Files]
Source: "MyApp.exe"; DestDir: "{app}"; Flags: signonce

Then register the tool named bamboo once, in the Inno Setup IDE under Tools, Configure Sign Tools:

cmd /c npx -y github:bamboodeploy/cli#v1.1.0 sign $f

Or pass it on the command line if you compile from a script:

ISCC.exe "/Sbamboo=cmd /c npx -y github:bamboodeploy/cli#v1.1.0 sign $f" setup.iss

Two details that trip people up:

The tool uploads each file, waits for it to be signed, and writes the signed file back in place, which is what Inno Setup expects. It needs Node 18 or newer on the build machine and an API key in the BAMBOO_API_KEY environment variable, or in a .bamboorc file next to your project.

Signing straight from the Delphi IDE

If you ship a bare exe, or want the exe signed before Inno Setup ever sees it, add a post-build event under Project, Options, Build Events:

npx -y github:bamboodeploy/cli#v1.1.0 sign "$(OUTPUTPATH)"

Put it on the Release configuration only. There is no point signing every debug build, and each signature is a round trip to the service. Build events run through the command shell, so no cmd /c is needed here.

Delphi-specific false positives

Delphi binaries draw more antivirus heuristics than most, for reasons that have nothing to do with your code:

The pattern to look for is a handful of detections with generic names (Heur, Gen:Variant, ML, Suspicious) and no named malware family. That is the false positive shape, and a valid signature is the main remedy for it. You can check a build before release, free:

npx -y github:bamboodeploy/cli#v1.1.0 scan MyAppSetup.exe

It prints the packer analysis, import analysis, rule matches, and signing status, so you see what a scanner sees.

A release checklist

  1. Fill in the version info in Project Options: company name, product name, file description, version. An exe with empty version info looks anonymous to users and to scanners.
  2. Build Release. Sign the exe.
  3. Compile the Inno Setup script with SignTool and SignedUninstaller=yes.
  4. Right-click the finished installer, Properties, Digital Signatures. Confirm the signature is present and valid. Do the same for the installed exe and unins000.exe.
  5. Test the download on a clean machine, through a browser, not from a network share. SmartScreen only checks files that carry the downloaded-from-the-web mark.
  6. Keep the signing identity the same from release to release. Reputation follows the certificate.

Bamboo Deploy signs Delphi and Inno Setup builds without a certificate purchase or a hardware token. Builds are scanned, then signed with our certificate. See the Inno Setup and Delphi docs, or get started here.