<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/"><channel><atom:link href="https://www.finalbuilder.com/DesktopModules/LiveBlog/API/Syndication/GetRssFeeds?Category=finalbuilder&amp;mid=632&amp;PortalId=0&amp;tid=181&amp;ItemCount=20" rel="self" type="application/rss+xml" /><title>VSoft Technologies Blogs</title><description>VSoft Technologies Blogs - posts about our products and software development.</description><link>https://www.finalbuilder.com/resources/blogs</link><item><title>Managing Certificate and API Key Expiry with Signotaur</title><link>https://www.finalbuilder.com/resources/blogs/postid/879/managing-certificate-and-api-key-expiry-with-signotaur</link><category>.NET,Code Signing,Continua CI,Delphi,FinalBuilderSignotaur</category><pubDate>Fri, 13 Mar 2026 03:18:12 GMT</pubDate><description>&lt;style type="text/css"&gt;
	div.blog_content h1 { font-size: 1.9rem; margin-bottom: 0.3rem; }
    div.blog_content h2 { font-size: 1.4rem; margin-top: 2.2rem; border-bottom: 1px solid #e0e0e0; padding-bottom: 0.4rem; }
    div.blog_content h3 { font-size: 1.15rem; margin-top: 1.6rem; color: #222;}
    div.blog_content strong {  font-weight: 600;  color: #888;}
    div.blog_content .meta { color: #777; font-size: 0.9rem; margin-bottom: 2rem; }
    div.blog_content code { background: #f4f4f4; padding: 0.15em 0.4em; border-radius: 3px; font-size: 0.92em; }
    div.blog_content pre { background: #f4f4f4; padding: 1rem; border-radius: 5px; overflow-x: auto; }
    div.blog_content pre code { background: none; padding: 0; }
    div.blog_content a { color: #0066cc; }
    div.blog_content img { max-width: 100%; border: 1px solid #ddd; border-radius: 4px; margin: 1rem 0; }
    div.blog_content .note { background: #eef6ff; border-left: 4px solid #0066cc; padding: 0.8rem 1rem; margin: 1.2rem 0; border-radius: 0 4px 4px 0; }
    div.blog_content ol { margin: 1rem 0 1.5rem 1.5rem; padding-left: 0.5rem;}
    div.blog_content ol li {  margin-bottom: 0.7rem;  line-height: 1.6;}
    div.blog_content ol li strong {  font-weight: 600;}
    div.blog_content ul li {  margin-bottom: 0.45rem;}
&lt;/style&gt;
&lt;div class="note"&gt;&lt;strong&gt;In this article:&lt;/strong&gt;
&lt;ul&gt;
	&lt;li&gt;Why code signing certificates now expire sooner&lt;/li&gt;
	&lt;li&gt;How certificate labels remove thumbprints from build scripts&lt;/li&gt;
	&lt;li&gt;How to rotate and renew API keys safely&lt;/li&gt;
	&lt;li&gt;How to automate the process in Continua CI&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;

&lt;h2&gt;Shorter Certificate Lifetimes Are Coming&lt;/h2&gt;

&lt;p&gt;Code signing certificates used to last up to three years. As of &lt;strong&gt;March 1, 2026&lt;/strong&gt;, that is no longer the case.&lt;/p&gt;

&lt;p&gt;The CA/Browser Forum adopted &lt;strong&gt;Ballot CSC-31&lt;/strong&gt; on November 17, 2025, reducing the maximum validity period for publicly-trusted code signing certificates from 39 months to &lt;strong&gt;460 days&lt;/strong&gt; (roughly 15 months). For most teams, that means certificate renewals are now an annual operational task rather than an occasional one.&lt;/p&gt;

&lt;p&gt;When a certificate is renewed, it receives a new thumbprint, and build scripts that reference the old thumbprint must be updated. In large CI/CD environments, tracking down every reference can be tedious and error-prone.&lt;/p&gt;

&lt;p&gt;Separately, API keys used by CI agents to authenticate with the signing server have their own lifecycle and eventually need to be rotated. Replacing them without interrupting active build pipelines can be challenging.&lt;/p&gt;

&lt;p&gt;Signotaur addresses both concerns. &lt;strong&gt;Label-based certificate selection&lt;/strong&gt; decouples build pipelines from individual certificates, while &lt;strong&gt;API key rotation with overlap&lt;/strong&gt; allows credentials to be replaced without downtime. Together they turn what used to be stressful maintenance tasks into routine operations.&lt;/p&gt;

&lt;h2&gt;Certificate Labels: Automatic Certificate Rotation&lt;/h2&gt;

&lt;h3&gt;The Thumbprint Problem&lt;/h3&gt;

&lt;p&gt;Traditionally, build scripts reference a code signing certificate by its SHA-1 thumbprint — a 40-character hex string that uniquely identifies the certificate. When you renew, you get a new certificate with a new thumbprint, so every script that signs code needs to be updated. If you sign across multiple CI configurations, that means tracking down and editing each one.&lt;/p&gt;

&lt;h3&gt;Labels to the Rescue&lt;/h3&gt;

&lt;p&gt;Signotaur lets you assign a &lt;strong&gt;label&lt;/strong&gt; to each registered certificate — for example, &lt;code&gt;production&lt;/code&gt; or &lt;code&gt;nightly&lt;/code&gt;. When you request a signing operation by label instead of thumbprint, Signotaur automatically selects the certificate with the &lt;strong&gt;latest expiry date&lt;/strong&gt; among all enabled, non-expired certificates that share that label. This ensures that newly issued certificates automatically take precedence.&lt;/p&gt;

&lt;p&gt;The rotation workflow is straightforward:&lt;/p&gt;

&lt;ol&gt;
	&lt;li&gt;Register your renewed certificate and assign it the same label as the outgoing one.&lt;/li&gt;
	&lt;li&gt;Builds automatically pick up the new certificate — no script changes required.&lt;/li&gt;
	&lt;li&gt;The old certificate expires naturally; remove it from Signotaur when you're ready.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;Expiration Monitoring&lt;/h3&gt;

&lt;p&gt;Signotaur's background monitoring service checks certificate expiration &lt;strong&gt;daily&lt;/strong&gt; and sends email notifications to administrators at configurable intervals. The defaults are &lt;strong&gt;30, 14, 7, 3, and 1 day(s)&lt;/strong&gt; before expiry, with an additional alert if a certificate has already expired. You can customise these warning thresholds in the server configuration.&lt;/p&gt;

&lt;p&gt;During a rotation window — when both the old and new certificates are registered with the same label — the admin UI highlights the duplicate label so you can confirm the overlap is intentional.&lt;/p&gt;

&lt;p&gt;&lt;img alt="Screenshot: Certificate list in the Signotaur admin UI showing two certificates sharing the 'production' label. The older certificate shows an expiry warning badge." src="https://cdn.finalbuilder.com/blog/daves/managing-certificate-and-api-key-expiry/screenshot-cert-labels.png" /&gt;&lt;/p&gt;

&lt;h2&gt;API Key Rotation with Overlap&lt;/h2&gt;

&lt;h3&gt;Why Rotate Keys?&lt;/h3&gt;

&lt;p&gt;API keys grant access to your signing service. If a key is leaked or reused indefinitely, it becomes a long-lived security risk. Regular rotation limits the impact if a key is compromised, satisfies compliance requirements, and handles natural key expiry gracefully. But naive rotation — revoke old, issue new — creates a window where CI agents holding the old key start failing.&lt;/p&gt;

&lt;h3&gt;How Signotaur Handles It&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;rotate-key&lt;/code&gt; command creates a new API key while keeping the old one valid for a configurable &lt;strong&gt;overlap period&lt;/strong&gt; of &lt;strong&gt;0–30 days&lt;/strong&gt; (default: &lt;strong&gt;7 days&lt;/strong&gt;). During this window, both keys are accepted, allowing CI agents and environments to transition without interruption.&lt;/p&gt;

&lt;p&gt;Once the overlap period expires, the old key is &lt;strong&gt;automatically revoked&lt;/strong&gt;. If you prefer to manage revocation manually, pass &lt;code&gt;--no-auto-revoke&lt;/code&gt; and the old key will remain valid until you explicitly revoke it.&lt;/p&gt;

&lt;p&gt;&lt;img alt="Screenshot: API Keys page in the Signotaur admin UI showing a rotated key pair. The old key displays an 'Auto-revoke' date and the new key is marked as active." src="https://cdn.finalbuilder.com/blog/daves/managing-certificate-and-api-key-expiry/screenshot-api-key-rotation.png" /&gt;&lt;/p&gt;

&lt;h3&gt;Safety Guardrails&lt;/h3&gt;

&lt;ul&gt;
	&lt;li&gt;&lt;strong&gt;Role required&lt;/strong&gt; — users must be assigned the &lt;strong&gt;ApiKeyRotator&lt;/strong&gt; role before they can rotate keys. An administrator can assign this role in the Signotaur admin UI.&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;Rate limiting&lt;/strong&gt; — a maximum of 5 rotations per user per 24-hour period prevents accidental key sprawl.&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;Linear chain only&lt;/strong&gt; — a key that has already been rotated cannot be rotated again; you must use the successor key. This prevents branching into multiple active key chains.&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;Proactive expiry checking&lt;/strong&gt; — the sign command accepts a &lt;code&gt;--fail-if-expiring-within&lt;/code&gt; flag (e.g. &lt;code&gt;14d&lt;/code&gt;). If the API key used for signing will expire within that window, the command fails immediately with a clear message — catching the problem in CI before it causes a real signing failure.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Conditional Rotation&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;--if-expiring-within&lt;/code&gt; flag on &lt;code&gt;rotate-key&lt;/code&gt; makes rotation idempotent: the key is only rotated if it expires within the specified duration (e.g. &lt;code&gt;14d&lt;/code&gt;, &lt;code&gt;1w&lt;/code&gt;, &lt;code&gt;24h&lt;/code&gt;). This makes it safe to run &lt;code&gt;rotate-key&lt;/code&gt; on every CI build or on a nightly schedule without generating unnecessary keys.&lt;/p&gt;

&lt;p&gt;Example scheduled rotation command:&lt;/p&gt;

&lt;pre&gt;
&lt;code&gt;signotaur rotate-key --if-expiring-within 14d&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Key Renewal&lt;/h3&gt;

&lt;p&gt;By default, a rotated key &lt;strong&gt;inherits the old key's expiry date&lt;/strong&gt;. If the old key had 30 days of validity remaining, the new key also expires in 30 days. Over time, repeatedly rotating a key gradually shortens its remaining lifetime — which can be a problem for long-running automation.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;--renew&lt;/code&gt; flag gives the new key a &lt;strong&gt;fresh validity period&lt;/strong&gt; starting from the rotation date, rather than inheriting whatever time was left on the old key. Without a value, it uses the server default of &lt;strong&gt;90 days&lt;/strong&gt;; with a value (e.g. &lt;code&gt;--renew 180d&lt;/code&gt;), it sets a specific duration up to a maximum of &lt;strong&gt;365 days&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This pairs naturally with conditional rotation — check whether the key is approaching expiry, and if so, rotate and renew in a single command:&lt;/p&gt;

&lt;pre&gt;
&lt;code&gt;signotaur rotate-key --if-expiring-within 14d --renew&lt;/code&gt;&lt;/pre&gt;

&lt;div class="note"&gt;If the renewal duration would be &lt;em&gt;shorter&lt;/em&gt; than the old key's remaining validity (for example renewing for 30 days when 60 days remain), the command fails as a safety measure. Pass &lt;code&gt;--allow-validity-reduction&lt;/code&gt; to override this check when the shorter duration is intentional.&lt;/div&gt;

&lt;h2&gt;Putting It Together in Continua CI&lt;/h2&gt;

&lt;p&gt;Continua CI ships dedicated &lt;strong&gt;Signotaur actions&lt;/strong&gt; for both signing and key rotation, so you can wire up the entire workflow without writing any custom scripts. Before configuring those actions, you'll need to assign a label to your certificates in the Signotaur admin UI.&lt;/p&gt;

&lt;h3&gt;Assigning a Label to Your Certificates&lt;/h3&gt;

&lt;p&gt;In the Signotaur admin UI, navigate to &lt;strong&gt;Certificates&lt;/strong&gt; and either add a new certificate or edit an existing one. In the certificate dialog you'll find two name fields:&lt;/p&gt;

&lt;ul&gt;
	&lt;li&gt;&lt;strong&gt;Alias&lt;/strong&gt; — a unique display name for the certificate (auto-generated by default, e.g. "CodeSigningCert (2027-12-31)").&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;Label&lt;/strong&gt; — an optional identifier used for CLI and CI/CD certificate selection, e.g. &lt;code&gt;production&lt;/code&gt;. Multiple certificates can share the same label. Matching is case-insensitive, so &lt;code&gt;Production&lt;/code&gt; and &lt;code&gt;production&lt;/code&gt; resolve the same way.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When you renew a certificate, register the new one and assign it the same label as the outgoing certificate. The admin UI will show an orange notice confirming that multiple active certificates share the label and that the one with the latest expiry will be selected automatically. No build script changes needed.&lt;/p&gt;

&lt;p&gt;&lt;img alt="Screenshot: Signotaur certificate edit dialog showing the Alias and Label fields. The Label field is set to 'production'." src="https://cdn.finalbuilder.com/blog/daves/managing-certificate-and-api-key-expiry/screenshot-cert-edit-label.png" /&gt;&lt;/p&gt;

&lt;p&gt;For full details, see the &lt;a href="https://docs.finalbuilder.com/sn/1.0/server/admin/certificates/certificates.html"&gt; Certificates documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;Setting Up the Rotate Keys Action&lt;/h3&gt;

&lt;p&gt;Add the &lt;strong&gt;Signotaur Rotate Keys&lt;/strong&gt; action to a stage — either in a scheduled maintenance configuration or directly in your build configuration. With the &lt;strong&gt;If Expiring Within&lt;/strong&gt; condition the action only rotates the key when expiry is approaching, so it can safely run on every build.&lt;/p&gt;

&lt;p&gt;The action is organised into several tabs:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Signotaur Rotate Keys tab&lt;/strong&gt; — configure &lt;strong&gt;Overlap Days&lt;/strong&gt; (how long the old key remains valid alongside the new one, default 7) and whether to &lt;strong&gt;Disable auto-revocation&lt;/strong&gt; if you prefer to revoke old keys manually.&lt;/p&gt;

&lt;p&gt;&lt;img alt="Screenshot: Continua CI Signotaur Rotate Keys action — Main tab showing Overlap Days and Disable auto-revocation options." src="https://cdn.finalbuilder.com/blog/daves/managing-certificate-and-api-key-expiry/screenshot-rotate-keys-main.png" /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Server tab&lt;/strong&gt; — set the &lt;strong&gt;Server URL&lt;/strong&gt; for your Signotaur instance and the &lt;strong&gt;API Key Source&lt;/strong&gt;. Select &lt;em&gt;Value (from variable)&lt;/em&gt; and reference a server variable (e.g. &lt;code&gt;%SignotaurAPIKey%&lt;/code&gt;) to avoid hard-coding keys in the action.&lt;/p&gt;

&lt;p&gt;&lt;img alt="Screenshot: Continua CI Signotaur Rotate Keys action — Server tab showing Server URL and API Key Source set to a server variable." src="https://cdn.finalbuilder.com/blog/daves/managing-certificate-and-api-key-expiry/screenshot-rotate-keys-server.png" /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conditions tab&lt;/strong&gt; — set &lt;strong&gt;If Expiring Within&lt;/strong&gt; to make the rotation conditional (e.g. &lt;code&gt;14d&lt;/code&gt; to only rotate if expiry is within two weeks). Enable &lt;strong&gt;Ignore already rotated error&lt;/strong&gt; to safely run the action in concurrent CI builds without failure if the key was already rotated by another build.&lt;/p&gt;

&lt;p&gt;&lt;img alt="Screenshot: Continua CI Signotaur Rotate Keys action — Conditions tab showing If Expiring Within and Ignore already rotated error options." src="https://cdn.finalbuilder.com/blog/daves/managing-certificate-and-api-key-expiry/screenshot-rotate-keys-conditions.png" /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Renewal tab&lt;/strong&gt; — enable the &lt;strong&gt;Renew&lt;/strong&gt; checkbox to give the new key a fresh validity period instead of inheriting the old key's remaining lifetime. Set a specific &lt;strong&gt;Renew Duration&lt;/strong&gt; (e.g. &lt;code&gt;90d&lt;/code&gt;), or leave it blank to use the server default. Check &lt;strong&gt;Allow validity reduction&lt;/strong&gt; if the renewal duration may be shorter than the old key's remaining validity.&lt;/p&gt;

&lt;p&gt;&lt;img alt="Screenshot: Continua CI Signotaur Rotate Keys action — Renewal tab showing Renew checkbox, Renew Duration, and Allow validity reduction options." src="https://cdn.finalbuilder.com/blog/daves/managing-certificate-and-api-key-expiry/screenshot-rotate-keys-renewal.png" /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Output tab&lt;/strong&gt; — choose &lt;strong&gt;Set Variable&lt;/strong&gt; as the output destination and select a &lt;strong&gt;Server variable&lt;/strong&gt; to store the new key. This way your sign actions automatically pick up the rotated key without any manual updates.&lt;/p&gt;

&lt;p&gt;&lt;img alt="Screenshot: Continua CI Signotaur Rotate Keys action — Output tab with Set Variable selected, storing the new key in a server-scoped variable." src="https://cdn.finalbuilder.com/blog/daves/managing-certificate-and-api-key-expiry/screenshot-rotate-keys-output.png" /&gt;&lt;/p&gt;

&lt;p&gt;Full documentation: &lt;a href="https://docs.finalbuilder.com/ci/1.0/user-guide/actions/signing-actions/signotaur-rotate-keys-action.html"&gt; Signotaur Rotate Keys Action &lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;Setting Up the Sign Action with Label Selection&lt;/h3&gt;

&lt;p&gt;Add the &lt;strong&gt;Signotaur Sign&lt;/strong&gt; action to your build stage, after compilation and before packaging.&lt;/p&gt;

&lt;p&gt;Key fields:&lt;/p&gt;

&lt;ul&gt;
	&lt;li&gt;&lt;strong&gt;Files to Sign&lt;/strong&gt; — glob patterns for your build output, e.g. &lt;code&gt;**/*.exe&lt;/code&gt;, &lt;code&gt;**/*.dll&lt;/code&gt;.&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;Certificate Selection Mode&lt;/strong&gt; — set to &lt;strong&gt;Label&lt;/strong&gt;.&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;Label&lt;/strong&gt; — your shared label, e.g. &lt;code&gt;production&lt;/code&gt;. Signotaur will automatically select the certificate with the latest expiry date.&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;API Key Source&lt;/strong&gt; — point to the server variable populated by the Rotate Keys action, or a securely stored key.&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;Fail If Expiring Within&lt;/strong&gt; — e.g. &lt;code&gt;14d&lt;/code&gt;. If the API key expires within two weeks, the action fails early so you can rotate before it becomes a blocker.&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;Timestamp Server &amp; Digest&lt;/strong&gt; — configure your preferred timestamping authority and hash algorithm.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="Screenshot: Continua CI Signotaur Sign action — Certificate tab showing Selection Mode set to Label with value 'production'." src="https://cdn.finalbuilder.com/blog/daves/managing-certificate-and-api-key-expiry/screenshot-sign-certificate.png" /&gt; 
&lt;/p&gt;
&lt;p&gt;&lt;img alt="Screenshot: Continua CI Signotaur Sign action — Server tab showing Fail If Expiring Within set to '14d'." src="https://cdn.finalbuilder.com/blog/daves/managing-certificate-and-api-key-expiry/screenshot-sign-server.png" /&gt;&lt;/p&gt;

&lt;p&gt;Full documentation: &lt;a href="https://docs.finalbuilder.com/ci/1.0/user-guide/actions/signing-actions/signotaur-sign-action.html"&gt; Signotaur Sign Action &lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;Typical Rotation Workflow&lt;/h2&gt;

&lt;p&gt;In practice, certificate and API key rotation can be handled with a small amount of scheduled automation in your CI system.&lt;/p&gt;

&lt;ol&gt;
	&lt;li&gt;&lt;strong&gt;Register renewed certificates&lt;/strong&gt; in Signotaur and assign them the same label as the previous certificate.&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;CI builds continue using the label&lt;/strong&gt;, automatically selecting the certificate with the latest expiry date.&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;Schedule periodic API key checks&lt;/strong&gt; using the &lt;code&gt;rotate-key --if-expiring-within&lt;/code&gt; option.&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;The new key is written to a CI server variable&lt;/strong&gt;, allowing build pipelines to automatically use the rotated key.&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;Use &lt;code&gt;--renew&lt;/code&gt;&lt;/strong&gt; so rotated keys receive a fresh validity period rather than inheriting the old key's remaining lifetime.&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;Retire old certificates and keys&lt;/strong&gt; once they are no longer needed.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;Wrapping Up&lt;/h2&gt;

&lt;p&gt;With code signing certificate lifetimes dropping to roughly 15 months, the days of "set it and forget it" certificate management are over. Signotaur's label-based signing means your CI/CD pipelines don't need to know — or care — which specific certificate is current. And overlap-based API key rotation ensures you can swap credentials without any signing downtime.&lt;/p&gt;

&lt;p&gt;These features are already available in Signotaur. If you're evaluating it, check out the &lt;a href="https://docs.finalbuilder.com/signotaur/1.0/"&gt;Signotaur documentation&lt;/a&gt; to get started.&lt;/p&gt;
</description><guid isPermaLink="false">879</guid></item><item><title>Using YAML with Delphi - VSoft.YAML</title><link>https://www.finalbuilder.com/resources/blogs/postid/875/using-yaml-with-delphi-vsoftyaml</link><category>Delphi,FinalBuilder,Open Source</category><pubDate>Tue, 16 Sep 2025 13:21:38 GMT</pubDate><description>&lt;h2&gt;Introduction&lt;/h2&gt;

&lt;p&gt;Almost every modern Delphi application needs a way to store structured data: configuration settings, runtime options, or even project metadata. For decades, developers have relied on INI files for simple key/value storage, XML for deeply structured documents, or JSON as a lightweight alternative.&lt;/p&gt;

&lt;p&gt;But there’s another option that has grown into the de facto standard in DevOps and configuration management: YAML.&lt;/p&gt;

&lt;p&gt;This article introduces &lt;a href="https://github.com/VSoftTechnologies/VSoft.YAML" target="_blank"&gt;VSoft.YAML&lt;/a&gt; - an open-source Delphi library that makes working with YAML straightforward. We’ll cover why you might choose YAML over INI, XML, or JSON, then dive into practical Delphi code examples for parsing, editing, and writing YAML.&lt;/p&gt;

&lt;h2&gt;Why YAML?&lt;/h2&gt;

&lt;h3&gt;Human-Readability&lt;/h3&gt;

&lt;p&gt;YAML is designed for humans first. Compare the following formats describing a database configuration:&lt;/p&gt;

&lt;h4&gt;YAML&lt;/h4&gt;

&lt;pre class="brush:plain; toolbar:false;"&gt;
database:
  host: localhost
  port: 5432
  user: admin
  password: secret

            &lt;/pre&gt;

&lt;h4&gt;JSON&lt;/h4&gt;

&lt;pre class="brush:jscript; toolbar:false;"&gt;
{
    "database": {
    "host": "localhost",
    "port": 5432,
    "user": "admin",
    "password": "secret"
    }
}

            &lt;/pre&gt;

&lt;h4&gt;XML&lt;/h4&gt;

&lt;pre class="brush:xml; toolbar:false;"&gt;
&lt;database&gt;
    &lt;host&gt;localhost&lt;/host&gt;
    &lt;port&gt;5432&lt;/port&gt;
    &lt;user&gt;admin&lt;/user&gt;
    &lt;password&gt;secret&lt;/password&gt;
&lt;/database&gt;
            &lt;/pre&gt;

&lt;p&gt;The YAML version is the least noisy, especially when configurations get larger.&lt;/p&gt;

&lt;h4&gt;Expressiveness&lt;/h4&gt;

&lt;ul&gt;
	&lt;li&gt;Supports mappings (key/value), sequences (lists), and scalars (strings, numbers, booleans).&lt;/li&gt;
	&lt;li&gt;Handles deeply nested structures naturally.&lt;/li&gt;
	&lt;li&gt;More flexible than INI files, which are limited to sections and key/value pairs.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;Adoption&lt;/h4&gt;

&lt;ul&gt;
	&lt;li&gt;YAML is everywhere, especially in DevOps.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Introducing VSoft.YAML&lt;/h3&gt;

&lt;p&gt;VSoft.YAML is a pure Delphi implementation of a YAML 1.2 parser and emitter:&lt;/p&gt;

&lt;ul&gt;
	&lt;li&gt;&lt;strong&gt;No external dependencies&lt;/strong&gt; — just add the source to your project.&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;Round-trip capable&lt;/strong&gt; — parse, modify, and write YAML without losing formatting.&lt;/li&gt;
	&lt;li&gt;Supports multiple documents in a single YAML stream.&lt;/li&gt;
	&lt;li&gt;Supports reading/writing JSON&lt;/li&gt;
	&lt;li&gt;Extensive &lt;a href="https://github.com/VSoftTechnologies/VSoft.YAML/blob/main/docs/JSONPath-Syntax.md" target="_blank"&gt;JSONPath&lt;/a&gt; support&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Getting Started&lt;/h3&gt;

&lt;h4&gt;Installation&lt;/h4&gt;

&lt;p&gt;Clone the repo or add it as a Git submodule:&lt;/p&gt;

&lt;pre brush="bash"&gt;
git clone https://github.com/VSoftTechnologies/VSoft.YAML.git
            &lt;/pre&gt;

&lt;p&gt;Then add the &lt;code&gt;VSoft.YAML\Source&lt;/code&gt; folder to your Delphi project’s search path.&lt;/p&gt;

&lt;h3&gt;Parsing YAML&lt;/h3&gt;

&lt;p&gt;The most common scenario is loading YAML from a string or file.&lt;/p&gt;

&lt;pre class="brush:delphi; toolbar:false;"&gt;
uses
  VSoft.YAML;

var
  Doc: IYAMLDocument;
  YamlText: string;
begin
  YamlText :=
    'database:' + sLineBreak +
    ' host: localhost' + sLineBreak +
    ' port: 5432' + sLineBreak +
    ' user: admin' + sLineBreak +
    ' password: secret';

    Doc := TYAML.LoadFromString(YamlText);
    Writeln('Database host: ', Doc.Root.Values['database'].Values['host'].AsString);
    Writeln('Database port: ', Doc.Root.Values['database'].Values['port'].AsInteger);
end;
            &lt;/pre&gt;

&lt;p&gt;To load from a file, just call &lt;code&gt;TYAML.LoadFromFile&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;Traversing Sequences&lt;/h3&gt;

&lt;p&gt;YAML supports lists (called &lt;strong&gt;sequences&lt;/strong&gt;).&lt;/p&gt;

&lt;h4&gt;Example YAML&lt;/h4&gt;

&lt;pre class="brush:plain; toolbar:false;"&gt;
servers:
- name: web01
  ip: 10.0.0.1
- name: web02
  ip: 10.0.0.2
            &lt;/pre&gt;

&lt;h4&gt;Delphi Code&lt;/h4&gt;

&lt;pre class="brush:delphi; toolbar:false;"&gt;
var
    doc : IYAMLDocument;
    servers: IYAMLSequence;
    server : IYAMLMapping; 
    i: integer;
begin
    doc := TYAML.LoadFromFile('c:\test\config.yaml');
    servers := Doc.Root.Values['servers'].AsSequence;
    for i := 0 to servers.Count - 1 do
    begin
        server := Servers.Items[I].AsMapping;
        Writeln(Format('%s (%s)',[server.Values['name'].AsString, Server.Values['ip'].AsString]));
    end;
end;
          &lt;/pre&gt;

&lt;h3&gt;Modifying YAML&lt;/h3&gt;

&lt;p&gt;Once parsed, you can update values and write them back out:&lt;/p&gt;

&lt;pre class="brush:delphi; toolbar:false;"&gt;
var
    root: IYAMLMapping;
begin
    root := Doc.Root.AsMapping;
    root.AddOrSetValue('environment', 'production');
    TYAML.WriteToFile(doc, 'c:\test\config.yaml')
end;
            &lt;/pre&gt;

&lt;h2&gt;Practical Use Cases for Delphi Developers&lt;/h2&gt;

&lt;ul&gt;
	&lt;li&gt;Configuration files — ship your app with config.yaml instead of INI or XML.&lt;/li&gt;
	&lt;li&gt;DevOps integration — generate or consume YAML configs for devops tools.&lt;/li&gt;
	&lt;li&gt;Structured data — when you need nested lists or dictionaries without verbosity.&lt;/li&gt;
	&lt;li&gt;Collaboration — YAML files are easy for non-developers to read and edit.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Tips and Best Practices&lt;/h2&gt;

&lt;ul&gt;
	&lt;li&gt;&lt;strong&gt;Use JSON when machine-only consumption is expected.&lt;/strong&gt;&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;Use YAML when humans will edit the config.&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;YAML Rules to be aware of&lt;/h2&gt;

&lt;p&gt;Even though YAML is designed to be human-friendly, it comes with its own quirks. Here are a few issues you might run into when using YAML with Delphi:&lt;/p&gt;

&lt;h3&gt;1. Indentation Rules&lt;/h3&gt;

&lt;ul&gt;
	&lt;li&gt;YAML is indentation-sensitive.&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;Spaces only&lt;/strong&gt; — tabs are not allowed for indentation.&lt;/li&gt;
	&lt;li&gt;A single misplaced space can completely change the structure.&lt;/li&gt;
&lt;/ul&gt;

&lt;pre class="brush:plain; toolbar:false;"&gt;
valid:
  key1: value
  key2: value

invalid:
  key1: value
   key1: value # wrong indentation
            &lt;/pre&gt;

&lt;h3&gt;2. Duplicate Keys&lt;/h3&gt;

&lt;p&gt;Unlike JSON, YAML technically allows duplicate keys in mappings, but this can lead to unexpected behavior. YAML Parsers will typically keep only the last occurrence.&lt;/p&gt;

&lt;pre class="brush:plain; toolbar:false;"&gt;
settings:
  timeout: 10
  timeout: 30 # overwrites the first one
            &lt;/pre&gt;

&lt;p&gt;VSoft.YAML has a parser option to control the handling of duplicate keys&lt;/p&gt;

&lt;pre class="brush:delphi; toolbar:false;"&gt;
options := TYAML.CreateParserOptions;
options.DuplicateKeyBehavior := TYAMLDuplicateKeyBehavior.dkError; // default is dkOverwrite
doc := TYAML.LoadFromFile(fileName, options);
            &lt;/pre&gt;

&lt;p&gt;Best practice: avoid duplicates in configs, and add validation in your app if needed.&lt;/p&gt;

&lt;h3&gt;3. Scalars and Quoting&lt;/h3&gt;

&lt;p&gt;YAML is permissive about quoting strings, which can sometimes surprise you:&lt;/p&gt;

&lt;pre class="brush:plain; toolbar:false;"&gt;
path: C:\Temp\file.txt # might be misinterpreted due to backslashes
             &lt;/pre&gt;

&lt;p&gt;Safer to quote unusual strings:&lt;/p&gt;

&lt;pre class="brush:plain; toolbar:false;"&gt;
path: "C:\Temp\file.txt"
            &lt;/pre&gt;

&lt;h3&gt;4. Boolean Values&lt;/h3&gt;

&lt;p&gt;YAML recognizes a wide set of values as booleans: yes/no, true/false, on/off.&lt;/p&gt;

&lt;pre class="brush:plain; toolbar:false;"&gt;
feature_enabled: yes # interpreted as boolean true
            &lt;/pre&gt;

&lt;p&gt;If you actually mean the literal string "yes", you must quote it:&lt;/p&gt;

&lt;pre class="brush:plain; toolbar:false;"&gt;
feature_enabled: "yes"
                        &lt;/pre&gt;

&lt;h3&gt;5. Comments&lt;/h3&gt;

&lt;p&gt;While YAML supports # comments, they are not part of the data model and usually not preserved&lt;/p&gt;

&lt;p&gt;VSoft.YAML &lt;strong&gt;does&lt;/strong&gt; attempt to preserve comments. This is non standard. Generally, comments before mappings (objects) and sequences(arrays) are preserved, comments after scalar values may be preserved.&lt;/p&gt;

&lt;p&gt;Blank lines will not be preserved.&lt;/p&gt;

&lt;h3&gt;6. Large or Complex Documents&lt;/h3&gt;

&lt;ul&gt;
	&lt;li&gt;For deeply nested structures, readability can drop.&lt;/li&gt;
	&lt;li&gt;Split configs into multiple YAML files if possible.&lt;/li&gt;
	&lt;li&gt;Use &lt;code&gt;---&lt;/code&gt;(start) and &lt;code&gt;...&lt;/code&gt;(end) to separate documents in a single file if needed.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;7. Type Guessing&lt;/h3&gt;

&lt;p&gt;By default, YAML interprets unquoted values:&lt;/p&gt;

&lt;ul&gt;
	&lt;li&gt;&lt;code&gt;42&lt;/code&gt; → integer&lt;/li&gt;
	&lt;li&gt;&lt;code&gt;3.14&lt;/code&gt; → float&lt;/li&gt;
	&lt;li&gt;&lt;code&gt;3.1.4&lt;/code&gt; → string&lt;/li&gt;
	&lt;li&gt;&lt;code&gt;true&lt;/code&gt; → boolean&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you want to enforce string semantics, quote the value:&lt;/p&gt;

&lt;pre class="brush:plain; toolbar:false;"&gt;
port: "5432"
            &lt;/pre&gt;

&lt;h3&gt;8. CRLF vs LF Line Endings&lt;/h3&gt;

&lt;p&gt;VSoft.YAML is tolerant of Windows vs Unix line endings, but if your configs are shared across systems, normalize line endings in your source control to avoid “it works on my machine” issues.&lt;/p&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;YAML offers developers a unique combination of human readability, expressiveness, and versatility. Unlike INI files, it can represent complex nested structures; unlike XML, it remains clean and concise; and unlike JSON, it's easier for humans to read and maintain.&lt;/p&gt;

&lt;p&gt;The full list of features support by VSoft.YAML is &lt;a href="https://github.com/VSoftTechnologies/VSoft.YAML/blob/main/docs/YAML-Features-Implementation.md" target="_blank"&gt;available here.&lt;/a&gt;&lt;/p&gt;
</description><guid isPermaLink="false">875</guid></item><item><title>FinalBuilder 8.5 and Automise 5.5 Release</title><link>https://www.finalbuilder.com/resources/blogs/postid/871/finalbuilder-85-and-automise-55-release</link><category>Automise,Delphi,FinalBuilderGeneral,Visual Studio,Windows</category><pubDate>Wed, 09 Apr 2025 01:50:56 GMT</pubDate><description>&lt;p&gt;It's no secret that we are always working on the next version of FinalBuilder and Automise - that's the nature of software development. That said, the next major versions are taking much longer than we would like - the reason for this is dealing with serious technical debt (active scripting).&lt;/p&gt;

&lt;p&gt;With this extended development cycle, there are changes that we finished some time ago that we decided just could not wait for the next major version. We backported those changes to the FinalBuilder 8.x and Automise 5.x - but since some of these changes break project compatibility (with the x.0 releases) we are releasing FinalBuilder 8.5 and Automise 5.5&lt;/p&gt;

&lt;h2&gt;Encryption Algorithm&lt;/h2&gt;

&lt;p&gt;FinalBuilder &amp; Automise have always used the &lt;a href="https://en.wikipedia.org/wiki/Blowfish_(cipher)" target="_blank"&gt;Blowfish&lt;/a&gt; algorithm (with a 160 bit key) for encrypting passwords, apikeys etc.&lt;/p&gt;

&lt;p&gt;FinalBuilder 8.5/Automise 5.5 adds the &lt;a href="https://en.wikipedia.org/wiki/Advanced_Encryption_Standard" target="_blank"&gt;AES 256 Algorithm&lt;/a&gt; (with a 256 bit key) as an option.&lt;/p&gt;

&lt;p&gt;There is a new IDE option to specify the default project encryption for new projects - this defaults to AES256. Note this only affects New projects. To change the algorithm used for existing projects, open the project info window from the Project Menu, change the setting and click ok and then save the project.&lt;/p&gt;

&lt;p&gt;Note that these options will be removed in FinalBuilder 9/Automise 6, when AES 256 will become the default (and projects still using Blowfish will be upgraded automatically).&lt;/p&gt;

&lt;p&gt;It's should be noted that Blowfish is still considered reasonably secure, this change is to enabled the continued use of FinalBuilder in organisations must comply with NIST (US) or ASD (Australia) requirements.&lt;/p&gt;

&lt;h2&gt;Password Variables&lt;/h2&gt;

&lt;p&gt;In FinalBuilder &amp; Automise we have always attempted to mask passwords from the logs, but occasionally that can slip through.&lt;/p&gt;

&lt;p&gt;Any passwords stored in variables were visible in plain text in project project files. For this reason, we have added a new Password variable type. These variables will be encrypted in project files. The backing type is string.&lt;/p&gt;

&lt;h2&gt;Password UI&lt;/h2&gt;

&lt;p&gt;All password fields on all now utilise a new password edit control that allows peeking at the value (like the windows 11 password box).&lt;/p&gt;

&lt;h2&gt;Windows Credential Manager Actions&lt;/h2&gt;

&lt;p&gt;The Windows Credential Manager actions enable you to read/write/delete credentials stored in the credential manager.&lt;/p&gt;

&lt;h2&gt;Project file compatibility Warning&lt;/h2&gt;

&lt;p&gt;FinalBuilder 8.5 project files are NOT downward compatible with FinalBuilder 8.0 - or put another way, FinalBuilder 8.0 cannot load FinalBuilder 8.5 projects. The same applies to Automise 5.5 projects. This is due to some of the changes outlined above.&lt;/p&gt;
</description><guid isPermaLink="false">871</guid></item><item><title>FinalBuilder and Automise on Windows 11 24H2</title><link>https://www.finalbuilder.com/resources/blogs/postid/848/finalbuilder-and-automise-on-windows-11-24h2</link><category>Automise,Delphi,FinalBuilder</category><pubDate>Thu, 21 Nov 2024 22:35:00 GMT</pubDate><description>&lt;h2&gt;The problem&lt;/h2&gt;

&lt;p&gt;Windows 11 24H2 breaks scripting in FinalBuilder and Automise. You will see a range of different errors depending on your scripts or the actions you use (some actions use jscript).&lt;/p&gt;

&lt;h2&gt;The cause&lt;/h2&gt;

&lt;p&gt;Windows 24h2 enables a policy by default that causes JScript.dll (the com dll) to load JScript9Legacy.dll rather than JScript9.dll&lt;/p&gt;

&lt;p&gt;JScript9Legacy.dll is a replacement engine using Chakra - which is an odd choice since it seems abandoned since Edge moved to using chromium. The reason they did this was because of a security issue - which is understandable - but unfortnately it introduces a whole host of bugs they do not seem to interested in fixing (I guess it works for them). &lt;/p&gt;

&lt;p&gt;This issue even affects some of Microsoft's own applications (like Visual Studio)&lt;/p&gt;

&lt;h2&gt;The work around&lt;/h2&gt;

&lt;p&gt;The workaround is to &lt;a href="https://admx.help/?Category=Windows_11_2022&amp;Policy=Microsoft.Policies.InternetExplorer::JScriptReplacement)" target="_blank"&gt;disable the policy&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Run regedit.&lt;/p&gt;

&lt;p&gt;navigate to (for all users) :&lt;/p&gt;

&lt;pre&gt;
HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Internet Explorer\Main&lt;/pre&gt;

&lt;p&gt;or (for the current user only)&lt;/p&gt;

&lt;pre&gt;
HKEY_CURRENT_USER\SOFTWARE\Policies\Microsoft\Internet Explorer\Main&lt;/pre&gt;

&lt;p&gt;Note these keys did not exist on my machine, so I added them.&lt;/p&gt;

&lt;p&gt;Right click the Main key and select New DWORD (32-bit) Value, name the new value JScriptReplacement and the value to 0.&lt;/p&gt;

&lt;p&gt;Restart FinalBuilder (no need to reboot).&lt;/p&gt;

&lt;p&gt;Obviously, this is not ideal - we have been looking to replace JScript for some time - unfortunately so far our efforts have not resulted in something that is 100% backwards compatible - so we still have some work to do in this area.&lt;/p&gt;
</description><guid isPermaLink="false">848</guid></item><item><title>FinalBuilder 8.0.0.3378 and Automise 5.0.0.1593 breaking changes.</title><link>https://www.finalbuilder.com/resources/blogs/postid/847/finalbuilder-8003378-and-automise-5001593-breaking-changes</link><category>Automise,Delphi,FinalBuilder,Windows</category><pubDate>Tue, 16 Jul 2024 05:30:16 GMT</pubDate><description>&lt;p&gt;Throughout the lifespan of FinalBuilder and Automise, we have worked very hard to avoid breaking changes - however sometimes they are unavoidable.&lt;/p&gt;

&lt;p&gt;Today's updates to FinalBuilder 8 and Automise 5 have a breaking change in the SSH Batch Execute action. Previously, this action would manage it's own connect/disconnect - the breaking change is this action now requires separate SSH Connect/Disconnect actions. &lt;/p&gt;

&lt;p&gt;The reason for this is complicated, but it was brought about by us changing the client library we use for the SSH actions. The previous client library had too many issues that we were unable to work around. The most annoying example - the actions would not work correctly/reliably with openssh running on windows servers. We did try to fix this issue, but in the end the only viable option was to replace the library (something we were planning to do in the future anyway).  The new library (Rebex) is much more stable and performant. We plan to re-implement the SFTP actions (which have issues with some servers) with this library in a future update.&lt;/p&gt;

&lt;p&gt;We have been using a build with these changes in production for some time now to dogfood these changes. &lt;/p&gt;

&lt;p&gt;To use the  SSH Batch Execute action, add an SSH Connect action before it and an SSH Disconnect after, set the connection name on the SSH Batch Execute and SSH Disconnect to the name of the new SSH Connect action's connection name and you should be all set.&lt;/p&gt;

&lt;p&gt;If you experience any issues with the SSH actions in these new updates let us know (with as much info as you can about the server and action settings). &lt;/p&gt;
</description><guid isPermaLink="false">847</guid></item><item><title>Black Friday Sale 2023 - 50% off all new licenses</title><link>https://www.finalbuilder.com/resources/blogs/postid/846/black-friday-sale-2023-50-percent-off-all-new-licenses</link><category>Automise,Continua CI,Delphi,FinalBuilder</category><pubDate>Fri, 24 Nov 2023 02:27:58 GMT</pubDate><description>&lt;p&gt;50% OFF. No, that’s not a typo! Our first ever Black Friday sale - 50% off all new licenses - valid to midnight Tues 28th Nov (UTC).&lt;/p&gt;

&lt;p&gt;No coupon code required, the store will apply the discount automatically.&lt;/p&gt;
</description><guid isPermaLink="false">846</guid></item><item><title>Code Signing with USB Tokens</title><link>https://www.finalbuilder.com/resources/blogs/postid/845/code-signing-with-usb-tokens</link><category>Code Signing,Continua CI,DelphiFinalBuilder,Signotaur</category><pubDate>Mon, 03 Oct 2022 16:40:22 GMT</pubDate><description>&lt;h3&gt;Update Nov 2024&lt;/h3&gt;

&lt;p&gt;Whilst the content of this post is as valid today as it was originally, we became frustrated with being limited to signing on one machine. That meant our build agents were doing a lot of copying of files to and from the server with the token.&lt;/p&gt;

&lt;p&gt;Our solution was to build a Code Signing Server - &lt;a href="https://www.finalbuilder.com/signotaur" target="_blank"&gt;Signotaur&lt;/a&gt; - keep reading and then take a look at how Signotaur solves the problems we talk about in this post.&lt;/p&gt;

&lt;hr /&gt;
&lt;p&gt;Big changes are coming for code signing certificates in 2023. New and reissued publicly trusted organisation validation (OV) and individual validation (IV) code signing certificates will have to be issued or stored on preconfigured secure hardware by the issuing Certificate Authority (CA) and the device must meet FIPS 140 Level 2, Common Criteria EAL 4+ or equivalent security standards.&lt;/p&gt;

&lt;p&gt;This is already the case for EV (Extended Validation) certificates, and it presents some problems in an automated build environment. In this post we'll take a look at the issues with hardware-based certificates and how to work around them. &lt;/p&gt;

&lt;h2&gt;Why is this change necessary?&lt;/h2&gt;

&lt;p&gt;If you work in IT, you will have heard or read about the &lt;a href="https://www.sans.org/blog/what-you-need-to-know-about-the-solarwinds-supply-chain-attack/" target="_blank"&gt;SolarWinds supply chain hack&lt;/a&gt;. It was a big deal. It's more common than we might think - in February 2022 &lt;a href="https://www.malwarebytes.com/blog/news/2022/03/stolen-nvidia-certificates-used-to-sign-malware-heres-what-to-do" target="_blank"&gt;NVIDIA&lt;/a&gt; had their code signing certificates stolen and they were used to sign malware (those certificates have since expired).&lt;/p&gt;

&lt;p&gt;These (and other) episodes made many in the industry (Microsoft in particular) very nervous. Trust is a big deal when it comes to certificates, and that is certainly the case when it comes to certificate issuance, but there is not a lot of trust in how those certificates are secured by the developers using them. Ask anyone who has done the merry validation dance with a CA, it's not that easy to get a code signing certificate these days. With that in mind, the CA/Browser forum &lt;a href="https://cabforum.org/2022/04/06/ballot-csc-13-update-to-subscriber-key-protection-requirements/" target="_blank"&gt;adopted a proposal&lt;/a&gt; to change the requirements for how issued certificates are stored.&lt;/p&gt;

&lt;p&gt;The change makes a lot of sense - it's much harder to steal hardware than it is to steal files. &lt;/p&gt;

&lt;h2&gt;What does this mean&lt;/h2&gt;

&lt;p&gt;From 1 June 2023, all new and reissued publicly trusted OV and IV code signing certificates will have to be issued or stored on a pre-configured secure hardware device by the issuing certificate authority (CA) and the device must meet FIPS 140 Level 2, Common Criteria EAL 4+ or equivalent security standards. &lt;/p&gt;

&lt;p&gt;Existing OV/IV certificates will continue to work, but if you need your certificate to be reissued you may encounter issues due to key size requirements changing (so don't lose your certificate). The reality is that most certificate providers have already switched to issuing certificates on tokens (or discontinued selling OV/IV certificates). This is the end of simply downloading a pfx. &lt;/p&gt;

&lt;h2&gt;What are these hardware devices &lt;/h2&gt;

&lt;p&gt;These devices fall broadly into 3 categories:&lt;/p&gt;

&lt;h3&gt;Network-attached Hardware Security Modules (HSM)&lt;/h3&gt;

&lt;p style="text-align: center"&gt;&lt;img src="https://cdn.finalbuilder.com/blog/vincent/codesign-usb/safenet-luna-network-hsm_0.png" /&gt;&lt;/p&gt;

&lt;p&gt;HSM's in this class bring a lot of benefits and functionality (like key usage audit logs) - code signing is just part of that. These devices are not cheap - usually in the "if you have to ask you probably can't afford" price range! There's a reason for that steep price though. They are designed to be ultra-secure and tamper proof - open the lid and you will likely lock it up or brick it. &lt;/p&gt;

&lt;p&gt;CA's will charge you a premium if you BYOD (bring your own device) - expect an audit fee of around $500 - or you can employ your own suitably qualified auditor (no idea what the criteria is for that but it sounds expensive). You will also have to deal with creating a Certificate Signing Request (CSR) to send to the CA. The process varies depending on the device, and the CA websites don't offer much guidance there. &lt;/p&gt;

&lt;h3&gt;Cloud HSM's&lt;/h3&gt;

&lt;p&gt;Azure, AWS, Google and others provide cloud HSM's, a service layer in front of network-attached HSM's - you basically rent time/space on them. They typically charge a monthly fee and then a fee per cryptographic operation. CA's charge a hefty fee to create certificates for use on these services - up to $1200 - and on top of that some CA's charge per number of signings per year (no idea how they police that). You also need to do some work to configure secure access to the HSM. These services make sense if you are already running on the cloud. Like other HSM's you will need to create a CSR to send to the CA during the order/validation process&lt;/p&gt;

&lt;p&gt;SSL.com offer an eSigner cloud-based service (they are also a CA), but the prices will make you think twice about code signing: USD $100 per month for 10 signings, plus $10 for each additional signing. We sign every build that might escape the building and each build has several files that need signing! &lt;/p&gt;

&lt;h3&gt;USB tokens&lt;/h3&gt;

&lt;p&gt;In my research so far, the most common USB token is the Gemalto/Thales SafeNet token. The only other ones I have encountered are Yubikey (only SSL.com seems to be using those) and Certum (for which I could find very little info on the client software). The token tends to be included in the price of the certificate (I did see one case where it was not). You do not need to create a CSR (unless you are using your own existing token) as the CA loads the certificate on the device before posting it to you. The one I have (from Digicert) is a Safenet token. It's already obsolete and cannot be used for new certificates as it doesn't support the larger key size required now (newer model required).  &lt;/p&gt;

&lt;h3&gt;Locked In&lt;/h3&gt;

&lt;p&gt;One thing to note about all the possible hardware devices, whether it's yours or one you rent, is that once a certificate is installed on that device, it's private key cannot be exported. So if you decide the cloud service you are using is too expensive and want to move, well it's time for a new certificate. &lt;/p&gt;

&lt;p&gt;Some CA's say they cannot reissue EV's on USB tokens, whilst others provide a procedure - it's likely you will be up for a new token cost and more verification hoops to jump through. So don't lose or damage it! &lt;/p&gt;

&lt;p&gt;In the rest of this post, I'm only going to cover USB tokens. If you have access to network or cloud HSM's then you are probably well past this point.  &lt;/p&gt;

&lt;h2&gt;So, what's the problem then?&lt;/h2&gt;

&lt;p&gt;Different USB tokens might use different client software/drivers - but they all have one thing in common - the USB token needs to be present (i.e. plugged in to the machine) when code signing. This seemingly innocuous little USB token (which looks just like a memory stick) needs to be physically secure. If someone walks past your machine and takes it (likely thinking it's a memory stick), well you are up a creek without a paddle. My SafeNet token has a bright blue LED on the end that just screams "Take me!". Our build servers are colocated at a data centre - so leaving things like USB devices plugged in is asking for trouble. It's not like I can walk over and plug it in when needed (every day!). The data center is 300km from where I live/work.&lt;/p&gt;

&lt;p&gt;Add to this that build machines are typically virtual, so you are into the realm of USB passthrough. If you use Hyper-V Server (as we do), well you are bang out of luck.. not supported. I have heard that VMWare ESXI supports it just fine but have never used it. I tested with XCP-ng and did get it working, but it was a major hassle to configure (reams of commands and copying of guids).&lt;/p&gt;

&lt;h2&gt;USB - Remotely&lt;/h2&gt;

&lt;p&gt;Fortunately, there are alternatives to USB passthrough. I looked at a bunch of USB remoting products (USB over IP/UDP), and after poor results with most, I found one that works. In fact it works incredibly well, with much better pricing than the others.&lt;/p&gt;

&lt;p&gt;That product is &lt;a href="https://virtualhere.com" target="_blank"&gt;VirtualHere&lt;/a&gt; (VH). Of all the vendors I contacted, they were the only one who actually responded and answered the question I asked - "Does it support code signing tokens?". The author responded, "Actually I use my (Digicert) JC Token via VirtualHere to sign VirtualHere when I build VirtualHere inside a VM." Good enough for me to give it a try!&lt;/p&gt;

&lt;p&gt;The VH Server runs on Windows, Linux, MacOS, a bunch of NAS servers, even a Raspberry Pi! The server licence is locked to the host machine, so if you decide to move the USB token to another host you will need to purchase another license - but at USD$49 that probably won't break the bank!&lt;/p&gt;

&lt;p&gt;I installed the VH server software on my XCP-ng host - installation was trivial and took all of 2 minutes (I'm no Linux expert). I then plugged the USB token in (the server is in my mini rack at home) and installed the VirtualHere client software on my Windows machine.&lt;/p&gt;

&lt;p&gt;The VH client can auto detect servers, however in my case the two machines were on different subnets, so I had to manually specify it. With the trial version, a message box shows up when it first connects. The client immediately showed a tree of the USB devices plugged into the server. The SafeNet token shows up as Token JC, right-click on it and select "Auto use this device" so it connects automatically. When I did this, the familiar Windows sound indicated a device had plugged in. I already had the SafeNet software installed so it didn't prompt me for drivers etc.&lt;/p&gt;

&lt;p style="text-align: center"&gt;&lt;img src="https://cdn.finalbuilder.com/blog/vincent/codesign-usb/virtualhere-client.png" /&gt;&lt;/p&gt;

&lt;p&gt;The last step in this USB remoting journey was to install the client as a service (right click on the USB Hubs node). This can only connect to licensed servers, so leave this step until you have purchased.&lt;br /&gt;
&lt;br /&gt;
&lt;strong&gt;NOTE&lt;/strong&gt; : I didn't make it clear before, but the VH client and token client software need to be installed on the machine where the signing takes place, ie your build machine or build agent machine. &lt;/p&gt;

&lt;h2&gt;Prompting for Passwords&lt;/h2&gt;

&lt;p&gt;Another issue with the USB tokens being present during code signing, is they also expect a human to be present - a password prompt is shown. That flies in the face of conventional wisdom - automate all the things!&lt;/p&gt;

&lt;p&gt;Fortunately, for the SafeNet token at least, there is a work around for this.&lt;/p&gt;

&lt;p&gt;Open the Safenet Authentication Client Tools, click on the Advanced View button (the gear). You may be prompted for the token password if you haven't already entered it. In the tree on the left, right-click on the certificate (under User certificates) and select Export certificate. Just to be clear here, this is the certificate without the private key (which stays on the token) - you can't use this exported certificate on a machine that does not have access to the USB token. &lt;/p&gt;

&lt;p style="text-align: center"&gt;&lt;img src="https://cdn.finalbuilder.com/blog/vincent/codesign-usb/safenetvalues.png" /&gt;&lt;/p&gt;

&lt;p&gt;In the certificate view, under Private Key, take note of the Cryptographic Provider value (likely "eToken Base Cryptographic Provider" and the Container Name (p11#xxxxxxxxxxx). You will have to manually type them out somewhere as it doesn't support the clipboard. Save those values somewhere - as you will need them in your build process for code signing.&lt;/p&gt;

&lt;p&gt;Whilst still in the Client tools, select Client Settings and go to the Advance tab, check the "Enable single Login" and "Enable single Logon for PKCS#11." options, and set Automatic Logoff to Never - then hit Save. You can close the client now.&lt;/p&gt;

&lt;h2&gt;Code Signing&lt;/h2&gt;

&lt;p&gt;With all that done, we can use Signtool action in FinalBuilder. The Signing option tab is where those values we saved earlier come into play.&lt;/p&gt;

&lt;p&gt;The only difficult one is the Private Key container. Fortunately, some clever person on StackOverflow figure out the required format:&lt;/p&gt;

&lt;p&gt;[{{%CSPWD%}}]=p11#xxxxxxxxxx&lt;/p&gt;

&lt;p&gt;I have used a variable CSPWD for the token password.&lt;/p&gt;

&lt;p style="text-align: center"&gt;&lt;img src="https://cdn.finalbuilder.com/blog/vincent/codesign-usb/signtooloptions.png" /&gt;&lt;/p&gt;

&lt;p&gt;That's it. In my tests I have run FinalBuilder from the Windows task scheduler while logged out, and from a Continua CI build agent service (again while logged out) and it worked in both instances. I did a bunch of login/out/reboot testing and it continued to work. VirtualHere has been flawless. The next step is to configure our CI agents to access the USB token over VPN. Sadly our EV token is about to expire (and we never used it once in production, our OV cert still has another year left) - so I first have to jump through the validation hoops to get a new one.&lt;/p&gt;

&lt;p&gt;When using this technique on a CI server, you will need to take care that only one build at a time is using the token. In Continua CI, that is trivial to achieve using a &lt;a href="https://wiki.finalbuilder.com/display/continua/Shared+Resources" target="_blank"&gt; shared resource lock.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I would love to test out some of the cloud HSM services too, but purchasing a certificate for each one is too rich for me. If you are using any of those with a cloud-based HSM, jump on our forums and let us know your experiences. If you experiment with or get up and running using VH let us know how it went - I might do a follow up post as we all gain more experience with usb tokens and code signing.&lt;/p&gt;

&lt;h2&gt;Warning (added 19 Oct 2022)&lt;/h2&gt;

&lt;p&gt;I probably should have pointed out that most tokens are configured to lock you out after too many authentication failures. So if you are getting auth failures when setting this up, stop, and manually login to the token to reset the failed count. &lt;/p&gt;

&lt;h2&gt;Rant&lt;/h2&gt;

&lt;p&gt;CA's (and their resellers) have some of the worst websites I have ever had the displeasure of reading. Pages and pages of useless or contradictory information with links promising more information that take you around in circles. Grrrrr. &lt;/p&gt;
</description><guid isPermaLink="false">845</guid></item><item><title>Continua CI System Server Properties</title><link>https://www.finalbuilder.com/resources/blogs/postid/844/continua-ci-server-properties</link><category>Continua CI,Delphi,FinalBuilder,General</category><pubDate>Thu, 13 May 2021 12:59:28 GMT</pubDate><description>&lt;p&gt;If you are using Continua for your CI, (and if not why not?) ensure that you check out &lt;a href="https://wiki.finalbuilder.com/x/BYDp"&gt;System Server Properties&lt;/a&gt;. These allow access to global settings which do not fit on any existing page.&lt;/p&gt;
&lt;p&gt;They can be used to configure several aspects of the UI and build process to fit your team preferences. This could simply be the number items to show per page on each of the dashboard views (&lt;em&gt;Server.ProjectsView.*.PageSize&lt;/em&gt;), or more complex patterns for detecting errors and warnings in actions settings (&lt;em&gt;Actions.Messages.*Patterns&lt;/em&gt;). Some system server properties are rarely needed, but some can be considered essential, such as &lt;em&gt;Server.HostUrl&lt;/em&gt; which can be used to ensure the links in notifications go to the correct external host name.&lt;/p&gt;

&lt;p&gt;We have recently added some new server properties which allow you to control the tabs on the Queue Options dialog (&lt;em&gt;Server.QueueOptionsDialog.*&lt;/em&gt;) and create a banner for displaying a message to all (or a subset of) users (&lt;em&gt;Server.Banner.*&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;Here is the result of changing &lt;em&gt;Server.QueueOptionsDialog.TabSequence&lt;/em&gt; from "Variables,Repositories,Options"&lt;/p&gt;

&lt;p&gt;&lt;img alt="Queue Options dialog tabs - Variables first" src="https://cdn.finalbuilder.com/blog/daves/serverprops/queueoptionsvariablesfirst.png" /&gt;&lt;/p&gt;

&lt;p&gt;to "Repositories,Variables,Options".&lt;/p&gt;

&lt;p&gt;&lt;img alt="Queue Options dialog tabs - Variables first" src="https://cdn.finalbuilder.com/blog/daves/serverprops/queueoptionsrepositoriesfirst.png" /&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;This is what happens to an existing banner when you change the &lt;em&gt;Server.Banner.MessageType&lt;/em&gt; from "Information"&lt;/p&gt;

&lt;p&gt;&lt;img alt="Information Banner" src="https://cdn.finalbuilder.com/blog/daves/serverprops/informationbanner.png" /&gt;&lt;/p&gt;

&lt;p&gt;to "Warning".&lt;/p&gt;

&lt;p&gt;&lt;img alt="Warning Banner" src="https://cdn.finalbuilder.com/blog/daves/serverprops/warningbanner.png" /&gt;&lt;/p&gt;

&lt;p&gt;Server properties can be edited on the "Continua Server - Properties" page located in the "Administration" section of Continua CI. See our documentation for &lt;a href="https://wiki.finalbuilder.com/x/BYDp"&gt;details on all the currently available server properties&lt;/a&gt;.&lt;/p&gt;
</description><guid isPermaLink="false">844</guid></item><item><title>Managing Delphi Version Info with FinalBuilder</title><link>https://www.finalbuilder.com/resources/blogs/postid/836/managing-delphi-version-info-with-finalbuilder</link><category>Delphi,FinalBuilder,Windows</category><pubDate>Wed, 26 Jun 2019 15:49:26 GMT</pubDate><description>&lt;p&gt;In this post, we'll take a look at the various options for managing and updating Version Info in Delphi projects using FinalBuilder.&lt;/p&gt;

&lt;h2&gt;Windows Version Info Primer&lt;/h2&gt;

&lt;p&gt;Windows Version Info (ie the version info shown in explorer) is stored in a &lt;a href="https://docs.microsoft.com/en-us/windows/desktop/menurc/versioninfo-resource" target="_blank"&gt;VERSIONINFO&lt;/a&gt; resource inside the executable (exe or dll). These resources are created by defining a .rc file, and compiling with either the windows resource compiler (rc.exe) or Delphi's provided resource compiler (brcc32 or cgrc depending on the delphi version). This results in a .res file, which can be linked into exe at compile time by referencing it in the source code, e.g :&lt;/p&gt;

&lt;pre class="brush:delphi; toolbar:false;"&gt;
{$R 'myresource.res'}&lt;/pre&gt;

&lt;p&gt;I highly recommend familiarising yourself with the VERSIONINFO resource type and it's parts.&lt;/p&gt;

&lt;h2&gt;Delphi IDE Support for Version Info&lt;/h2&gt;

&lt;p&gt;The Delphi IDE creates a [YourProjectName].res file next to the dpr or dpk when you create a new project. This is where the IDE will place the VERSIONINFO resource when you enable the option to "Include version information in project".  When you compile the project in the IDE, if needed the IDE will regenerate this res file with updated version info before it is linked into the executable.  For exe's, this resource file also includes the MAINICON resource (the icon shown in explorer).&lt;/p&gt;

&lt;p&gt;You do not have to use this feature, you can leave the option turned off and manage the version info yourself, by creating your own resource script (.rc) with a VERSIONINFO structure,  and compiling it and referencing the resulting .res file in your source code. You can even just reference the .rc file&lt;/p&gt;

&lt;pre class="brush:delphi; toolbar:false;"&gt;
{$R 'myresource.res' 'myresource.rc'}&lt;/pre&gt;

&lt;p&gt;and the IDE will compile the rc file and link in the resulting res file. The caveat to this technique is that the command line compiler (dcc32, dcc64 etc) does not support this. &lt;/p&gt;

&lt;p&gt;If your binary doesn't have version info, or has incorrect version info, it's typically because :&lt;/p&gt;

&lt;p&gt;1) The version info  resource wasn't referenced in the source and wasn't linked in&lt;br /&gt;
2) There are duplicate VERSIONINFO resources linked, windows will pick the first one it finds.&lt;br /&gt;
3) You set the version info on the wrong IDE configuration (more on this below). &lt;/p&gt;

&lt;p&gt;The Delphi IDE, along with the dproj file (which is an msbuild project file), uses a convoluted configuration inheritance mechanism to set project properties, including version info. Many a developer has been caught out by this scheme, setting the version info at the wrong node in the heirachy, resulting in no version info in their executables. There have also been issues with dproj files that have been upgraded through multiple versions of delphi over the years.&lt;/p&gt;

&lt;h2&gt;Using FinalBuilder&lt;/h2&gt;

&lt;p&gt;In the development environment, the version info usually doesn't matter too much, but for formal releases it's critical, so it's best to leave setting/updating your version info  to your &lt;a href="/finalbuilder" target="_blank"&gt;automated build tool&lt;/a&gt; or your &lt;a href="/continua-ci" target="_blank"&gt;continuous integration server&lt;/a&gt;. In FinalBuilder we have invested a lot of time and energy to making version info work correctly with all the different versions of delphi, dealing with the vagaries and subtle differences with each version (and there are many!).&lt;/p&gt;

&lt;p style="text-align: center;"&gt;&lt;img src="https://cdn.finalbuilder.com/blog/vincent/fbversioninfo/delphi-versioninfo-tab.png" /&gt;&lt;/p&gt;

&lt;p&gt;On the Delphi action in FinalBuilder, the Version Info tab presents the version info in a similar way to old versions of delphi IDE did (a much nice ui that the current version imho). This ui allows you control all the various version info properties (and there are a lot!). Note that these will only take effect if you have the "Regenerate resource" option checked on the Project tab (ie, regenerate yourproject.res). &lt;/p&gt;

&lt;p style="text-align: center;"&gt;&lt;img src="https://cdn.finalbuilder.com/blog/vincent/fbversioninfo/delphi-project-tab.png" /&gt;&lt;/p&gt;

&lt;p&gt;Note that the Major, Minor, Release and Build fields are number spin edits, and cannot take FinalBuilder variables. That can easily be worked around with some simple scripting, in the BeforeAction script event  (javascript):&lt;/p&gt;

&lt;p style="text-align: center;"&gt;&lt;img src="https://cdn.finalbuilder.com/blog/vincent/fbversioninfo/delphi-action-script.png" /&gt;&lt;/p&gt;

&lt;p&gt;Another option is to use &lt;a href="https://wiki.finalbuilder.com/display/FB8/Property+Sets" target="_blank"&gt;Property Sets&lt;/a&gt; to provide the source of the Version Info. Property sets are especially useful when you have multiple actions that need the same version info, or at least to share the same version numbers. Creating a Property Set is trivial, just drop a PropertySet Define action on your target, before the Delphi Action. In the PropertySet Define action, select Win32 Version Info to manage all version info properties, or Win32 Version Numbers to have the property set just manage the major, minor, release and build numbers.&lt;/p&gt;

&lt;p style="text-align: center;"&gt;&lt;img src="https://cdn.finalbuilder.com/blog/vincent/fbversioninfo/define-propertyset.png" /&gt;&lt;/p&gt;

&lt;p&gt;To set the property set values, add a PropertySet Assign Values action before the Delphi action.&lt;/p&gt;

&lt;p style="text-align: center;"&gt;&lt;img src="https://cdn.finalbuilder.com/blog/vincent/fbversioninfo/propset-assign.png" /&gt;&lt;/p&gt;

&lt;p&gt;Then in the Delphi action it's a simple task to select the property set in the version info tab&lt;/p&gt;

&lt;p style="text-align: center;"&gt;&lt;img src="https://cdn.finalbuilder.com/blog/vincent/fbversioninfo/delphi-use-propset.png" /&gt;&lt;/p&gt;

&lt;p&gt;Notice that the version number fields are disabled, since they are now provided by the property set. If you choose the Win32 Version Info property set type, more fields are disabled.&lt;/p&gt;

&lt;p&gt;One last thing I should mention, is that along with the Version Info and the MAINICON, the project.res file also typically (well for windows at least) contains the manifest file. I recommend you look at the Resource Compiler tab, where it lets you choose which resource compiler to use (more useful in older versions of delphi, where brcc32 didn't cope with some hicolor icon types) and specify the manifest file. I discussed &lt;a href="/resources/blogs/windows-manifest-files" target="_blank"&gt;windows manifest files a few years ago in this blog post&lt;/a&gt;.&lt;/p&gt;
</description><guid isPermaLink="false">836</guid></item><item><title>Visual Studio 2019 Preview Support</title><link>https://www.finalbuilder.com/resources/blogs/postid/833/visual-studio-2019-preview-support</link><category>FinalBuilder,Visual Studio</category><pubDate>Thu, 13 Dec 2018 11:45:35 GMT</pubDate><description>&lt;p&gt;Today we released a FinalBuilder 8 update with Visual Studio 2019 and MSBuild 16 Preview support. So far, for the most part Visual Studio 2019 seems to operate (well, from our point of view) pretty much the same as 2017. There were some changes to the MSBuild location, but other than that it all seems to work fine. Since it's based on the preview, it's subject to change and or breakage at any time.&lt;/p&gt;

&lt;p style="text-align: center;"&gt;&lt;img src="https://cdn.finalbuilder.com/blog/vincent/vs2019/vs2019.png" /&gt; &lt;/p&gt;
</description><guid isPermaLink="false">833</guid></item><item><title>Delphi 10.3 Rio - Language Changes</title><link>https://www.finalbuilder.com/resources/blogs/postid/832/delphi-103-rio-language-changes</link><category>Delphi,FinalBuilder</category><pubDate>Thu, 13 Dec 2018 11:12:39 GMT</pubDate><description>&lt;p&gt;Back in December 2016, I posted some ideas for some &lt;a href="/resources/blogs/delphi-language-enhancements"&gt;Delphi language enhancements&lt;/a&gt;. That post turned out to be somewhat controversial, I received some rather hostile emails about how I was trying to turn Delphi into C#. That certainly wasn't my intent, but rather to modernize Delphi, in a way that helps me write less, but more maintainable code. Nearly 2 years later, Delphi 10.3 Rio actually implements some of those features.&lt;/p&gt;

&lt;p&gt;I'm not going to claim credit for the new language features, and the syntax suggestions I made were pretty obvious ones, but I like to think I perhaps spurred them on a bit ;) My blog post had over 12K views, so there was certainly plenty of interest in new language features, and from what I have seen out there on the interwebs they have for the most part been well received.&lt;/p&gt;

&lt;p&gt;So lets take a look at which suggestions made the cut for 10.3 - referencing my original post.&lt;/p&gt;
&lt;style type="text/css"&gt;.featureTable {
        border: 1px solid #0071c5;
        border-collapse: collapse;
        width: 100%;
        margin-left: auto;
        margin-right: auto;
    }

    .featureTable thead {
        background-color: #0071c5;
        color: White;
    }

    .featureTable td {
        border: 1px solid #0071c5;
        padding: 5px;
    }
&lt;/style&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="featureTable"&gt;
	&lt;thead&gt;
		&lt;tr&gt;
			&lt;th&gt;Feature&lt;/th&gt;
			&lt;th&gt;Implemented&lt;/th&gt;
			&lt;th&gt;Comments&lt;/th&gt;
		&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
		&lt;tr&gt;
			&lt;td&gt;&lt;a href="/resources/blogs/delphi-language-enhancements#localvarinit" target="_blank"&gt;Local Variable Initialisation&lt;/a&gt;&lt;/td&gt;
			&lt;td&gt;No&lt;/td&gt;
			&lt;td&gt; &lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;&lt;a href="/resources/blogs/delphi-language-enhancements#typeinference" target="_blank"&gt;Type Inference&lt;/a&gt;&lt;/td&gt;
			&lt;td&gt;Yes!&lt;/td&gt;
			&lt;td&gt;For inline variables only, Confuses code insight!&lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;&lt;a href="/resources/blogs/delphi-language-enhancements#inlinevars" target="_blank"&gt;Inline variable declaration, with type inference and block scope&lt;/a&gt;&lt;/td&gt;
			&lt;td&gt;Yes, Yes and Yes!&lt;/td&gt;
			&lt;td&gt;Confuses code insight!&lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;&lt;a href="/resources/blogs/delphi-language-enhancements#loopvars" target="_blank"&gt;Loop variable inline declaration&lt;/a&gt;&lt;/td&gt;
			&lt;td&gt;Yes!&lt;/td&gt;
			&lt;td&gt;Confuses code insight!&lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;&lt;a href="/resources/blogs/delphi-language-enhancements#shortcutprops" target="_blank"&gt;Shortcut property declaration&lt;/a&gt;&lt;/td&gt;
			&lt;td&gt;No&lt;/td&gt;
			&lt;td&gt; &lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;&lt;a href="/resources/blogs/delphi-language-enhancements#interfacehelpers" target="_blank"&gt;Interface Helpers&lt;/a&gt;&lt;/td&gt;
			&lt;td&gt;No&lt;/td&gt;
			&lt;td&gt; &lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;&lt;a href="/resources/blogs/delphi-language-enhancements#nonordinalcase" target="_blank"&gt;Strings (and other non ordinals) in Case Statements&lt;/a&gt;&lt;/td&gt;
			&lt;td&gt;No&lt;/td&gt;
			&lt;td&gt; &lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;&lt;a href="/resources/blogs/delphi-language-enhancements#ternaryoperator" target="_blank"&gt;Ternary Operator&lt;/a&gt;&lt;/td&gt;
			&lt;td&gt;No&lt;/td&gt;
			&lt;td&gt; &lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;&lt;a href="/resources/blogs/delphi-language-enhancements#tryexceptfinally" target="_blank"&gt;Try/Except/Finally&lt;/a&gt;&lt;/td&gt;
			&lt;td&gt;No&lt;/td&gt;
			&lt;td&gt; &lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;&lt;a href="/resources/blogs/delphi-language-enhancements#namedargs" target="_blank"&gt;Named Arguments&lt;/a&gt;&lt;/td&gt;
			&lt;td&gt;No &lt;/td&gt;
			&lt;td&gt; &lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;&lt;a href="/resources/blogs/delphi-language-enhancements#varargs" target="_blank"&gt;Variable method arguments&lt;/a&gt;&lt;/td&gt;
			&lt;td&gt;No&lt;/td&gt;
			&lt;td&gt; &lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;&lt;a href="/resources/blogs/delphi-language-enhancements#lambdas" target="_blank"&gt;Lambdas&lt;/a&gt;&lt;/td&gt;
			&lt;td&gt;No&lt;/td&gt;
			&lt;td&gt; &lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;&lt;a href="/resources/blogs/delphi-language-enhancements#linq" target="_blank"&gt;Linq&lt;/a&gt;&lt;/td&gt;
			&lt;td&gt;No&lt;/td&gt;
			&lt;td&gt;Depends on lambdas and interface helpers.&lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;&lt;a href="/resources/blogs/delphi-language-enhancements#asyncawait" target="_blank"&gt;Async/Await&lt;/a&gt;&lt;/td&gt;
			&lt;td&gt;No&lt;/td&gt;
			&lt;td&gt; &lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;&lt;a href="/resources/blogs/delphi-language-enhancements#nonrefinterfaces" target="_blank"&gt;Non reference counted interfaces&lt;/a&gt;&lt;/td&gt;
			&lt;td&gt;No&lt;/td&gt;
			&lt;td&gt; &lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;&lt;a href="/resources/blogs/delphi-language-enhancements#attributeconstraints" target="_blank"&gt;Attribute Constraints&lt;/a&gt;&lt;/td&gt;
			&lt;td&gt;No&lt;/td&gt;
			&lt;td&gt; &lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;&lt;a href="/resources/blogs/delphi-language-enhancements#operatoroverloading" target="_blank"&gt;Operator overloading on classes.&lt;/a&gt;&lt;/td&gt;
			&lt;td&gt;No&lt;/td&gt;
			&lt;td&gt; &lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;&lt;a href="/resources/blogs/delphi-language-enhancements#genericonstraints" target="_blank"&gt;Improve Generic Constraint&lt;/a&gt;&lt;/td&gt;
			&lt;td&gt;No&lt;/td&gt;
			&lt;td&gt; &lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;&lt;a href="/resources/blogs/delphi-language-enhancements#fixienumerable" target="_blank"&gt;Fix IEnumerable &lt;t&gt;&lt;/t&gt; &lt;/a&gt;&lt;/td&gt;
			&lt;td&gt;No&lt;/td&gt;
			&lt;td&gt; &lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;&lt;a href="/resources/blogs/delphi-language-enhancements#yield" target="_blank"&gt;Yield return - Iterator blocks&lt;/a&gt;&lt;/td&gt;
			&lt;td&gt;No&lt;/td&gt;
			&lt;td&gt; &lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;&lt;a href="/resources/blogs/delphi-language-enhancements#partialclasses" target="_blank"&gt;Partial classes&lt;/a&gt;&lt;/td&gt;
			&lt;td&gt;No&lt;/td&gt;
			&lt;td&gt; &lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;&lt;a href="/resources/blogs/delphi-language-enhancements#multipleuses" target="_blank"&gt;Allow Multiple Uses clauses&lt;/a&gt;&lt;/td&gt;
			&lt;td&gt;No&lt;/td&gt;
			&lt;td&gt; &lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;&lt;a href="/resources/blogs/delphi-language-enhancements#interfacegenerics" target="_blank"&gt;Allow non parameterized interfaces to have parameterized methods&lt;/a&gt;&lt;/td&gt;
			&lt;td&gt;No&lt;/td&gt;
			&lt;td&gt; &lt;/td&gt;
		&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;So, 3 out of 23. To be honest, I was pleasantly surprised when I found out about them, given the pace of language change in the past. I'm hopeful this is just the start of things to come and we get to see Delphi evolve and catch up with other modern programming languages. I have a bunch of other language features I'd like to see, and received lots of suggestions from other users. &lt;/p&gt;

&lt;p&gt;We're still using Delphi XE7 for FinalBuilder 8, and I rarely change compiler versions during the life of a major product version. So I'll only get to use the new language features when I get fully stuck into FinalBuilder 9 &amp; Automise 6. I'm in the process of getting Delphi 10.3 compatible versions of all the third party libraries (commercial and open source) - as and long time delphi user will know, that's always more difficult than it should be!  &lt;/p&gt;
</description><guid isPermaLink="false">832</guid></item><item><title>Windows 10 Fall Creators Update</title><link>https://www.finalbuilder.com/resources/blogs/postid/756/windows-10-fall-creators-update</link><category>Automise,Delphi,FinalBuilder,Windows</category><pubDate>Tue, 17 Oct 2017 09:55:38 GMT</pubDate><description>The &lt;a href="https://blogs.windows.com/windowsexperience/2017/10/17/get-windows-10-fall-creators-update" title="How do I get the Fall Update?"&gt;Windows 10 Fall Creators Update has only been out a few hours&lt;/a&gt;, but we're already getting questions about it.&amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
In our limited testing, FinalBuilder 8 and Automise 5 run fine.&lt;br /&gt;
&lt;br /&gt;
I've only been running the Fall Update for a few hours, but so far I have not noticed any issues. The applications I use daily all run fine.&amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
The "Windows 10 Creators Update" (ie the one before the Fall Update - stupid release naming imho) &lt;a href="https://quality.embarcadero.com/browse/RSP-17972" title="Embarcadero issue tracker. Requires registration/login to view."&gt;broke the Delphi debugger&lt;/a&gt; when using runtime packages. Aparently the issue was caused by a library loader optiimisation, not taking into account that dll's can have multiple import tables. I never did see a full explaination or acknowledgement of the problem from Microsoft. &lt;br /&gt;
&lt;br /&gt;
This only affected the debugger (all native code debuggers, not just Delphi), which would load and unload each dll many times (based on the number of imports, for FinalBuilder's core package, it was in the hundreds). Sometimes the application would launch, only for the debugger to crash, sometimes it would just hang, sometimes the Delphi IDE would get out of memory errors.&amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
For me, this was a big issue, since FinalBuilder and Automise use runtime packages. This affected all versions of Delphi, even the latest 10.2 (Tokyo). Embarcadero did eventually ship an update to 10.2 that mostly resolved the problem (not an easy thing as it involved major linker changes), but that didn't help us as we're using an older version (for reasons I won't go into here!). &lt;br /&gt;
&lt;br /&gt;
So since April 2017, I've been really hamstrung when it comes to debugging. Fortunately we discovered the issue before the Creators Update was installed on our other Delphi development machines (and it's a been a constant battle with windows update nagging to install it ever since) so we were still able debug, just not on my dev machine. Frustrating to say the least.&amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
The good news is that the Fall Update (mostly) fixes the problem.&amp;nbsp; I still see some dlls/packages getting unloaded and reloaded again, but the application launches and I can debug.&amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
As far as windows functionality in the Fall Update goes, well the Task Manager has a new GPU section on the performance tab which is mildly interesting, but since I don't use a Pen, or wear a VR headset while working, I'm not noticing much to get excited about. Hopefully, it's just a lot of bug fixes and performance enhancements, minus the show stoppers!!&amp;nbsp;</description><guid isPermaLink="false">756</guid></item><item><title>Continuous Integration with FinalBuilder</title><link>https://www.finalbuilder.com/resources/blogs/postid/755/continuous-integration-with-finalbuilder</link><category>.NET,Continua CI,Delphi,FinalBuilder</category><pubDate>Wed, 20 Sep 2017 13:49:00 GMT</pubDate><description>&lt;p&gt;In this post, I'm going to look at how to structure a FinalBuilder project so that it will run on your dev machine, or on your Continua CI Server without modification. This allows the best of both worlds, develop and debug your build process on your development machine, and then later run it on your CI server.&lt;/p&gt;

&lt;p&gt;I'm going to assume you are familiar with FinalBuilder to speed this along.&lt;/p&gt;

&lt;h3&gt;Version Control&lt;/h3&gt;

&lt;p&gt;The very first thing we need to do is add our FinalBuilder project to our version control system. This will ensure that the Continua CI agent will be able to access the projects.&lt;/p&gt;

&lt;p&gt;We typically create a Build folder in each repository that has our FinalBuilder projects, installer scripts etc. Make sure you save your projects in uncompressed format (ie, .fbp8 for FinalBuilder 8), as that will make it possible to diff project file changes using your usual diff tool (we use Beyond Compare 4).&lt;/p&gt;

&lt;p&gt;So in a typical repository, you might have a folder structure that looks something like this :&lt;/p&gt;

&lt;pre&gt;
        \Build
        \Src
        \Docs
        \Help
        \Tools
        \Output
    &lt;/pre&gt;

&lt;p&gt;Note the Output folder is ignored by our version control system (via .gitignore or .hgignore for example). Don't forget to add ignores for the finalbuilder log file as you don't want to commit that to the repo.&lt;/p&gt;

&lt;p&gt;This is the file structure I'll be using as the example in this post.&lt;/p&gt;

&lt;h3&gt;Build Workspace&lt;/h3&gt;

&lt;p&gt;Continua CI runs each build in a separate, clean build workspace folder. The reason for this is to allow multiple builds of the same configuration to be run concurrently (for example, building different branches at the same time). This means our folder structure above will be rooted differently for each build. So to deal with this, we will define some FinalBuilder Project Variables.&lt;/p&gt;

&lt;h3&gt;FinalBuilder Variables&lt;/h3&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p style="text-align: center;"&gt;&lt;img alt="FinalBuilder Project Variables" src="https://cdn.finalbuilder.com/blog/vincent/ci-with-fb/fb-project-variables.png" /&gt;&lt;/p&gt;
&lt;!-- 
    &lt;table width="250px" style="text-align:left;border-collapse:collapse;"&gt;
        &lt;tr style="border-bottom: 1px solid #777"&gt;
            &lt;th width="30%"&gt;Name&lt;/th&gt;
            &lt;th width="20%"&gt;Type&lt;/th&gt;
            &lt;th width="40%"&gt;Default Value&lt;/th&gt;
            &lt;th width="10%"&gt;Macro&lt;/th&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;REPO&lt;/td&gt;
            &lt;td&gt;string&lt;/td&gt;
            &lt;td&gt;..&lt;/td&gt;
            &lt;td&gt;no&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;WORKSPACE&lt;/td&gt;
            &lt;td&gt;string&lt;/td&gt;
            &lt;td&gt;..&lt;/td&gt;
            &lt;td&gt;no&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;BUILD&lt;/td&gt;
            &lt;td&gt;string&lt;/td&gt;
            &lt;td&gt;%REPO%\Build&lt;/td&gt;
            &lt;td&gt;yes&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;SOURCE&lt;/td&gt;
            &lt;td&gt;string&lt;/td&gt;
            &lt;td&gt;%REPO%\Src&lt;/td&gt;
            &lt;td&gt;yes&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;LIBS&lt;/td&gt;
            &lt;td&gt;string&lt;/td&gt;
            &lt;td&gt;%REPO%\Libs&lt;/td&gt;
            &lt;td&gt;yes&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;OUTPUT&lt;/td&gt;
            &lt;td&gt;string&lt;/td&gt;
            &lt;td&gt;%WORKSPACE%\Output&lt;/td&gt;
            &lt;td&gt;yes&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;DOCS&lt;/td&gt;
            &lt;td&gt;string&lt;/td&gt;
            &lt;td&gt;%REPO%\Docs&lt;/td&gt;
            &lt;td&gt;yes&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;HELP&lt;/td&gt;
            &lt;td&gt;string&lt;/td&gt;
            &lt;td&gt;%REPO%\Help&lt;/td&gt;
            &lt;td&gt;yes&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;TOOLS&lt;/td&gt;
            &lt;td&gt;string&lt;/td&gt;
            &lt;td&gt;%REPO%\Tools&lt;/td&gt;
            &lt;td&gt;yes&lt;/td&gt;
        &lt;/tr&gt;
    &lt;/table&gt;
--&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;You can of course modify these variables to suite your needs. The REPO variable has a default value of "..", we will use the Path Manipulation action to expand that relative path when our build starts, using the FBPROJECTDIR variable as the base path. This will give us the root folder of our repository, which we can then use as the basis for other path variables.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Side Note:&lt;/strong&gt; FinalBuilder does not support using unrooted relative paths. The best practice is to fully expand the relative path before using it. Relative paths need to be relative to something, and in windows that is typically the Current Directory for the process, however this is not viable in a multi-threaded application. Rooted relative paths (e.g "%SOURCE%\.." ) will work in most cases, however some windows api functions do not support relative paths at all.&lt;/p&gt;

&lt;p&gt;The WORKSPACE variable will have the path to the Continua CI build workspace folder. Depending on how your repository and &lt;a href="https://docs.finalbuilder.com/ci/1.0/user-guide/stages/repository-rules.html"&gt;repository rules&lt;/a&gt; are structured, this might be different.&lt;/p&gt;

&lt;h3&gt;Repository Rules&lt;/h3&gt;

&lt;p&gt;Continua CI configurations can have multiple &lt;a href="https://docs.finalbuilder.com/ci/1.0/user-guide/repositories/repositories.html"&gt;Repositories&lt;/a&gt; assigned to them, for example when building FinalBuilder, we have mulitple repos on the configuration, one for our source and three others for libraries. On our dev machines, we use symlinks to map the libs folder into our main repo's path, so we end up with :&lt;/p&gt;

&lt;pre&gt;
        MainRepo\Src
        MainRepo\Libs &lt;- symlink to LibsRepo\
    &lt;/pre&gt;

&lt;p&gt;This makes it easier to deal with search paths in Delphi, as we can just use simple relative paths. With .Net, working with libraries is so much simpler due to package managers like nuget or packet.&lt;/p&gt;

&lt;p&gt;At the start of a Continua CI Stage, the source code is exported from the Repository Cache (a Mercurial repo) for each repository associated with the Configuration. How and what gets exported is controlled by the Repository Rules for that Stage.&lt;/p&gt;

&lt;p&gt;The default rules looks like this :&lt;/p&gt;

&lt;pre&gt;
        $Source$ &gt;&gt; Source
    &lt;/pre&gt;

&lt;p&gt;This will export all associated repos to a folder structure like this&lt;/p&gt;

&lt;pre&gt;
        workspace\source\repo1
        workspace\source\repo2
    &lt;/pre&gt;

&lt;p&gt;In this example, I'm going to change the rules to mirror the folder structure on our dev machines :&lt;/p&gt;

&lt;p style="text-align: center;"&gt;&lt;img alt="Repository Rules" src="https://cdn.finalbuilder.com/blog/vincent/ci-with-fb/repo-rules.png" /&gt;&lt;/p&gt;

&lt;p&gt;This results in the following folder structure :&lt;/p&gt;

&lt;pre&gt;
        workspace\build
        workspace\src
        workspace\libs
    &lt;/pre&gt;

&lt;p&gt;Note that you can also use rules to limit which parts of the repository are exported to the workspace, so, for example, if you have files in the repository that are not needed for the build process, you can avoid exporting them and save some time (I/O is usually the biggest overhead) using exclusion rules.&lt;/p&gt;

&lt;p&gt;Getting back to our FinalBuilder variables, we can see from the above folder structure, that our WORKSPACE variable will have the same value as the REPO variable. If your folder structure is different then you will need to adjust accordingly.&lt;/p&gt;

&lt;h3&gt;Continua CI Stage Actions&lt;/h3&gt;

&lt;p&gt;Ok, so now we have a basic FinalBuilder project, and Repository Rules set up to export our source to the build workspace, now it's time to call FinalBuilder. Continua CI has a FinalBuilder Action for doing just that.&lt;/p&gt;

&lt;p style="text-align: center;"&gt;&lt;img alt="Continua CI - FinalBuilder Action" src="https://cdn.finalbuilder.com/blog/vincent/ci-with-fb/fbaction.png" /&gt;&lt;/p&gt;

&lt;p&gt;We need to tell the action where our FinalBuilder project file lives. This needs to be anchored by the workspace folder, e.g $Workspace$\Build\FB\FinalBuilderBuild.fbp8&lt;/p&gt;

&lt;p&gt;In the Variables tab, we will check the "Automatically apply Continua CI variable values to matching FinalBuilder variables." Option. If you want to send any protected Continua variables (ie passwords, api keys etc) to FinalBuilder, then check the "Save sensitive variable values to context XML file for use by FinalBuilder." option as well. Lastly, on the Environment Variables tab, we are passing some environment variables that are used in delphi search paths to FinalBuilder.&lt;/p&gt;

&lt;p style="text-align: center;"&gt;&lt;img alt="Continua CI - FinalBuilder Action" src="https://cdn.finalbuilder.com/blog/vincent/ci-with-fb/fbaction-variables.png" /&gt;&lt;/p&gt;

&lt;p&gt;We also set some environment variables that are needed for our build process, Continua CI makes this painless.&lt;/p&gt;

&lt;p style="text-align: center;"&gt;&lt;img alt="Continua CI - Set Environment Variables" src="https://cdn.finalbuilder.com/blog/vincent/ci-with-fb/fbaction-env.png" /&gt;&lt;/p&gt;

&lt;h3&gt;FinalBuilder Project&lt;/h3&gt;

&lt;p&gt;Remember that we want to be able to run the project on our dev machine and from Continua CI. So some logic is required to make sure it behaves the same way in both environments.&lt;/p&gt;

&lt;p&gt;I added some targets to the project, Init, Build and Test.&lt;/p&gt;

&lt;p&gt;The Init target is a dependency of the Default target, so it will always run first. This is where we initialise the variables, detect if the project is running from Continua CI or not, and set version info. We also create the Output folder here.&lt;/p&gt;

&lt;p style="text-align: center;"&gt;&lt;img alt="FinalBuilder - Init Target" src="https://cdn.finalbuilder.com/blog/vincent/ci-with-fb/fb-init-target.png" /&gt;&lt;/p&gt;

&lt;p&gt;Back in the Default target, we call the Build and Test targets. This is wrapped in a try/finally block and we export the FinalBuilder log file to %OUTPUT%\BuildLog.html in the finally section. We can register this file as an artifact and create a report definition in Continua CI to make it easy to view in the Continua CI UI. I've covered this before in an &lt;a href="/resources/blogs/adding-custom-reports-to-continua-ci-build-results"&gt;earlier blog post&lt;/a&gt;, so I won't cover it here.&lt;/p&gt;

&lt;p style="text-align: center;"&gt;&lt;img alt="FinalBuilder - Init Target" src="https://cdn.finalbuilder.com/blog/vincent/ci-with-fb/fb-default-target.png" /&gt;&lt;/p&gt;

&lt;p&gt;Note that you don't have to do the whole build/test/deploy all in one FinalBuilder project. When building FinalBuilder, we do the build &amp; test in one project, and the deploy in another that is called from the Deploy stage. This avoids the temptation to deploy from a developer workstation!&lt;/p&gt;

&lt;p&gt;When we build Continua CI (on Continua CI of course), we have separate Build, Obfuscate, Test, Package &amp; Deploy Stages that use different FinalBuilder projects. This allows us to run different parts of the build process on different agent machines. The .net obfuscation tool we use is very expensive, so we only have a single license which is installed on one agent machine, so the obfuscation stage will only run on that agent machine (vm). Continua CI selects the best agent based on agent properties and the Stages Agent Requirements. I'll cover this in more detail in another blog post.&lt;/p&gt;

&lt;p&gt;I have added this example project to the &lt;a href="https://github.com/VSoftTechnologies/FinalBuilder.Examples"&gt;Examples repository on GitHub&lt;/a&gt;.&lt;/p&gt;
</description><guid isPermaLink="false">755</guid></item><item><title>Continuous Integration Server performance</title><link>https://www.finalbuilder.com/resources/blogs/postid/754/continuous-integration-server-performance</link><category>.NET,Continua CI,Delphi,FinalBuilder,Git,Mercurial,Web Development</category><pubDate>Mon, 11 Sep 2017 14:31:58 GMT</pubDate><description>&lt;p&gt;Continuous Integration Servers are often underspecified when it comes to hardware. In the early days of Automated Builds, the build server was quite often that old pc in the corner of the office, or an old server in the data center that no one else wanted.
Developers weren't doing many builds per day, so it worked, it was probably slow but that didn't seem to matter much.&lt;/p&gt;
&lt;p&gt;Fast forward 20 years, and the Continuous Integration Server is now a critical service. The volume and frequency of builds has increased dramatically and a slow CI server can be a real problem in an environment where we want fast feedback on that code
we just committed (even though it "worked on my machine"). Continuous Deployment only adds to the workload of the CI server.&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;In this post, I'm going to cover off some ideas to hopefully improve the performance of your CI server. I'm not going to cover compilation, unit tests etc. (which can be where a lot of the time is spent). Instead, I'll focus on the environment, machine
configuration and some settings on your Continua CI configurations.&lt;/p&gt;
&lt;h2&gt;Hardware Requirements&lt;/h2&gt;
&lt;p&gt;It's impossible to provide hard and fast specs for hardware or virtual machines, as it varies greatly depending on the expected load.&lt;/p&gt;
&lt;p&gt;There are a bunch of things you can tweak that may improve performance. I will touch on some key points for virtual hosts, but I'm not going to go too deep into tuning virtual hosts, that's not my area of expertise. Of course, dedicated physical machines
would be the ideal, but these days, even if you do get dedicated hardware for CI/CD, it's most likely going to be as a virtual host (hyper-v or vmware) rather than an OS installed on bare metal (do companies still provision a single os on bare metal
servers these days?). Virtualisation brings in a whole bunch of benefits, but it also brings with it some limitations that cannot be ignored.&lt;/p&gt;
&lt;p&gt;Continuous Integration environments are mostly I/O bound and Continua CI is no different in that regard. So let's look at the various resources used by CI/CD.&lt;/p&gt;
&lt;h3&gt;CPU&lt;/h3&gt;
&lt;p&gt;It's unlikely that CPU will be a limiting factor in the performance of your CI server, unless you are running other CPU intensive tasks on your server. If that's the case, then move your CI server to dedicated hardware, or at least a dedicated virtual
host.
&lt;/p&gt;
&lt;p&gt;At a minimum you should have at least 2 cores on the server. On our production server, which is a virtual machine (on Hyper-V 2012R2) with 4 virtual cores and dynamic RAM, the Windows resource monitor shows that average CPU usage usually sits around 2%
when idle (no running builds, measured on the guest OS using resource monitor on the Continua Server Service). With 10 concurrent builds running, the Continua CI server service was using around 6% cpu.&lt;/p&gt;
&lt;p&gt;Adding another 4 cores made very little difference. The Hyper-V host machine, which is also running a bunch of agent VM's, has plenty of CPU capacity, with the average CPU usage round 5-7%. Cutting down the number of cores to 2 did make a slight difference,
with the VM showing slightly higher CPU usage, however no discernible difference in build times.&lt;/p&gt;
&lt;p&gt; This is obviously not very scientific, but it did demonstrate (well to me at least) that CPU is not the limiting factor. I set the server VM back to 4 cores and left it at that. Our Hyper-V host machines are a few years old now, and have 7200 rpm SAS
hard drives (in Raid 10) rather than SSD's (they were still too expensive when we bought the machines).&lt;/p&gt;
&lt;p&gt;On a Continua CI Agent, we recommend at least 2 cpu cores, and limit the concurrent builds running on the agent to 1 per core. This isn't a hard and fast rule, just a convention we adhere to here (based on some performance testing). You may want to add
extra cores depending on what compilers or tools you are running during your build process. The only way to know if this is needed is to monitor cpu on the agent machine while a build is running.&lt;/p&gt;
&lt;h3&gt;I/O&lt;/h3&gt;
&lt;p&gt;The most used resources are disk read/write and network read/write. Poor I/O performance will really slow down your builds.&lt;/p&gt;
&lt;h4&gt;Disk&lt;/h4&gt;
&lt;p&gt;It goes without saying, but use the fastest disks you have available to you. If you can afford it, new generation nvme/pcie SSD's are the way to go. They are still quite expensive for larger capacities though. At the very least, use a separate disk for
the operating system and software installation, and another disk for your Continua CI Server's share folder (or the agents workspace folder on agent machines). This is where most of the I/O happens during builds. This recommendation applies whether
running on dedicated hardware or in a virtual machine.&lt;/p&gt;
&lt;p&gt;
If you are running the server and agent machines on the same virtual host (as we do for our production environment) then this is very important to get right. Poor I/O performance in virtualised environments is not uncommon - having agents and the server
fighting for a slice of the same I/O pie is not a good idea.&lt;br /&gt;
&lt;br /&gt;
On the agent machines, good disk performance is critical. When a build is started on the agent, the first thing it does is create a workspace folder. It then exports the source code from the repository cache(s) (Mercurial repo which was cloned
from the server) to that folder, using the repository rules (more on this later). This workspace initialisation phase can be very slow if you have poor I/O performance.&lt;/p&gt;
&lt;h4&gt;Network&lt;/h4&gt;
&lt;p&gt;Continua CI uses networking to transfer files, repository changes etc between the server and the agents. Poor network performance will impact on build initialisation times (updating the agents repo cache, build workspace) and on build completion times
(transferring workspace changes back to the server). Logging between the agent and the server will also be impacted by poor network performance.&lt;/p&gt;
&lt;p&gt;By default, Continua CI uses SMB to transfer files, source code (repository caches) between the server and the agents. When the server's share folder is not accessible by SMB, Continua CI will try to use SSH/SFTP (Continua CI installs it own specialised
SSH service). In high latency networks (for example if the agent is remote from the server), SSH/SFTP may perform better than SMB.&lt;/p&gt;
&lt;p&gt;You can force an agent to use SSH/SFTP by setting the agents ServerFileTransport.ForceSSH property to true.&lt;/p&gt;
&lt;h3&gt;Database&lt;/h3&gt;
&lt;p&gt;Continua CI supports PostgreSQL (the default) or Microsoft SQL Server. If you chose to use MSSQL, we recommend running it on a separate well specified machine. MSSQL is quite heavy in it's use of RAM and disk I/O - it's best run on a machine that has
been tuned to run it properly. I'm not going to go into that here, that's a whole other topic on an area that I'm definitely not an expert.&lt;/p&gt;
&lt;p&gt;The PostgreSQL database server that is installed by default (unless you select otherwise) with Continua CI is much more more frugal when it comes to resources. On our main Continua CI server, PostgreSQL typically using around 60MB of ram. Contrast that
with SQL Server running on my dev machine, not used or touched for weeks and it's using 800MB! PostgreSQL can also be tuned, we have tried to provision it with sensible defaults that strike a balance between performance and resource usage. If you
need to tune PostgreSQL, then we recommend installing your own PostgreSQL instance and pointing Continua CI at it.&lt;/p&gt;
&lt;p&gt;Currently the Continua CI installer doesn't provide any options for the database install location (C:\ProgramData\VSoft\ContinuaCI\PostgreSQLDB ), this is something we are looking at for a future release, that will make it possible to put the database
on it's own drive. For now, it's possible to move the database to another location by using a symlink, we have a few customers who have done this successfully. Contact support if you need help with this.&lt;/p&gt;
&lt;h2&gt;Virtualisation Tips&lt;/h2&gt;
&lt;h3&gt;Virtual CPU Cores&lt;/h3&gt;
&lt;p&gt;In a virtual environment, it's very important not to overload your virtual host. Note that there is a difference between overloading and over allocating virtual cores. It's a common practice to allocate more virtual cores across the virtual machines than
there are physical/logical cores (logical when HyperThreading is enabled), but this has to be done with the knowledge and understanding of the load on the host machine. Overloading happens when so many cores are allocated and in use that the hypervisor
is unable to schedule a core to a virtual machine when needed. This results in pauses and poor performance.&lt;/p&gt;
&lt;p&gt;In a clustered environment this is even more important, because when a cluster node dies, or is removed for upgrades etc, virtual machines will move to another node in the cluster - if that node is already overloaded then you will soon start hearing the
complaints from users!&lt;/p&gt;
&lt;p&gt;The best explanation I have found on how hypervisors allocate cores is this article - &lt;a href="https://www.altaro.com/hyper-v/hyper-v-virtual-cpus-explained/"&gt;https://www.altaro.com/hyper-v/hyper-v-virtual-cpus-explained/&lt;/a&gt; - it's Hyper-V specific (we
use Hyper-V here) but much of the information also applies to VMWare.&lt;/p&gt;
&lt;h3&gt;Virtual Disks&lt;/h3&gt;
&lt;p&gt;When creating separate virtual disk volumes for your virtual machines, try to put those virtual drives on different physical drives, so they are not competing for the same I/O. Use fixed size virtual disks.&lt;/p&gt;
&lt;h2&gt;Continua CI Configuration Tuning&lt;/h2&gt;
&lt;p&gt;Continua CI is not immune to performance problems, we're always working to make it faster and consume less resources. There are however a few things that can be tuned in Continua CI to improve performance.&lt;/p&gt;
&lt;h3&gt;Repository Branch Settings&lt;/h3&gt;
&lt;p&gt;Use specific branch patterns to narrow down the number of repository files and folders which are monitored and downloaded. With repositories which use folder-based branches, such as Subversion and TFS, consider moving old branches to a separate archive
folder in your repository which will not match the branch patterns. Note that you can use more than one Continua CI repository per actual repository. Some users will have multiple projects in one repository, but only need to build a single one for
each configuration. Make use of relative paths, where supported by your repository type, to limit your repository to a single project folder. This can significantly speed up repository initialisation and changeset updating. &lt;/p&gt;
&lt;h3&gt;Repository Polling&lt;/h3&gt;
&lt;p&gt;Continua CI polls repositories periodically to detect new commits. Each time this occurs, Continua CI invokes the command line client for that repo, and parses the output of that process. Some clients use a surprising amount of CPU. The git client, for
example, uses around 8% CPU per instance on our production server while checking for commits. Most of the time, these processes only run for a very short amount of time (when no changes are detected), however if you have a lot of repositories, these
small cpu spikes can add up.&lt;/p&gt;
&lt;p&gt; There are a couple of options to keep this under control.&lt;/p&gt;
&lt;p&gt; 1) Set the appropriate polling interval for your repositories. If changes to a repository occur infrequently, then there's no point polling frequently.&lt;/p&gt;
&lt;p&gt;2) Set the Server property Server.RepoMonitor.MaxCheckers property. This controls how many version control client processes are spawned concurrently, the default (5) is quite conservative so you should only need to lower this on a very low spec system.
If you have plenty of spare CPU capacity, then you can increase this value, however if you do then monitor CPU usage to make sure you don't overload the server.&lt;/p&gt;
&lt;p&gt;3) Manual polling, using post commit hooks. This reduces CPU usage on the server, by only polling for repository changes when requested and has the added benefit of reducing the load on your version control server. This does take some setting up, and
depends very much on the capabilities of your version control system. I'll take a look at post commit hooks in a future blog post.&lt;/p&gt;
&lt;h3&gt;Repository Path Filtering&lt;/h3&gt;
&lt;p&gt;Repository Path Filtering is an option on all repository types, with the exception of Mercurial (*I'll explain why shortly). What this filtering does is allow you to limit which files get added to the server's repository cache. This filtering has a few
benefits, less disk space used on the server and the agents, less network I/O when transferring the changes from the server to the agent, and less I/O when checking out the source into the build workspace.&lt;/p&gt;
&lt;p&gt;A typical use case for these rules is when you have files in your repository that rarely change and are not needed for the build process (design docs, deployment notes etc). No point adding them to the repo cache if you don't use them.&lt;/p&gt;
&lt;p&gt;Changes to these rules won't affect files that are already in the repository cache, but it will avoid committing changes to those filtered out files to the repo cache. The best bang for buck with these filters will come if the repository is reset (the
cache is rebuilt, so filtered out files are never committed to the cache), however that can be an expensive operation, so unlike other repository settings, changing these rules will not force a reset.&lt;/p&gt;
&lt;p&gt;* These filters don't apply to Mercurial repositories, as we use Mercurial for our repository cache. When you point Continua CI at a Mercurial repository, it just clones it to the server (repo cache), and then clones it to the agents (repo cache) without
any modifcations.&lt;/p&gt;
&lt;h3&gt;Repository Rules&lt;/h3&gt;
&lt;p&gt;Each Stage has a settings tab called Repository Rules. These rules apply when checking out the source from the agent's repository cache(s) to the build workspace. Only check out the source you need, this will improve performance. If a stage doesn't need
the source at all (for example, it's only working with artifacts from previous stages), then just blank out the Repository Rules field.&lt;/p&gt;
&lt;p&gt;Don't leave logging of the repository rules turned on unless you are debugging the rules. Logging the files exported to the workspace can be a real performance killer.&lt;/p&gt;
&lt;h3&gt;Workspace Rules&lt;/h3&gt;
&lt;p&gt;Similar to Repository Rules, these rules control which files are transferred between the server and agent's build workspace folders, and back again. Only transfer files back to the server's workspace that you actually need, like build artifacts, reports
etc.
&lt;/p&gt;
&lt;p&gt;Don't leave logging of the workspace rules turned on unless you are debugging the rules. Logging the files transferred can be a real performance killer.&lt;/p&gt;
&lt;h3&gt;Actions&lt;/h3&gt;
&lt;p&gt;Avoid logging too much information. For example, verbose logging on MSBuild should be avoided unless debugging build issues. Output logged from actions is queued and sent back to the server to be written to the build log, this causes high network and
disk I/O.&lt;/p&gt;
&lt;h3&gt;Disk Space&lt;/h3&gt;
&lt;p&gt;Disk space is quite often at a premium (especially with SSD's), and it's important to keep on top of it. This is where the Clean up Policies come into play. Continua CI allows you to specify a global clean up policy for both the server and the agents,
however it can be overridden at the Project or Configuration level. The clean up policy controls how long to keep old builds and their associated workspaces around. The clean up policy is highly configurable - use it to keep control over disk space.
Bear in mind that the work of cleaning up old builds is quite I/O and database intensive, so be sure to schedule it to run during a quite period&lt;/p&gt;
&lt;h3&gt;Anti-virus Software&lt;/h3&gt;
&lt;p&gt;Anti-virus software can be a major performance killer, and in instances, an application killer. If I had a dollar for every time anti-virus software turned out to be the cause of a problem with Continua CI or FinalBuilder, well that would be some serious
beer money at least!&lt;/p&gt;
&lt;p&gt;If you have anti-virus software installed on your server or agents, be sure to add exclusions from real-time scanning for the server's share folder, and the agent's workspace folder. Add scheduled scans on those folders instead. Also, when using the bundled
PostgreSQL database, add an exclusion for C:\ProgramData\VSoft\ContinuaCI\PostgreSQLDB &amp;nbsp;- otherwise you may experience database corruption.&lt;/p&gt;
&lt;p&gt;You should also consider adding an exclusions for the hg.exe in the "C:\Program Files\VSoft Technologies\ContinuaCI Agent\hg" folder. We found in testing that this will speed up the processing of the repostiory rules substantially (testing with windows
defender).
&lt;/p&gt;
&lt;h3&gt;Version Control Clients&lt;/h3&gt;
&lt;p&gt;Avoid installing tools like TortoiseSVN or ToirtoiseHG on your server or agent machines as these programs do background indexing (for icon overlays) and can also cause file/folder access issues.&lt;/p&gt;
&lt;h2&gt;Wrapping Up&lt;/h2&gt;
&lt;p&gt;I intend to revise this post as I learn more about performance tuning, especially in a virtual environment. If you have any techniques or tweaks that helped speed up your CI Server please feel free to share them with us (and fellow users).&lt;/p&gt;</description><guid isPermaLink="false">754</guid></item><item><title>Windows Manifest Files</title><link>https://www.finalbuilder.com/resources/blogs/postid/753/windows-manifest-files</link><category>Delphi,FinalBuilder,XML</category><pubDate>Mon, 28 Aug 2017 12:35:00 GMT</pubDate><description>&lt;p&gt;In this post I'm going to look at Windows Manifest Files, what they do, why we need them and how to use them in Delphi and FinalBuilder.&lt;/p&gt;

&lt;p&gt;We often get asked questions about UAC prompts, High DPI settings, Windows Themes etc when compiling Delphi &amp; C++Builder projects in FinalBuilder. In this post we'll dissect windows manifest files, and look at how the project settings in Rad Studio interact with the manifest file, and why you should use a custom manifest file.&lt;/p&gt;

&lt;h3&gt;What is a manifest file and what's it for?&lt;/h3&gt;

&lt;p&gt;A manifest is an xml file, which is typically embedded as a resource (it can be a separate file, but it's not a good practice and is not recommended) in your native windows executable (x86 or x64). This file has information that tells windows (vista or later) what parts of windows it supports, what permissions it needs (UAC), what common control dependencies it has (&lt;a href="https://en.wikipedia.org/wiki/Side-by-side_assembly" target="_blank"&gt;Windows Side-by-Side loading&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Without a manifest resource, windows has no idea what permissions your application needs, and will not treat your application kindly. You will find things like common controls (file dialogs etc) look strange, attempts to write to files failing and other general misery. In fact your application may fail to run at all on some systems.&lt;/p&gt;

&lt;p&gt;Ok, so now we know we really need a manifest, what does that look like.&lt;/p&gt;

&lt;pre class="brush:xml; toolbar:false;"&gt;
&lt;assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3"&gt;
    &lt;assemblyIdentity 
        name="VSoftTechnologies.FinalBuilder" 
        processorArchitecture="x86" 
        version="8.0.0.0" 
        type="win32"
    /&gt;
    &lt;description&gt;FinalBuilder is a GUI-based build automation tool for Windows developers.&lt;/description&gt;
    &lt;dependency&gt;
        &lt;dependentAssembly&gt;
            &lt;assemblyIdentity 
                type="win32"    
                name="Microsoft.Windows.Common-Controls" 
                version="6.0.0.0"
                processorArchitecture="x86" 
                publicKeyToken="6595b64144ccf1df" 
                language="*" 
            /&gt;
        &lt;/dependentAssembly&gt;
    &lt;/dependency&gt;
    &lt;trustInfo xmlns="urn:schemas-microsoft-com:asm.v2"&gt;
        &lt;security&gt;
            &lt;requestedPrivileges&gt;
                &lt;requestedExecutionLevel level="asInvoker" uiAccess="false" /&gt;
            &lt;/requestedPrivileges&gt;
         &lt;/security&gt;
    &lt;/trustInfo&gt;
    &lt;compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"&gt;
        &lt;application&gt;
            
            &lt;supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/&gt; 
            
            &lt;supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/&gt;
            
            &lt;supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/&gt;
            
            &lt;supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/&gt;
            
            &lt;supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/&gt;
        &lt;/application&gt;
    &lt;/compatibility&gt;
&lt;/assembly&gt;
&lt;/pre&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;The above example is actually the manifest file used in the FinalBuilder IDE. Lets break it down.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h4&gt;AssemblyIdentity&lt;/h4&gt;

&lt;p&gt;The assemblyIdentity tells windows about your application and what the system architecture requirements are. This should be unique. Note that the type, name and version attributes are required. Typically, the version field just has the major version info, I guess you could update it with the exact version each time, but I've never found the need to do that.&lt;/p&gt;

&lt;h4&gt;Description&lt;/h4&gt;

&lt;p&gt;The description field is pretty self explanatory.&lt;/p&gt;

&lt;h4&gt;Dependency&lt;/h4&gt;

&lt;p&gt;The dependency section is where you describe the side by side dll dependencies, which for Delphi/C++ Builder applications means windows common controls. This is pretty standard stuff, but it's important because without it, your application will have pretty strange looking file dialogs, if it loads at all.&lt;/p&gt;

&lt;h4&gt;TrustInfo&lt;/h4&gt;

&lt;p&gt;The trustinfo section is all about security, it tells windows what sort of permissions your application should be given. The requestedExecutionLevel level attribute has 3 possible values :&lt;/p&gt;

&lt;ul&gt;
	&lt;li&gt;&lt;strong&gt;asInvoker&lt;/strong&gt; - requesting no additional permissions. This level requires no additional trust prompts.&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;highestAvailable&lt;/strong&gt; - requesting the highest permissions available to the parent process. When a standard user runs the application, it will behave the same as asInvoker, ie no UAC prompt. If an administrator runs the application, they will see a UAC prompt.&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;requireAdministrator&lt;/strong&gt; - requesting full administrator permissions. All users will see a UAC prompt, standard users will be required to enter an administrator password.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;The uiAccess attribute Indicates whether the application requires access to protected user interface elements. Most of the time, this should be set to false. The typical use case for setting it to true is when creating remote desktop style application (like teamviewer etc). If you do set it to true, your application needs to be signed - see this post for code signing in FinalBuilder(&lt;a href="/resources/blogs/code-signing-changes-for-2016"&gt;https://www.finalbuilder.com/resources/blogs/code-signing-changes-for-2016&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h4&gt;High DPI support.&lt;/h4&gt;

&lt;p&gt;I'm not going go into to detail on this, it's a complex issue with major differences between windows versions, and limited High DPI support in Delphi. I will say, think very carefully before you enable this, High DPI support in Delphi depends very much on the version of delphi, and third party control support. Don't just enable High DPI support without serious testing. See the msdn doco link at the bottom of this post.&lt;/p&gt;

&lt;h4&gt;Compatibility&lt;/h4&gt;

&lt;p&gt;The compatibility section tells windows what versions of windows your application supports. It enables windows functionality in your application. Manifests without a compatibility section default to Windows Vista level functionality.&lt;/p&gt;

&lt;p&gt;One of the areas where the compatibility section is very important is detecting the windows version. On Windows 8.1 and 10, in applications that do not specify compatibility with them, GetVersion and GetVersionEx will return 6.2.0.0 for the windows version, rather than 6.3.* for Windows 8.1 and 10.0.* for Windows 10. So your application will think it's running on Windows 8 (or Server 2012) and quite possibly disable functionality.&lt;/p&gt;

&lt;h4&gt;Don't use Rad Studio's default or auto generated manifest!&lt;/h4&gt;

&lt;p&gt;I'll explain why in a minute, but first lets look at delphi's support for manifests. Delphi's manifest support differs quite a lot depending on which version of Delphi you are using. I don't have every version installed to check on.&lt;/p&gt;

&lt;p&gt;The earliest version I have installed at the moment is D2010, which just has a cryptically named check box :&lt;/p&gt;

&lt;p style="text-align: center;"&gt;&lt;img alt="" src="https://cdn.finalbuilder.com/blog/vincent/windows-manifest/d2010-enable-themes.png" /&gt;&lt;/p&gt;

&lt;p&gt;This option will include a default manifest in the projectname.res file. No options to change anything about that manifest. The manifest included is woefully inadequate.&lt;/p&gt;

&lt;h5&gt;Fast forward to XE7 :&lt;/h5&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p style="text-align: center;"&gt;&lt;img alt="" src="https://cdn.finalbuilder.com/blog/vincent/windows-manifest/xe7-enable-themes.png" /&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;Things got slightly better (not sure in which XE? version though) as you can now point Rad Studio at a custom manifest file (and you should!) to be included with your application. The default manifest included is still woefully inadequate.&lt;/p&gt;

&lt;h5&gt;Fast forward again, to Seattle:&lt;/h5&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p style="text-align: center;"&gt;&lt;img alt="" src="https://cdn.finalbuilder.com/blog/vincent/windows-manifest/seattle-manifest-file.png" /&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;Things look different again here, now you can set the badly named "Enable High DPI" and "Enable Administrator Privileges" options. I say badly named, because that's not what those options do. Checking "Enable High DPI" won't make your application support High DPI, it just tells windows it does (when really, it doesn't unless embarcadero fixed it while I wasn't looking). The same applies to the "Enable Administrator Privileges" - it won't give your application Administrator Privileges, it just tells windows your application needs them to run. Semantics shemantics... but I know this has confused many a developer.&lt;/p&gt;

&lt;p&gt;Note that the auto generated manifest uses a template, default_app.manifest, which lives in the bin folder, which is typically under program files, so you might need admin access to modify. It's probably a bad idea to modify it anyway, as it will result in a "works on my machine" moment. This template is different in Seattle and later, as it has some "variables" that get substituted by the IDE when building, this file can't be used when building with FinalBuilder as we have no way to get at those variables.&lt;/p&gt;

&lt;p&gt;The manifest included is slightly better than before, but still inadequate.&lt;/p&gt;

&lt;p&gt;Berlin &amp; Tokyo manifest options are the same as Seattle, just some layout/styling changes. The auto generated manifests have the same limitations as Seattle.&lt;/p&gt;

&lt;p&gt;So I said earlier, "Don't use Rad Studio's default or auto generated manifest", and said that the auto generated manifests are inadequate, here's why : they are simply missing information.&lt;/p&gt;

&lt;p&gt;There's no assemblyIdentity element, which according to microsoft is required. There's no description element. The High DPI option just sets the dpiAware element to "True/PM", or not at all. You should use a manifest file that is specific to and reflects your application.&lt;/p&gt;

&lt;p&gt;For the versions of Rad Studio that support specifying a custom manifest file, just do that. For versions without custom manifest support, uncheck the "Enable runtime themes" option, and add a resource to your project that includes the manifest :&lt;/p&gt;

&lt;p&gt;Example manifest.rc&lt;/p&gt;

&lt;pre class="brush:delphi; gutter:false; toolbar:false; "&gt;
1 24 "E:\\Source\\app\\myapp.manifest"
&lt;/pre&gt;

&lt;h3&gt;Using Manifests in FinalBuilder&lt;/h3&gt;

&lt;p&gt;FinalBuilder has had support for manifest files for a long time (2007, in FB 5), way before Delphi mentioned the word manifest! On the resource compiler tab of the Delphi and C++Builder actions, there is a field to specify the manifest file.&lt;/p&gt;

&lt;p style="text-align: center;"&gt;&lt;img alt="" src="https://cdn.finalbuilder.com/blog/vincent/windows-manifest/fb8-resource-tab.png" /&gt;&lt;/p&gt;

&lt;p&gt;That's all there is to it, FinalBuilder will add that manifest to the projectname.res file (along with the icon and version info).&lt;/p&gt;

&lt;p&gt;One last thing, don't forget to add your custom manifest file to your version control, it's source code after all.&lt;/p&gt;

&lt;h4&gt;References :&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://msdn.microsoft.com/en-us/library/aa374191%28v=vs.85%29.aspx?f=255&amp;MSPPError=-2147217396"&gt;MSDN - Application Manifests&lt;/a&gt;&lt;/p&gt;
</description><guid isPermaLink="false">753</guid></item><item><title>Delphi VersionInfo errors</title><link>https://www.finalbuilder.com/resources/blogs/postid/752/delphi-versioninfo-errors</link><category>Delphi,FinalBuilder</category><pubDate>Thu, 17 Aug 2017 11:44:15 GMT</pubDate><description>&lt;p&gt;Over the last year or so, we have seen more and more "bug reports" about compiling Delphi projects with FinalBuilder, in particular, reporting issues with compiling version info resources when using Delphi 10.1 (Berlin) and Delphi 10.2 (Tokyo). &lt;/p&gt;
&lt;p&gt;This only happens if you tell the Delphi action in FinalBuilder to load version info from the dproj.&lt;/p&gt;
&lt;p style="text-align: center;"&gt;
&lt;img src="/blogimages/vincent/versioninfo/action-settings.png" alt="delphi action settings" /&gt;
&lt;/p&gt;
&lt;p&gt;The error typically looks something like this :&lt;/p&gt;
&lt;p style="text-align: center;"&gt;
&lt;img src="/blogimages/vincent/versioninfo/fbreserror.png" alt="resource compiler error" /&gt;
&lt;/p&gt;
&lt;p&gt;or this :&lt;/p&gt;
&lt;p style="text-align: center;"&gt;
&lt;img src="/blogimages/vincent/versioninfo/fbreserror2.png" alt="resource compiler error" /&gt;
&lt;/p&gt;
&lt;p&gt;"What's this ModuleName variable?? What's com.embarcadero.$(ModuleName) ? I didn't put that there...." &lt;/p&gt;
&lt;p&gt;Or "what's this MSBuildProjectName variable?"&lt;/p&gt;
&lt;p&gt;This all stems from Embarcadero's support for non windows platforms (in this case I would suggest andriod). The default values for version info Berlin and later have "$(ModuleName)" in the FileDescription, ProductName and ProgramID fields.&lt;/p&gt;
&lt;p style="text-align: center;"&gt;
&lt;img src="/blogimages/vincent/versioninfo/default-version-info.png" alt="default version info" /&gt;
&lt;/p&gt;
&lt;p&gt;This of course is nonsense for the Windows platform, but some bright new embarcadero hire obviously thought this would be a good idea (well that's what I think, who knows what was behind the decision). The problem is, $(ModuleName) is completely unknown outside of the IDE or MSBuild. So when we compile from the command line (using dcc32, dcc64 etc), if your Delphi Action is set to read the version values from the dproj, then you will get this error. &lt;/p&gt;
&lt;p&gt;There are three options to resolve this :&lt;/p&gt;
&lt;ol style="margin: 10px;"&gt;
    &lt;li&gt;Change the FileDescription field in your delphi project settings to something more meaningful, rather than an ad for Embarcadero, like ummm, oh I know, your product name!&lt;/li&gt;
    &lt;li&gt;Define the ModuleName variable in FinalBuilder - but this still gets the FileDescription field saying com.embarcadero.YourProductName (hey, it's not a java app!). &lt;/li&gt;
    &lt;li&gt;Don't load the version info from the dproj, let FinalBuilder handle it completely. After all, you are using FinalBuilder to create your production builds, and version information is part of the release process, not the development process. &lt;strong&gt;*This would be my recommended option.*&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;</description><guid isPermaLink="false">752</guid></item><item><title>Visual Studio 2017 15.3 Update issues</title><link>https://www.finalbuilder.com/resources/blogs/postid/751/visual-studio-2017-153-update-issues</link><category>.NET,Continua CI,FinalBuilder</category><pubDate>Thu, 17 Aug 2017 10:37:26 GMT</pubDate><description>&lt;span style="color: #ff0000;"&gt;&lt;strong&gt;Update 25 Sept 2017 :&lt;/strong&gt;&amp;nbsp;Microsoft have closed our bug report with a Wont Fix status.. seems they are too busy with other things.&lt;br /&gt;
&lt;/span&gt;&lt;br /&gt;
The recent Visual Studio 2017 Update (also known as VS 15.3) &amp;nbsp;introduced a problem with command line compilation when the Lightweight Solution Load feature is enabled for the solution.&amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
If you are using devenv (ie you have the Use MSBuild option unchecked in FinalBuilder), and have the action set to Rebuild... be aware that while the action will succeed, nothing actually gets compiled! &lt;br /&gt;
Just to be clear, this is &lt;strong&gt;not&lt;/strong&gt; a FinalBuilder (or Continua CI) problem :&lt;br /&gt;
&lt;br /&gt;
&lt;div class="reCodeBlock" style="border: 1px solid #7f9db9; overflow-y: auto;"&gt;
&lt;div style="background-color: #ffffff;"&gt;&lt;span style="margin-left: 0px !important;"&gt;&lt;code style="color: #000000;"&gt;"C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\IDE\devenv.com" /rebuild "Release|Any CPU" ConsoleApps.sln&lt;/code&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style="background-color: #f8f8f8;"&gt;&lt;span style="margin-left: 0px !important;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
&lt;div style="background-color: #ffffff;"&gt;&lt;span style="margin-left: 0px !important;"&gt;&lt;code style="color: #000000;"&gt;Microsoft Visual Studio 2017 Version 15.0.26730.3.&lt;/code&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style="background-color: #f8f8f8;"&gt;&lt;span style="margin-left: 0px !important;"&gt;&lt;code style="color: #000000;"&gt;Copyright (C) Microsoft Corp. All rights reserved.&lt;/code&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style="background-color: #ffffff;"&gt;&lt;span style="margin-left: 0px !important;"&gt;&lt;code style="color: #000000;"&gt;========== Rebuild All: 0 succeeded, 0 failed, 0 skipped ==========&lt;/code&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;br /&gt;
Turning off Lightweight Solution Load on the solution (don't forget to save the solution) results in proper compilation :&lt;br /&gt;
&lt;br /&gt;
&lt;div class="reCodeBlock" style="border: 1px solid #7f9db9; overflow-y: auto;"&gt;
&lt;div style="background-color: #ffffff;"&gt;&lt;span style="margin-left: 0px !important;"&gt;&lt;code style="color: #000000;"&gt;"C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\IDE\devenv.com" /rebuild "Release|Any CPU" ConsoleApps.sln&lt;/code&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style="background-color: #f8f8f8;"&gt;&lt;span style="margin-left: 0px !important;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
&lt;div style="background-color: #ffffff;"&gt;&lt;span style="margin-left: 0px !important;"&gt;&lt;code style="color: #000000;"&gt;Microsoft Visual Studio 2017 Version 15.0.26730.3.&lt;/code&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style="background-color: #f8f8f8;"&gt;&lt;span style="margin-left: 0px !important;"&gt;&lt;code style="color: #000000;"&gt;Copyright (C) Microsoft Corp. All rights reserved.&lt;/code&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style="background-color: #ffffff;"&gt;&lt;span style="margin-left: 0px !important;"&gt;&lt;code style="color: #000000;"&gt;1&amp;gt;------ Rebuild All started: Project: ConsoleApps1, Configuration: Release Any CPU ------&lt;/code&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style="background-color: #f8f8f8;"&gt;&lt;span style="margin-left: 0px !important;"&gt;&lt;code style="color: #000000;"&gt;2&amp;gt;------ Rebuild All started: Project: ConsoleApp2, Configuration: Release Any CPU ------&lt;/code&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style="background-color: #ffffff;"&gt;&lt;span style="margin-left: 0px !important;"&gt;&lt;code style="color: #000000;"&gt;3&amp;gt;------ Rebuild All started: Project: ConsoleApp3, Configuration: Release Any CPU ------&lt;/code&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style="background-color: #f8f8f8;"&gt;&lt;span style="margin-left: 0px !important;"&gt;&lt;code style="color: #000000;"&gt;4&amp;gt;------ Rebuild All started: Project: ConsoleApp4, Configuration: Release Any CPU ------&lt;/code&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style="background-color: #ffffff;"&gt;&lt;span style="margin-left: 0px !important;"&gt;&lt;code style="color: #000000;"&gt;1&amp;gt;&amp;nbsp; ConsoleApps1 -&amp;gt; C:\Users\vincent.OFFICE\Documents\Visual Studio 2017\Projects\ConsoleApps\ConsoleApps1\bin\Release\ConsoleApps1.exe&lt;/code&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style="background-color: #f8f8f8;"&gt;&lt;span style="margin-left: 0px !important;"&gt;&lt;code style="color: #000000;"&gt;2&amp;gt;&amp;nbsp; ConsoleApp2 -&amp;gt; C:\Users\vincent.OFFICE\Documents\Visual Studio 2017\Projects\ConsoleApps\ConsoleApp2\bin\Release\ConsoleApp2.exe&lt;/code&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style="background-color: #ffffff;"&gt;&lt;span style="margin-left: 0px !important;"&gt;&lt;code style="color: #000000;"&gt;3&amp;gt;&amp;nbsp; ConsoleApp3 -&amp;gt; C:\Users\vincent.OFFICE\Documents\Visual Studio 2017\Projects\ConsoleApps\ConsoleApp3\bin\Release\ConsoleApp3.exe&lt;/code&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style="background-color: #f8f8f8;"&gt;&lt;span style="margin-left: 0px !important;"&gt;&lt;code style="color: #000000;"&gt;4&amp;gt;&amp;nbsp; ConsoleApp4 -&amp;gt; C:\Users\vincent.OFFICE\Documents\Visual Studio 2017\Projects\ConsoleApps\ConsoleApp4\bin\Release\ConsoleApp4.exe&lt;/code&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style="background-color: #ffffff;"&gt;&lt;span style="margin-left: 0px !important;"&gt;&lt;code style="color: #000000;"&gt;========== Rebuild All: 4 succeeded, 0 failed, 0 skipped ==========&lt;/code&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;br /&gt;
MSBuild is not affected by this bug (&lt;a href="https://developercommunity.visualstudio.com/content/problem/96511/visual-studo-153-devenv-rebuild-does-nothing-when.html"&gt;reported to Microsoft here&lt;/a&gt;). Unless you have a very good reason for using devenv to compile visual studio solutions these days, just use MSBuild. &lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&lt;br /&gt;</description><guid isPermaLink="false">751</guid></item><item><title>Visual Studio 2017 RC Support</title><link>https://www.finalbuilder.com/resources/blogs/postid/749/visual-studio-2017-rc-support</link><category>.NET,Continua CI,Delphi,FinalBuilder</category><pubDate>Tue, 22 Nov 2016 14:44:36 GMT</pubDate><description>Today we released updates to &lt;a href="https://www.finalbuilder.com/downloads/finalbuilder" target="_blank"&gt;FinalBuilder (8.0.0.2007)&lt;/a&gt; and &lt;a href="https://www.finalbuilder.com/downloads/continuaci" target="_blank"&gt;Continua CI (1.8.1.185)&lt;/a&gt; which add support for Visual Studio 2017 RC.&amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
There were a few issues we found with Visual Studio 2017 Release Candidate. The first was, unlike every other previous version of Visual Studio, 2017 RC does not write any useful information to the registry that allows us to reliably find out where it was installed to. So at the moment, we just check the default install locations :&lt;br /&gt;
&lt;br /&gt;
On 64 bit windows :&lt;br /&gt;
&lt;br /&gt;
C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\IDE&lt;br /&gt;
C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\Common7\IDE&lt;br /&gt;
C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Common7\IDE&lt;br /&gt;
&lt;br /&gt;
on 32 bit windows (do people still use it?) :&lt;br /&gt;
&lt;br /&gt;
C:\Program Files\Microsoft Visual Studio\2017\Community\Common7\IDE\Common7\IDE&lt;br /&gt;
C:\Program Files\Microsoft Visual Studio\2017\Professional\Common7\IDE&lt;br /&gt;
C:\Program Files\Microsoft Visual Studio\2017\Enterprise\Common7\IDE&lt;br /&gt;
&lt;br /&gt;
Yes, each edition now installs into different folders.&amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
As a work around for those who don't install in the default location, you can set environment variables &amp;nbsp;&lt;strong&gt;MSBuild15Path&lt;/strong&gt; (for MSBuild) and&amp;nbsp; &lt;strong&gt;VisualStudio2017Path&lt;/strong&gt;&amp;nbsp;for Visual Studio, if we don't find VS/MSBuild in the default locations, we'll check for those environment variables. &amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
Another issue we found is that when building with devenv.com (ie the visual studio command line, rather than msbuild), builds take a looooong time.. it appears to hang after building, and it also seems to randomly fail with windows error&amp;nbsp;80131623 (FatalExecutionEngineError). This has nothing to do with FinalBuilder or Continua CI, it happens on the command line as well. I have reported these issues to microsoft, hopefully they will resolve them before release. On the MSBuild Action in FinalBuilder, we were not able to get the list of targets for a dotnet core project. This is still being investigated, we do still hope to resolve this eventually.&amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
Note, since this work was done against a Release Candidate, things may change between now and the VS2017 RTM release (microsoft seem to have redifined what a release candidate is lately!). If you find any issues let us know.&lt;br /&gt;
&lt;br /&gt;
BTW, TFS 2017 support is currently being worked on for both FinalBuilder and Continua CI. We should have a VSO FinalBuilder build task available in the marketplace soon (it's close). However, getting our xaml builds working with TFS2017 is proving challenging (just like previous releases), there is no doco and it's deprecated (good riddance) and visual studio won't load our projects.. stay tuned.</description><guid isPermaLink="false">749</guid></item><item><title>Case Study: Mitov Software and FinalBuilder</title><link>https://www.finalbuilder.com/resources/blogs/postid/767/case-study-mitov-software-and-finalbuilder</link><category>Case Study,FinalBuilder</category><pubDate>Sun, 21 Aug 2016 00:25:00 GMT</pubDate><description>&lt;h2&gt;Case Study:  Mitov Software and FinalBuilder&lt;/h2&gt;

&lt;p&gt;Boian Mitov, owner of &lt;a href="https://www.mitov.com/"&gt;Mitov Software&lt;/a&gt;, explains how FinalBuilder has reduced build times by 88% and delivered a dramatic improvement in productivity, so that it is now essential for their software development process.  Mitov Software supplies developer components and custom solutions for audio, visual and signal processing, computer vision, and data visualization.&lt;/p&gt;

&lt;h2&gt;Challenges faced&lt;/h2&gt;

&lt;p&gt;“Before we started using FinalBuilder, we were running a combination of manual build steps and custom .BAT files. The creation and maintenance of the .BAT files was a huge challenge, especially when dealing with Visual C++ 6.0 .”&lt;/p&gt;

&lt;h2&gt;Why we chose FinalBuilder&lt;/h2&gt;

&lt;p&gt;“FinalBuilder is very reasonably priced, has a comprehensive feature set, and comes with very good support. We had some issues when we started using the product, mainly due to our lack of knowledge of the available features, but we received very quick and precise directions from the FinalBuilder team. It was great to see that all of the features we requested were delivered in the following release! I like how the trial version of the next release is fully functional, allowing easy and complete evaluation prior to purchase. It’s turning out to be a fantastic product!”&lt;/p&gt;

&lt;h2&gt;FinalBuilder cost recovered in less than one week&lt;/h2&gt;

&lt;p&gt;“FinalBuilder reduces our build time for a product line from around 3 days to less than 3 hours. It returned the money invested during the first week we used it. Because some basic testing is performed during the build we can discover and fix bugs within a matter of hours. It also allows us to easily run periodic builds as a quality control, and helps us discover issues at an early stage. We have reduced the incidence of missed steps and wrong order of build steps to practically zero!”&lt;/p&gt;

&lt;h2&gt;How we use FinalBuilder&lt;/h2&gt;

&lt;p&gt;“We use a lot of action lists. In our build we need to build 18 packages each under Delphi 5, Delphi 6, Delphi 7, Delphi 2005, C++ Builder 5, C++ Builder 6 and BDS 2006. By using Action Lists we can pass the package name as a parameter and have it built with all the compilers. The same applies for our demo applications.&lt;/p&gt;

&lt;p&gt;As part of our process we perform 138 package builds, 322 Delphi and C++ Builder demo projects, 3 Visual C++ libraries, 1 Delphi, 1 C++ Builder and 2 Visual C++ DLLs, 1 .NET library, and 138 Visual C++ examples, 15 Installs, 18 Help files.&lt;/p&gt;

&lt;p&gt;During the build we use FinalBuilder to automatically generate sections of the Installer. We also automatically generate the Visual C++ files for all of our components, and all the Visual C++ help files by performing a custom process over the existing Delphi and C++ Builder help files and sources. In addition our script automatically extracts all the component images to be used by the help service and by our web site.&lt;/p&gt;

&lt;p&gt;Finally, we use FinalBuilder to automatically generate and build several test projects to confirm the validity of our libraries. These auto generated test projects include all the components in our packages.”&lt;/p&gt;

&lt;h2&gt;FinalBuilder compatibility&lt;/h2&gt;

&lt;p&gt;“We use FinalBuilder with Delphi – Versions 5, 6, 7, 2005, C++ Builder 5 and 6, and BDS 2006, Visual Studio 6.0, 2003 and 2005, InnoSetup, and Doc-O-Matic. We also use a number of custom actions and command line utilities written by us for parts of the build process.”&lt;/p&gt;

&lt;h2&gt;Ease of use&lt;/h2&gt;

&lt;p&gt;“FinalBuilder projects are very easy to create and maintain. It takes just one part-time person to maintain the process. As our products evolve we are adding more and more functionality into the build project, and this is greatly assisted by FinalBuilder’s range of functions”.&lt;/p&gt;

&lt;h2&gt;Recommendation&lt;/h2&gt;

&lt;p&gt;“I highly recommend FinalBuilder to anyone. The tool is very easy to work with, very intuitive, flexible and powerful.”&lt;/p&gt;

&lt;h2&gt;Competitive Edge&lt;/h2&gt;

&lt;p&gt;“With FinalBuilder we can now develop and maintain 10 different large products with very minimal effort. It also gives us time and the efficiency to develop new products, because it significantly reduces the time we have to spend on building and testing. Therefore FinalBuilder has helped to significantly expand and further develop our product range and has strengthened our competitive position.”&lt;/p&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;“FinalBuilder is extremely valuable tool in our arsenal. In fact it’s one of the most important tools we use because it allows us to consistently release high quality products.”&lt;/p&gt;

&lt;h2&gt;About Mitov Software&lt;/h2&gt;

&lt;p&gt;Mitov Software is a very small privately owned company focused on development of Visual C++ libraries, and Delphi, C++ Builder and .NET component packages for very fast Digital Signal Processing (DSP), Video capture and Image Processing, Audio recording and processing, Data Visualization and Basic Computer Vision. We also provide a number of consulting services and custom development in these areas, as well as in Very Fast Data Acquisition and Process Control.&lt;/p&gt;

&lt;h2&gt;About Mitov Software products&lt;/h2&gt;

&lt;p&gt;Mitov Software currently offers 10 commercial products:&lt;/p&gt;

&lt;p&gt;5 Delphi and C++ Builder VCL component libraries:&lt;/p&gt;

&lt;p&gt;Video Lab VCL – very fast video capture, processing playback and visualization&lt;/p&gt;

&lt;p&gt;AudioLab VCL - very fast audio record, processing playback and visualization&lt;/p&gt;

&lt;p&gt;SignalLab VCL – Digital Signal Processing and visualization&lt;/p&gt;

&lt;p&gt;VisionLab VCL – basic computer vision&lt;/p&gt;

&lt;p&gt;PlotLab VCL – data visualization&lt;/p&gt;

&lt;p&gt;We also offer the same products in Visual C++ versions:&lt;/p&gt;

&lt;p&gt;Video Lab VC++ – very fast video capture, processing playback and visualization&lt;/p&gt;

&lt;p&gt;AudioLab VC++ – very fast audio record, processing playback and visualization&lt;/p&gt;

&lt;p&gt;SignalLab VC++ – Digital Signal Processing and visualization&lt;/p&gt;

&lt;p&gt;VisionLab VC++ – basic computer vision&lt;/p&gt;

&lt;p&gt;PlotLab VC++ – data visualization&lt;/p&gt;

&lt;p&gt;We are in the final stages of development of .NET versions of the above products.&lt;/p&gt;

&lt;p&gt;We are also working on a free Open Source project:&lt;/p&gt;

&lt;p&gt;OpenWire VCL – allows RAD codeless component development.&lt;/p&gt;

&lt;h2&gt;About VSoft Technologies&lt;/h2&gt;

&lt;p&gt;VSoft Technologies have been in business since 1996, and are focused on developing automation software for software developers, software configuration managers, system administrators, network administrators and IT professionals.  Both FinalBuilder and Automise save time and money by providing easy to use, flexible and powerful solutions to automation tasks.&lt;/p&gt;

&lt;p&gt;Visit our website at either &lt;a href="https://www.finalbuilder.com"&gt;https://www.finalbuilder.com&lt;/a&gt; to find out more information and to download fully functional 30 day evaluation editions.&lt;/p&gt;

&lt;p&gt;FinalBuilder™ is a Trade Mark of VSoft Technologies Pty Ltd. All other product and company names listed are trademarks or trade names of their respective companies.&lt;/p&gt;
</description><guid isPermaLink="false">767</guid></item><item><title>Continua CI and FinalBuilder integration improvements</title><link>https://www.finalbuilder.com/resources/blogs/postid/747/continua-ci-and-finalbuilder-integration-improvements</link><category>Continua CI,Delphi,FinalBuilder,FinalBuilder Server</category><pubDate>Tue, 21 Jun 2016 15:35:25 GMT</pubDate><description>Continua CI 1.8.0.176 and FinalBuilder 8.0.0.1817 (both released today) provide somewhat better integration between the two products. &amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;Continua CI 1.8&lt;/h3&gt;
&lt;p&gt;
The FinalBuilder Action in Continua CI now produces an xml file that is consumed by FinalBuilder when run under Continua CI. This xml file contains all the useful information about a build, such as version numbers, changesets, variables etc.&amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
There is also a new option on the action that will automatically apply Continua CI variable values to matching FinalBuilder variables. What this means is, if you have a variable declared in both FinalBuilder and Continua CI with the same name, FinalBuilder's variable will automatically get the value of the Continua CI variable at runtime. This option is only available for FinalBuilder 8, if you select FinalBuilder 7 the option will not be visible. If the version of FinalBuilder 8 you are running does not support this integration, a warning will appear in the Continua CI build log.&amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&lt;/p&gt;
&lt;p style="text-align: center;"&gt;
&lt;img alt="" src="/blogimages/vincent/continua-fb-integration/continua-fbaction.png" /&gt;
&lt;/p&gt;
&lt;h3&gt;FinalBuilder 8&lt;/h3&gt;
FinalBuilder 8 has two new actions. &lt;br /&gt;
&lt;br /&gt;
The "Is Running Under Continua" action is an If Then style action, i.e. the children of this action will only run if FinalBuilder is running under Continua CI. &amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&lt;p style="text-align: center;"&gt;
&lt;img alt="" src="/blogimages/vincent/continua-fb-integration/isrunningcontinua.png" /&gt;
&lt;/p&gt;
&lt;br /&gt;
&lt;p&gt;The other action is the Continua CI - Get Version Info action - this action will take the version info from Continua CI and apply it to a version info property set in your FinalBuilder project.;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="text-align: center;"&gt;
&lt;img alt="" src="/blogimages/vincent/continua-fb-integration/getversioninfo.png" /&gt;
&lt;/p&gt;
&lt;p&gt;The action is smart enough to use the correct version info scheme depending on whether the propertyset is a win32 or dotnet propertyset. This greatly simplifies getting the version info from Continua into FinalBuilder, no need to declare 4 variables on both sides and set them in the FinalBuilder Action in Continua CI.&lt;/p&gt;
&lt;h3&gt;Scripting&lt;/h3&gt;
That xml file I mentioned above is loaded into a Continua object model that is available in action script events. If you do make use of it, you should be sure to check the Continua.IsRunningUnderContinua property before using the rest of the object model (the script editor provides intellisense for the model.&lt;br /&gt;</description><guid isPermaLink="false">747</guid></item></channel></rss>