<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?aid=5&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>Black Friday Sale 2025 - 40% off all new licenses - Extended!</title><link>https://www.finalbuilder.com/resources/blogs/postid/877/black-friday-sale-2025-40-off-all-new-licenses</link><category>Delphi</category><pubDate>Sun, 23 Nov 2025 23:20:19 GMT</pubDate><description>&lt;p&gt;&lt;strong&gt;Black Friday Sale&lt;/strong&gt; - &lt;strong&gt;&lt;span style="color:#ff0000;"&gt;40%&lt;/span&gt;&lt;/strong&gt; off all new licenses until midnight (utc) 9th December 2025.&lt;/p&gt;

&lt;p&gt;No coupon code required, the store will apply the discount automatically.&lt;/p&gt;
</description><guid isPermaLink="false">877</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>Useful MSBuild Properties for Production Builds</title><link>https://www.finalbuilder.com/resources/blogs/postid/874/using-msbuilds-continuousintegrationbuild-in-continua-ci-for-more-predictable-builds</link><category>.NET,Continua CI,Visual Studio</category><pubDate>Tue, 16 Sep 2025 08:25:32 GMT</pubDate><description>&lt;p&gt;When deploying dotnet applications to production, the difference between a development build and a properly configured production build can be significant. MSBuild provides numerous properties that allow you to optimize your builds for performance, security, and reliability. This article explores essential MSBuild properties for production builds, with particular focus on configuration for CI servers like Continua CI.&lt;/p&gt;

&lt;h2 id="coreproductionbuildproperties"&gt;Core Production Build Properties&lt;/h2&gt;

&lt;h3 id="releaseconfiguration"&gt;Release Configuration&lt;/h3&gt;

&lt;p&gt;The foundation of any production build starts with the Release configuration:&lt;/p&gt;

&lt;pre  class="brush:xml; toolbar:false;"&gt;
&lt;PropertyGroup Condition="'$(Configuration)'=='Release'"&gt;
  &lt;Optimize&gt;true&lt;/Optimize&gt;
  &lt;DebugType&gt;portable&lt;/DebugType&gt;
  &lt;DebugSymbols&gt;true&lt;/DebugSymbols&gt;
&lt;/PropertyGroup&gt;
&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Optimize&lt;/strong&gt; enables compiler optimizations that improve runtime performance by inlining methods, removing dead code, and performing other optimizations. &lt;strong&gt;DebugType&lt;/strong&gt; set to "portable" creates portable PDB files that work across platforms while maintaining debugging capabilities. &lt;strong&gt;DebugSymbols&lt;/strong&gt; should remain true even in production to enable proper stack traces and debugging when issues occur.&lt;/p&gt;

&lt;h3 id="deterministicbuilds"&gt;Deterministic Builds&lt;/h3&gt;

&lt;p&gt;Deterministic builds ensure that identical source code produces identical binaries, which is crucial for security auditing and reproducible deployments:&lt;/p&gt;
&lt;pre  class="brush:xml; toolbar:false;"&gt;
&lt;PropertyGroup&gt;
  &lt;Deterministic&gt;true&lt;/Deterministic&gt;
  &lt;PathMap&gt;path1=sourcePath1,path2=sourcePath2&lt;/PathMap&gt;
&lt;/PropertyGroup&gt;
&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;PathMap&lt;/strong&gt; removes replaces the actual paths in your projects, so instead of having "c:\CI_AWS\WS\123\srs\myclass.cs" baked into your executable, you get something like ".\src\myclass.cs" .&lt;/p&gt;
&lt;p&gt;The syntax is straightforward - &lt;code&gt;path1&lt;/code&gt; is the real path on your build machine, and &lt;code&gt;sourcePath1&lt;/code&gt; is what you want it to look like in the output. If you need to map multiple paths, just separate them with commas.&lt;/p&gt;

&lt;h2 id="cispecificproperties"&gt;CI-Specific Properties&lt;/h2&gt;

&lt;h3 id="continuousintegrationbuild"&gt;ContinuousIntegrationBuild&lt;/h3&gt;

&lt;p&gt;One of the most important properties for CI environments is &lt;code&gt;ContinuousIntegrationBuild&lt;/code&gt;. According to the &lt;a href="https://learn.microsoft.com/en-us/dotnet/core/project-sdk/msbuild-props#continuousintegrationbuild"&gt;Microsoft documentation&lt;/a&gt;, this property enables several CI-specific optimizations:&lt;/p&gt;

&lt;ul&gt;
   &lt;li&gt;Suppresses certain warnings that are only relevant during development&lt;/li&gt;
   &lt;li&gt;Enables deterministic builds by default&lt;/li&gt;
   &lt;li&gt;Optimizes source link generation for better debugging experience&lt;/li&gt;
   &lt;li&gt;Improves build reproducibility&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For Continua CI, you can configure this property using the built-in &lt;code&gt;ContinuaCI.Version&lt;/code&gt; environment variable:&lt;/p&gt;

&lt;pre  class="brush:xml; toolbar:false;"&gt;
&lt;PropertyGroup&gt;
  &lt;ContinuousIntegrationBuild Condition="'$(ContinuaCI.Version)' != ''"&gt;true&lt;/ContinuousIntegrationBuild&gt;
&lt;/PropertyGroup&gt;
&lt;/pre&gt;

&lt;p&gt;Alternatively, you can set it in your CI build configuration by adding &lt;code&gt;ContinuousIntegrationBuild=true&lt;/code&gt; to the MSBuild Action Properties list.&lt;/p&gt;

&lt;h3 id="buildmetadata"&gt;Build Metadata&lt;/h3&gt;

&lt;p&gt;Including build metadata helps with traceability and debugging:&lt;/p&gt;

&lt;pre  class="brush:xml; toolbar:false;"&gt;&lt;PropertyGroup&gt;
  &lt;SourceRevisionId Condition="'$(SourceRevisionId)' == ''"&gt;$(ContinuaCI.Build.LatestChangeset.Revision)&lt;/SourceRevisionId&gt;
  &lt;InformationalVersion&gt;$(ContinuaCI.Build.Version)+$(SourceRevisionId)&lt;/InformationalVersion&gt;
&lt;/PropertyGroup&gt;
&lt;/pre&gt;

&lt;p&gt;This embeds the source control revision ID into the assembly, making it easier to identify which exact code version is running in production. Most CI servers provide information like revision, version etc using environment variables.&lt;/p&gt;

&lt;h2 id="securityandcodequalityproperties"&gt;Security and Code Quality Properties&lt;/h2&gt;

&lt;h3 id="treatwarningsaserrors"&gt;Treat Warnings as Errors&lt;/h3&gt;

&lt;p&gt;In production builds, warnings often indicate potential issues that should be addressed:&lt;/p&gt;

&lt;pre  class="brush:xml; toolbar:false;"&gt;&lt;PropertyGroup Condition="'$(Configuration)'=='Release'"&gt;
  &lt;TreatWarningsAsErrors&gt;true&lt;/TreatWarningsAsErrors&gt;
  &lt;WarningsNotAsErrors&gt;CS1591&lt;/WarningsNotAsErrors&gt;
&lt;/PropertyGroup&gt;
&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;TreatWarningsAsErrors&lt;/strong&gt; ensures your production code has no compiler warnings. &lt;strong&gt;WarningsNotAsErrors&lt;/strong&gt; allows you to exclude specific warnings (like CS1591 for missing XML documentation) that shouldn't break the build.&lt;/p&gt;

&lt;h3 id="codeanalysis"&gt;Code Analysis&lt;/h3&gt;

&lt;p&gt;Enable static code analysis for production builds:&lt;/p&gt;

&lt;pre  class="brush:xml; toolbar:false;"&gt;&lt;PropertyGroup&gt;
  &lt;EnableNETAnalyzers&gt;true&lt;/EnableNETAnalyzers&gt;
  &lt;AnalysisLevel&gt;latest&lt;/AnalysisLevel&gt;
  &lt;CodeAnalysisTreatWarningsAsErrors&gt;true&lt;/CodeAnalysisTreatWarningsAsErrors&gt;
&lt;/PropertyGroup&gt;
&lt;/pre&gt;

&lt;h3 id="nullablereferencetypes"&gt;Nullable Reference Types&lt;/h3&gt;

&lt;p&gt;For C# 8.0+ projects, enable nullable reference types to catch potential null reference exceptions:&lt;/p&gt;

&lt;pre  class="brush:xml; toolbar:false;"&gt;
&lt;PropertyGroup&gt;
  &lt;Nullable&gt;enable&lt;/Nullable&gt;
  &lt;TreatWarningsAsErrors&gt;true&lt;/TreatWarningsAsErrors&gt;
&lt;/PropertyGroup&gt;
&lt;/pre&gt;
&lt;p&gt;This option can be quite painful to enable on an existing code base - be prepared for a lot of clean up work!&lt;/p&gt;

&lt;h2 id="performanceoptimizationproperties"&gt;Performance Optimization Properties&lt;/h2&gt;

&lt;h3 id="aheadoftimecompilation"&gt;Ahead-of-Time Compilation&lt;/h3&gt;

&lt;p&gt;For applications where startup performance is critical, consider enabling ReadyToRun:&lt;/p&gt;

&lt;pre  class="brush:xml; toolbar:false;"&gt;
&lt;PropertyGroup Condition="'$(Configuration)'=='Release'"&gt;
  &lt;PublishReadyToRun&gt;true&lt;/PublishReadyToRun&gt;
&lt;/PropertyGroup&gt;
&lt;/pre&gt;

&lt;p&gt;Note that ReadyToRun is platform specific - you must specify a Runtime Identifier  (e.g., win-x64, linux-arm64) when publishing with PublishReadyToRun=true.&lt;/p&gt;


&lt;h3 id="trimmingforselfcontaineddeployments"&gt;Trimming for Self-Contained Deployments&lt;/h3&gt;

&lt;p&gt;For self-contained deployments, enable IL trimming to reduce application size:&lt;/p&gt;

&lt;pre  class="brush:xml; toolbar:false;"&gt;
&lt;PropertyGroup&gt;
  &lt;PublishTrimmed&gt;true&lt;/PublishTrimmed&gt;
  &lt;TrimMode&gt;partial&lt;/TrimMode&gt;
&lt;/PropertyGroup&gt;
&lt;/pre&gt;

&lt;p&gt;Be cautious with trimming as it can break applications that rely heavily on reflection.&lt;/p&gt;

&lt;h2 id="assemblyandversioningproperties"&gt;Assembly and Versioning Properties&lt;/h2&gt;
&lt;h3 id="strongnaming"&gt;Strong Naming&lt;/h3&gt;

&lt;p&gt;For libraries that will be consumed by other applications:&lt;/p&gt;

&lt;pre  class="brush:xml; toolbar:false;"&gt;
&lt;PropertyGroup&gt;
  &lt;SignAssembly&gt;true&lt;/SignAssembly&gt;
  &lt;AssemblyOriginatorKeyFile&gt;key.snk&lt;/AssemblyOriginatorKeyFile&gt;
&lt;/PropertyGroup&gt;
&lt;/pre&gt;

&lt;h3 id="versioninformation"&gt;Version Information&lt;/h3&gt;

&lt;p&gt;Properly configure version information for easier identification:&lt;/p&gt;
&lt;pre  class="brush:xml; toolbar:false;"&gt;
&lt;PropertyGroup&gt;
  &lt;AssemblyVersion&gt;1.0.0.0&lt;/AssemblyVersion&gt;
  &lt;FileVersion&gt;$(BuildNumber)&lt;/FileVersion&gt;
  &lt;Version&gt;$(ProductVersion)&lt;/Version&gt;
&lt;/PropertyGroup&gt;
&lt;/pre&gt;

&lt;h2 id="outputandpackagingproperties"&gt;Output and Packaging Properties&lt;/h2&gt;

&lt;h3 id="symbolpackagegeneration"&gt;Symbol Package Generation&lt;/h3&gt;

&lt;p&gt;For NuGet packages, include symbol packages for debugging:&lt;/p&gt;

&lt;pre  class="brush:xml; toolbar:false;"&gt;
&lt;PropertyGroup&gt;
  &lt;IncludeSymbols&gt;true&lt;/IncludeSymbols&gt;
  &lt;SymbolPackageFormat&gt;snupkg&lt;/SymbolPackageFormat&gt;
&lt;/PropertyGroup&gt;
&lt;/pre&gt;

&lt;h3 id="sourcelink"&gt;Source Link&lt;/h3&gt;

&lt;p&gt;Enable Source Link for better debugging experience:&lt;/p&gt;

&lt;pre  class="brush:xml; toolbar:false;"&gt;
&lt;PropertyGroup&gt;
  &lt;PublishRepositoryUrl&gt;true&lt;/PublishRepositoryUrl&gt;
  &lt;EmbedUntrackedSources&gt;true&lt;/EmbedUntrackedSources&gt;
&lt;/PropertyGroup&gt;
&lt;/pre&gt;
&lt;h2 id="platformspecificoptimizations"&gt;Platform-Specific Optimizations&lt;/h2&gt;

&lt;p&gt;Reference the &lt;a href="https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/compiler-options/code-generation"&gt;Microsoft documentation on code generation options&lt;/a&gt; for platform-specific optimizations:&lt;/p&gt;

&lt;pre  class="brush:xml; toolbar:false;"&gt;
&lt;PropertyGroup Condition="'$(RuntimeIdentifier)'=='win-x64'"&gt;
  &lt;PlatformTarget&gt;x64&lt;/PlatformTarget&gt;
  &lt;Prefer32Bit&gt;false&lt;/Prefer32Bit&gt;
&lt;/PropertyGroup&gt;
&lt;/pre&gt;


&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;Properly configuring MSBuild properties for production builds is essential for creating robust, performant, and maintainable applications. The &lt;code&gt;ContinuousIntegrationBuild&lt;/code&gt; property provides an excellent foundation for CI-optimized builds. Remember to test these configurations thoroughly in your CI environment before deploying to production, as some optimizations may have unexpected effects on applications that rely heavily on reflection or dynamic code generation.&lt;/p&gt;

</description><guid isPermaLink="false">874</guid></item><item><title>Signotaur and Certificate Revocation Lists</title><link>https://www.finalbuilder.com/resources/blogs/postid/873/signotaur-and-certificate-revocation-lists</link><category>.NET,Code Signing,DelphiSignotaur,Visual Studio</category><pubDate>Wed, 09 Apr 2025 08:08:24 GMT</pubDate><description>&lt;p&gt;We recently had a report from a customer that code-signing using Signotaur was taking a long time — in this case, around a minute to sign one file. This is obviously far too slow for practical use. &lt;/p&gt;

&lt;p&gt;The customer provided us with logs from two machines, which showed different results. When comparing the logs, the only thing that stood out was the &lt;a href="https://knowledge.digicert.com/solution/how-certificate-chains-work" target="_blank"&gt;Certificate Chain&lt;/a&gt; elements — the bad log only showed one element, whilst the good log showed three. &lt;/p&gt;

&lt;p&gt;These chain elements make up the certificate path — each certificate is signed by another, and up the path we go until there are no more.&lt;/p&gt;

&lt;p&gt;&lt;img alt="Certificate Path" src="https://cdn.finalbuilder.com/blog/vincent/signotaur-crl/certificate-path.png" /&gt;&lt;/p&gt;

&lt;p&gt;Seeing only one certificate in the path is a red flag. You would not typically see a code-signing certificate that is signed by a root certificate; there would be one or more intermediate certificates in the path.&lt;br /&gt;
&lt;br /&gt;
Installing the Certificate Authority's intermediate certificates solved that part — the chain was complete. It did not solve the timing issue.&lt;br /&gt;
&lt;br /&gt;
So we added more debug logging, and after much head scratching, we realised the issue was that the delay was due to the fact that, by default, when building the certificate chain, the .NET X509Chain class performs online checks of the &lt;a href="https://en.wikipedia.org/wiki/Certificate_revocation_list" target="_blank"&gt;Certificate Revocation Lists&lt;/a&gt; (CRLs).&lt;br /&gt;
&lt;br /&gt;
Each certificate includes a CRL Distribution Points field that points to the CRLs. These CRLs are used to check if the certificate has been revoked.&lt;/p&gt;

&lt;p&gt;&lt;img alt="CRL Distribution Point" src="https://cdn.finalbuilder.com/blog/vincent/signotaur-crl/certificate-crl.png" style="width: 405px; height: 515px;" /&gt;&lt;/p&gt;

&lt;p&gt;Performing Online CRL checks (the default) can run into problems. In our customer's case, they were being blocked by their firewall — so each HTTP request timed out, resulting in signing taking longer than expected. Note it didn't fail the signing, since the CRLs were not retrieved. After the customer allowed those URLs in their firewall configuration, code signing was fast again.&lt;br /&gt;
&lt;br /&gt;
If your internet connection is slow or has high latency to the CRL hosts, that will also impact code signing time.&lt;br /&gt;
&lt;br /&gt;
The X509Chain class has two alternatives to online checks: Offline and NoCheck.&lt;br /&gt;
&lt;br /&gt;
- Offline will use cached CRLs if available, and will not attempt to retrieve the CRLs online.&lt;br /&gt;
- NoCheck does what it says — skips the CRL/OCSP checks — and really should only be used in an emergency.&lt;br /&gt;
&lt;br /&gt;
Signotaur v1.0.0.444 adds a new -rm option, which allows the values: Online (default), Offline, and NoCheck.&lt;/p&gt;
</description><guid isPermaLink="false">873</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>Code Signing with Inno Setup and Signotaur</title><link>https://www.finalbuilder.com/resources/blogs/postid/852/code-signing-inno-setup-with-signotaur</link><category>.NET,Code Signing,DelphiGeneral,Signotaur</category><pubDate>Fri, 31 Jan 2025 01:04:38 GMT</pubDate><description>&lt;p&gt;Inno Setup has long supported code signing (since v5.2.4). Fortunately, the way the authors of Inno Setup implemented this feature makes it really easy to use custom tools to do the code signing. In this post we'll take a look at how to use Signotaur with Inno Setup.&lt;/p&gt;

&lt;p&gt;There are a few different ways to specify which command to run during signing with Inno Setup.&lt;/p&gt;

&lt;h3&gt;Sign Tool settings in Inno Setup IDE&lt;/h3&gt;

&lt;p&gt;The first is to define "Sign Tool" commands in the Inno Setup IDE. You can create multiple commands - for example if you have multiple certificates  - and then in your scripts you can point to the "Sign Tool" you want your setup script to use.&lt;/p&gt;

&lt;p&gt;To define a "Sign Tool" command in the IDE - tools menu, Configure Sign Tools...&lt;/p&gt;

&lt;p&gt;&lt;img alt="Add sign tool in Inno Setup" src="https://cdn.finalbuilder.com/blog/vincent/inno-signotaur/add-signtool.png" /&gt;&lt;/p&gt;

&lt;p&gt;The name can be anything you want, however if you are including other third party inno scripts you should make sure the name is unique to make sure those scripts cannot redefine the command (this is pointed out in the docs)&lt;/p&gt;

&lt;p&gt;Imagine if a third party script did this&lt;/p&gt;

&lt;pre class="brush:plain; toolbar:false;"&gt;
[Setup]
SignTool=Default cmd /c format.com z: $f
&lt;/pre&gt;

&lt;p&gt;If a Sign Tool named Default is defined in the inno IDE, that would be used. Of course you should always review any third party code before using it!&lt;/p&gt;

&lt;p&gt;After providing a name,  you are prompted for a command. This is where we can provide our Signotaur command line.&lt;/p&gt;

&lt;p&gt;Inno Setup will replace a few placeholders&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;tt&gt;$f&lt;/tt&gt;&lt;/strong&gt;, replaced by the quoted file name of the file to be signed. (required)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;tt&gt;$p&lt;/tt&gt;&lt;/strong&gt;, replaced by the Sign Tool parameters (more on this later).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;tt&gt;$q&lt;/tt&gt;&lt;/strong&gt;, replaced by a quote, useful for defining a Sign Tool which contains quotes from the command line.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;tt&gt;$$&lt;/tt&gt;&lt;/strong&gt;, replaced by a single &lt;tt&gt;$&lt;/tt&gt; character.&lt;/p&gt;

&lt;p&gt;So with that, lets build our command line (adjust to suite your scenario).&lt;/p&gt;

&lt;pre class="brush:plain; toolbar:false;"&gt;
e:\SignotaurClient\SignotaurTool.exe sign --sign-server https://mysignotaurhost:91/ --api-key *** --thumbprint YOURCERT-THUMBPRINT --fd "SHA256" --description "My Application" --tr http://timestamp.sectigo.com --td "SHA256" --allow-untrusted $f
&lt;/pre&gt;

&lt;p&gt;&lt;img alt="Signotaur command line" src="https://cdn.finalbuilder.com/blog/vincent/inno-signotaur/sign-tool-command.png" /&gt;&lt;/p&gt;

&lt;p&gt;Note - in Inno Setup 6.3.3 and earlier, the Sign Tool command line limit is 256 chars, which is a problem when using signotaur - this was fixed in 6.4.0. The work around for 6.3.3 or earlier is to modify the registry - under HKEY_CURRENT_USER\Software\Jordan Russell\Inno Setup\SignTools find the value for the Sign Tool you added and enter the full command line there.&lt;/p&gt;

&lt;p&gt;Make sure to restart the Inno Setup IDE after making the registry change.&lt;/p&gt;

&lt;p&gt;Now we can define which Sign Tool to use in our Innosetup project.&lt;/p&gt;

&lt;pre class="brush:plain; toolbar:false;"&gt;
[Setup]
SignTool=signotaur
&lt;/pre&gt;

&lt;p&gt;That's all we need for now - you should be able to see Signotaur being invoked to sign the uninstaller and the installer.&lt;/p&gt;

&lt;p&gt;One downside to this configuration is that there is no way to parameterize the Sign Tool command, so no way to avoid hard coding the ApiKey in the command (which is stored insecurely in the registry). For that reason alone, I do not recommend configuring the Sign Tool this way.&lt;/p&gt;

&lt;h3&gt;Sign Tool settings in the setup project&lt;/h3&gt;

&lt;p&gt;So lets look at the second option, which is to fully define the SignTool command in the [Setup] section. IMPORTANT : Firstly, to keep the IDE happy, define your signtool as above, but with a command of&lt;/p&gt;

&lt;pre&gt;$p&lt;/pre&gt;

&lt;p&gt;then in your innotsetup project :&lt;/p&gt;

&lt;pre class="brush:plain; toolbar:false;"&gt;
[Setup]
SignTool=signotaur e:\SignotaurClient\SignotaurTool.exe sign --sign-server https://mysignotaurhost:91/ --api-key **** --thumbprint YOURCERT-THUMBPRINT --fd "SHA256" --description "My Application" --tr http://timestamp.sectigo.com --td "SHA256" --allow-untrusted $f
&lt;/pre&gt;

&lt;p&gt;Note that Signtool name in the project must be one that is defined in the IDE&lt;/p&gt;

&lt;p&gt;That works fine, but of course now instead of hard coding the ApiKey in the registry, we have it in our project file - which is potentially worse since it's likely checked into version control (perhaps even in a public repo on GitHub!).&lt;/p&gt;

&lt;h3&gt;Sign Tool settings on the command line&lt;/h3&gt;

&lt;p&gt;To get around this, we need to change how we compile our Inno Setup projects. Using the Inno command line compiler lets us get around all of the issues.&lt;/p&gt;

&lt;p&gt;To do this, remove the Sign Tool configurations from the IDE - we won't be using them.&lt;/p&gt;

&lt;p&gt;In our project, we can use the pre-processor to only run the SignTool when Release is defined.&lt;/p&gt;

&lt;pre class="brush:plain; toolbar:false;"&gt;
[Setup]
#ifdef Release
SignTool=signotaur SignotaurTool.exe sign --sign-server {#signotaurServer} --api-key {#apiKey} --thumbprint {#thumbprint} --fd "SHA256" --description {#MyAppName} --tr {#timeStampServer} --td "SHA256" -v --allow-untrusted $f
#endif
&lt;/pre&gt;

&lt;p&gt;On the command line we can can provide values for the pre-processor defines&lt;/p&gt;

&lt;pre class="brush:plain; toolbar:false;"&gt;
/DRelease /DapiKey=abcdef ...
&lt;/pre&gt;

&lt;p&gt;That now moves the ApiKey to your build script.&lt;/p&gt;

&lt;p&gt;There is one last option we can explore here - that is to provide the entire Sign Tool command on the command line for the iscc compiler&lt;/p&gt;

&lt;pre class="brush:plain; toolbar:false;"&gt;
 
/Sname=command
&lt;/pre&gt;

&lt;p&gt;Sets a SignTool with the specified name and command&lt;/p&gt;

&lt;p&gt;e.g.&lt;/p&gt;

&lt;pre class="brush:plain; toolbar:false;"&gt;
/Ssignotaur e:\SignotaurClient\SignotaurTool.exe sign --sign-server https://mysignotaurhost:91/ --api-key **** --thumbprint YOURCERT-THUMBPRINT --fd "SHA256" --description "My Application" --tr http://timestamp.sectigo.com --td "SHA256" --allow-untrusted $f
&lt;/pre&gt;

&lt;p&gt;This is what the FinalBuilder InnoSetup action uses when you use the SignTool property. Of course you can use FinalBuilder variables for the ApiKey and other parts that might change. If you are calling FinalBuilder from a CI server, those variables can be provided from the CI tool - so the secret is stored and secured in one place.&lt;/p&gt;

&lt;p&gt;One last comment before I wrap this up - why would I need Innosetup to handle Code Signing, can't I just sign the resulting setup.exe myself? The main reason for letting Innosetup handle code signing the installer is that it also signs the uninstaller.&lt;/p&gt;
</description><guid isPermaLink="false">852</guid></item><item><title>Introducing Signotaur - Remote Code Signing Server</title><link>https://www.finalbuilder.com/resources/blogs/postid/851/introducing-signotaur-remote-code-signing-server</link><category>.NET,Code Signing,Delphi</category><pubDate>Wed, 04 Dec 2024 08:45:00 GMT</pubDate><description>&lt;p&gt;Over the last few years, code signing has changed somewhat. With the &lt;a href="https://www.finalbuilder.com/resources/blogs/code-signing-with-usb-tokens" target="_blank"&gt;requirement&lt;/a&gt; that private keys be secured, many developers have run into the issues that USB tokens present, or the limitations and costs associated with cloud-based signing solutions. Gone are the days of sharing a PFX file around the dev team or with the CI server (unless you managed to snag a 3-year renewal just before the new requirements were enforced).&lt;/p&gt;

&lt;h2&gt;Signotaur&lt;/h2&gt;

&lt;p&gt;Signotaur is a self-hosted code signing server that makes sharing certificates simple, all whilst maintaining the security of your private keys. Signing can be done (using the client) from any machine that has network access to the server.&lt;/p&gt;

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

&lt;h3&gt;Secure Code Signing&lt;/h3&gt;

&lt;p&gt;Private keys never leave the server, or the USB token or HSM for that matter. The client/server both support TLS (and can generate a self-signed certificate during the install), and administrators can configure access controls to limit who can use certificates for signing. Signing uses API keys rather than passwords, so no more dreaded SafeNet or YubiKey password prompts!&lt;/p&gt;

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

&lt;h3&gt;Supported Certificates&lt;/h3&gt;

&lt;p&gt;We have tested with PFX files, SafeNet, Certum and YubiKey USB tokens, and Windows certificate stores. Signotaur may work with other USB tokens or HSMs that have 64-bit PKCS#11 drivers.&lt;/p&gt;

&lt;h3&gt;Lightweight&lt;/h3&gt;

&lt;p&gt;Signotaur Server uses very little memory, CPU, or disk space. It uses SQLite for its database. Installing Signotaur takes a few minutes at most.&lt;/p&gt;

&lt;p&gt;Signotaur Client is a single native Windows executable (around 15MB). It's installed with the server and can be downloaded from the server's home page. The command-line interface is very similar to SignTool.&lt;/p&gt;

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

&lt;h3&gt;How does it work&lt;/h3&gt;

&lt;p&gt;In simple terms, the client calculates a digest of the files you want to sign, sends that to the server, which then uses the private key to create the signature and sends that back to the client. The client then writes the signatures to the files.&lt;/p&gt;

&lt;h3&gt;Supported Platforms&lt;/h3&gt;

&lt;p&gt;For this initial release, Signotaur (client and server) runs on 64-bit Windows 10+, Windows Server 2016, or later. Linux support for the server is in development.&lt;/p&gt;

&lt;h3&gt;Affordable&lt;/h3&gt;

&lt;p&gt;Unlike cloud-based services, we don't charge per signing, and the price isn't "available on application" like some "enterprise" products. The introductory price is USD $199 per server, and with the Black Friday Sale extended to midnight 8th December, that makes it USD $119.40 (discount applied at checkout). The price includes 12 months of updates and support. Renewals after 12 months are 30% of the new purchase price.&lt;/p&gt;

&lt;p&gt;Download it &lt;a href="/downloads/signotaur"&gt;here&lt;/a&gt;. After installation, login and browse to the admin\licenses page and request a 14 day trial license key.&lt;/p&gt;
</description><guid isPermaLink="false">851</guid></item><item><title>Black Friday Sale 2024 - 40% off all new licenses</title><link>https://www.finalbuilder.com/resources/blogs/postid/850/black-friday-sale-2024-40-off-all-new-licenses</link><category>Delphi,General</category><pubDate>Thu, 28 Nov 2024 09:38:11 GMT</pubDate><description>&lt;p&gt;Black Friday Sale - 40% off all new licenses until midnight (utc) &lt;s&gt;4th December 2024.&lt;/s&gt; &lt;span style="color:#c0392b;"&gt;Extended &lt;/span&gt;to midnight (utc) 8th December 2024.&lt;/p&gt;

&lt;p&gt;No coupon code required, the store will apply the discount automatically.&lt;/p&gt;
</description><guid isPermaLink="false">850</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>DPM Package Manager - Progress update</title><link>https://www.finalbuilder.com/resources/blogs/postid/842/dpm-package-manager-progress-update</link><category>Delphi,DPM</category><pubDate>Wed, 24 Feb 2021 10:46:15 GMT</pubDate><description>        &lt;p&gt;In December 2019, I &lt;a href="/resources/blogs/introducing-dpm-a-package-manager-for-delphi" target="_blank"&gt;blogged&lt;/a&gt; about a package manager for Delphi that I am working on. This post is
            a progress update that shows where it's at and what's left to do to get to v1.&lt;/p&gt;

        &lt;h3&gt;DPM Recap&lt;/h3&gt;

        &lt;p&gt;
            For those not familiar with what I am trying to achieve here, I highly recommend reading my original &lt;a href="/resources/blogs/delphi-package-manager-rfc" target="_blank"&gt;
                Delphi Package Manager RFC&lt;/a&gt; post. In that post I detailed my ideas, and some of the challenges that Delphi presents when compared to other development environments.
        &lt;/p&gt;

        &lt;p&gt;
            In December 2019, the bare bones of DPM were there. We had a command line tool and that was it. We were able to create packages, install packages (and their dependencies) and restore them
            (restore ensures all referenced packages are present). Oh and we could list the available packages in our package feed (a folder).
        &lt;/p&gt;

        &lt;h3&gt;IDE Integration&lt;/h3&gt;

        &lt;p&gt;
            In the last 13 months there were around 175 commits to the DPM repository. In that time I have added an IDE plugin (that works in Delphi XE2 to 10.4). This involved the creation of several
            custom controls (I wasn't able to bend any existing ones to work how I wanted it to).
        &lt;/p&gt;

        &lt;p&gt;
            In addition to the work in the project repository, I also published &lt;a href="https://github.com/vsoftTechnologies/" target="_blank"&gt;several useful libraries&lt;/a&gt; that I needed for this
            project. DPM is now bootstrapped, to build DPM you need DPM, as it requires several libraries that are referenced as dpm packages.
        &lt;/p&gt;

        &lt;p&gt;
            In Nov 2020 I published the first alpha release that included an installer (code signed by VSoft Technologies) for installing both the command line tool and the IDE plugin (single
            installer, you can choose which IDE versions to install for). The installer allows you to install for the current user, or for all users (requires elevation to install).
        &lt;/p&gt;

        &lt;img src="https://cdn.finalbuilder.com/blog/vincent/dpm-progress/installer.png"&gt;
        &lt;p&gt;&lt;/p&gt;
        &lt;p&gt;
            I also did a zoom presentation about DPM to the Melbourne chapter of the Australian Delphi Users Group - a recording of that (long) presentation can be found &lt;a
               href="https://www.youtube.com/watch?v=TjVAMLfhgLo" target="_blank"&gt;here&lt;/a&gt;.
        &lt;/p&gt;

        &lt;p&gt;
            Adding IDE support for DPM was a massive undertaking. I had very little experience in developing Delphi IDE plugins (using the tools api) - and there were lots of subtle changes between
            delphi versions, getting things working correctly in 12 versions of Delphi was not easy. In particular, with the later versions of Delphi IDE that use VCL themes, getting things to look
            right (ie like a native part of the IDE) was a challenge.
        &lt;/p&gt;

        &lt;img src="https://cdn.finalbuilder.com/blog/vincent/dpm-progress/dpm-ide.png"&gt;
        &lt;p&gt;&lt;/p&gt;
        &lt;p&gt;The above image shows the installed packages for one of the projects in the project group, you get to this view by right clicking on the project node, or the DPM Packages node in the
            Project tree. &lt;/p&gt;
        &lt;p&gt;Note the view only shows the directly installed packages, not the transient dependencies - those you can see in the project tree under the DPM Packages node.&lt;/p&gt;
        &lt;p&gt;Before you can use DPM in the IDE, you need to configure a package source (a folder where your package files will live)&lt;/p&gt;
        &lt;p&gt;This can be done fron the command line&lt;/p&gt;
        &lt;pre&gt;dpm sources add -name=local -source=path to the folder you created&lt;/pre&gt;
        &lt;p&gt;&lt;/p&gt;
        &lt;p&gt;Or from the IDE Settings&lt;/p&gt;
        &lt;img src="https://cdn.finalbuilder.com/blog/vincent/dpm-progress/dpm-settings.png"&gt;
        &lt;p&gt;&lt;/p&gt;
        &lt;h3&gt;Compile during install&lt;/h3&gt;
        &lt;p&gt;
            The most recent updates added support for compiling packages during first install. Packages need to declare how to build in their dspec file, and dpm will use that and call msbuild to
            compile the packages if needed. DPM also records a bill of materials file (package.bom) in the package cache so that it can tell whether the package needs to be recompiled or not.
        &lt;/p&gt;

        &lt;p&gt;On first install, packages that are being compiled during the install process will take a little longer, but on subsequent installs or restores, the process is almost instant (a few ms).
        &lt;/p&gt;

        &lt;p&gt;
            Prior to adding this feature, building dpm on our Continua CI build agents took 13 minutes, much of which was taken up with compiling the dpm packages that it references (in particular,
            earlier versions of Delphi were very slow with spring4d). Since updating dpm on our agents with the new version, the entire build process for DPM (console app and 12 versions of the IDE
            plugin and the installer) takes less than 2 minutes.
        &lt;/p&gt;
        &lt;img src="https://cdn.finalbuilder.com/blog/vincent/dpm-progress/dpm-build-times.png"&gt;
        &lt;p&gt;&lt;/p&gt;
        &lt;h3&gt;Missing features&lt;/h3&gt;

        &lt;h4&gt;Project group support&lt;/h4&gt;

        &lt;p&gt;
            When installing packages, the dependency resolution code does not know about other projects in the project group, or what packages and versions they reference. This
            will be a problem for packages that include design time components that need to be loaded - the IDE can only load 1 version of a design time package. This is what I am currently working
            on.
        &lt;/p&gt;

        &lt;h4&gt;Design time packages&lt;/h4&gt;
        &lt;p&gt;DPM does not currently install design time packages into the IDE. This is dependent on project group support, so it's next on the list after project group support.&lt;/p&gt;

        &lt;h4&gt;Package Updates&lt;/h4&gt;
        &lt;p&gt;The ability to detect when package updates are available and make it easy to install those updates. There's an Updates tab in the IDE but it's non functional at this time.&lt;/p&gt;

        &lt;h4&gt;Package Repository&lt;/h4&gt;

        &lt;p&gt;In it's current state, DPM only supports folder based package feeds. This works fine, but it does have some limitations&lt;/p&gt;
        &lt;ul&gt;
            &lt;li&gt;Limted search abilities - limted to searching on the package filenames.&lt;/li&gt;
            &lt;li&gt;You have to download packages to a folder.&lt;/li&gt;
            &lt;li&gt;Package Authors have to host the package files somewhere (mine are under releases on their github projects).&lt;/li&gt;
        &lt;/ul&gt;
        &lt;p&gt;I have made a start on the Package Repository, but not a lot of progress since I'm focusing on the client site right now.&lt;/p&gt;

        &lt;h3&gt;Q &amp; A&lt;/h3&gt;

        &lt;h4&gt;Is it usable?&lt;/h4&gt;
        &lt;p&gt;In it's current state, it's only usable for non visual libraries. As I mentioned, the DPM projects all use DPM themselves, and
            we have DPM actions in FinalBuilder for running the Pack and Restore commands. &lt;/p&gt;
        &lt;p&gt;If you use any of my open source libraries like DUnitX, Delphi Mocks etc, I have created packages for all of those libraries, and also
            created mirror projects (just for hosting the package files) for some other popular libraries like Spring4D. &lt;/p&gt;
        &lt;p&gt;I would encourage library authors in particular to take a look and provide feedback.&lt;/p&gt;

        &lt;h4&gt;Where can we find it?&lt;/h4&gt;
        &lt;p&gt;DPM is an open source project on &lt;a href="https://github.com/DelphiPackageManager/DPM" target="_blank"&gt;GitHub&lt;/a&gt;, the installer can be found under &lt;a
               href="https://github.com/DelphiPackageManager/DPM/releases" target="_blank"&gt;Releases&lt;/a&gt;
            (under each release, there is an Assets dropdown section).&lt;/p&gt;
        &lt;img src="https://cdn.finalbuilder.com/blog/vincent/dpm-progress/installer-location.png"&gt;
        &lt;p&gt;&lt;/p&gt;

        &lt;h4&gt;What versions of Delphi does it support?&lt;/h4&gt;
        &lt;p&gt;Delphi XE2 to 10.4.2 - note that we compile with the latest updates installed for each compiler version. &lt;/p&gt;

        &lt;h4&gt;Why is it taking so long?&lt;/h4&gt;
        &lt;p&gt;Yes, someone asked that recently! This is a side project, free and open source. My primary focus is on running my business and working on our products (that keeps the lights on).&lt;/p&gt;

        &lt;h4&gt;Can we sponsor the project?&lt;/h4&gt;
        &lt;p&gt;Not right now, however it's something I'll look at in the future. &lt;/p&gt;

        &lt;h4&gt;Can we help?&lt;/h4&gt;
        &lt;p&gt;Absolutely. Fork the project on GitHub and clone it to your dev machine and spend some time getting to know the source code. Before making any pull requests, create an issue on github
            to discuss your ideas and make sure we on the same wavelength!&lt;/p&gt;</description><guid isPermaLink="false">842</guid></item><item><title>Advice for Delphi library authors</title><link>https://www.finalbuilder.com/resources/blogs/postid/841/advice-for-delphi-library-authors</link><category>Delphi,DPM</category><pubDate>Wed, 24 Feb 2021 00:57:00 GMT</pubDate><description>        &lt;p&gt;We use many third-party Delphi libraries to build FinalBuilder and Automise, and that brings plenty of issues when upgrading compiler versions. I've been using Delphi since 1995, both as a
            developer and as a component vendor, I have learned a thing or two about creating libraries that I would like to share. These are all ideas that make life easier for users, and make it
            easy to migrate from one version of Delphi to another.&lt;/p&gt;
        &lt;p&gt;There's no hard and fast rules on how Delphi Libraries are &lt;i&gt;supposed to be&lt;/i&gt; structured, these are just my preferences and things I have learned over the years. Hopefully this will
            help new and existing library authors.&lt;/p&gt;

        &lt;h3&gt;Folder Structure&lt;/h3&gt;
        &lt;p&gt;Keep the Source and the Packages in separate folders, this makes it easier to find the correct packages to compile, e.g :
        &lt;pre&gt;\Source
\Packages
\Demos&lt;/pre&gt;
        &lt;/p&gt;
        &lt;p&gt;Under Packages, create a folder for each compiler version your library supports, e.g:
        &lt;pre&gt;\Packages\Rad Studio XE8
\Packages\Rad Studio 10.0
\Packages\Rad Studio 10.1&lt;/pre&gt;
        &lt;/p&gt;
        &lt;h3&gt;Package Names&lt;/h3&gt;

        &lt;p&gt;Please, &lt;b&gt;do not&lt;/b&gt; put the Delphi version in the package project names.&lt;/p&gt;
        &lt;h4&gt;Bad!!!&lt;/h4&gt;
        &lt;pre&gt;MyProjectRun_D10_4.dproj
MyProjectDesign270.dproj&lt;/pre&gt;
        &lt;h4&gt;Good&lt;/h4&gt;
        &lt;pre&gt;MyProjectRun.dproj
MyProjectR.dproj
MyProjectDesign.dproj
MyProjectD.dproj&lt;/pre&gt;
        &lt;p&gt;&lt;/p&gt;
        &lt;p&gt;Why not put the compiler version in the package project name you might ask? Well the answer is that it makes upgrading compiler versions a major pain for users who link their
            projects with Runtime Packages (yes, that includes us).&lt;/p&gt;

        &lt;p&gt;The reason is that when you compile a package, it creates a packagename.dcp file and that is what your project references. So, if your package name is MyPackageRun_D10_4 then that is what
            will be added to projects that use it.&lt;/p&gt;


        &lt;pre class="brush:delphi; toolbar:false;"&gt;
package MyOwnPackage;
//...
requires
  rtl,
  vcl,
  MyPackageRun_D10_4,
  AnotherPackage_Sydney,
  YetAnotherPackage_D104,
//  ...
        &lt;/pre&gt;
        &lt;p&gt;&lt;/p&gt;
        &lt;p&gt;When Delphi 10.5 comes out, guess what the user has to do to upgrade their projects.... Yep, replace that all those package references with 10.5 versions (and the multitude of suffixes).
            Multiply that by a number
            of
            projects and a number of libraries (each with potentially multiple runtime packages) and you can see why this might be a pain.&lt;/p&gt;

        &lt;p&gt;Now you might say, but we don't want 15 versions of MyPackageRun.bpl laying about on users machines, and you would be right. The solution to this is a feature that has been around
            since Delphi 6 (2001) - &lt;a href="https://docwiki.embarcadero.com/RADStudio/Sydney/en/Compiler_directives_for_libraries_or_shared_objects_(Delphi)" target="_blank"&gt;LIBSUFFIX&lt;/a&gt;.&lt;/p&gt;
        &lt;img src="https://cdn.finalbuilder.com/blog/vincent/advice-for-d/libsuffix.png" alt="LIBSUFFIX"&gt;
        &lt;p&gt;&lt;/p&gt;
        &lt;p&gt;Setting LIBSUFFIX (on the Description section of project settings) will append the specified suffix to the BPL file name. So a suffix of _D10_4 will result in a package :&lt;/p&gt;
        &lt;pre&gt;MyPackageRun_D10_4.bpl&lt;/pre&gt;
        &lt;p&gt;&lt;/p&gt;
        &lt;p&gt;however, the DCP file will still be generated as :&lt;/p&gt;
        &lt;pre&gt;MyPackageRun.dcp&lt;/pre&gt;
        &lt;p&gt;&lt;/p&gt;
        &lt;p&gt;Remember it's the dcp file that our projects reference (for linking) - so by keeping the dcp file the same for all delphi versions, upgrading to a new compiler version just got a whole lot
            easier!&lt;/p&gt;

        &lt;p&gt;So when Delphi 10.5 comes out in the future, all I need to do is install the packages, no changes to my projects.&lt;/p&gt;

        &lt;p&gt;&lt;b&gt;Update&lt;/b&gt; : Someone pointed out that Delphi 10.4.1 support LIBSUFFIX $(Auto) - this will use the Delphi defined PackageVersion - which for 10.4 is 270. This is a nice addition 
            as it makes upgrading the package projects simpler. Of course if you don't like the PackageVersion suffix and use a custom one, then this is not for you.&lt;/p&gt;

        &lt;h3&gt;Use Explicit rebuild, not Rebuild as needed&lt;/h3&gt;
        &lt;p&gt;Have you ever encountered the error
        &lt;pre&gt;E2466 Never-build package 'XXX' requires always-build package 'YYY'&lt;/pre&gt;
        What this means is, a package, set to Expicit rebuild, references another package, set to 'Rebuild as needed', and it's a pain in the proverbial. Rebuild as needed is also referred to
        as Implicit Build - in dpk's you will see it as
        &lt;pre&gt;{$IMPLICITBUILD ON}&lt;/pre&gt;
        If that "Rebuild as needed" package is not part of your project group, guess what, you get to waste time closing and opening projects trying to get it to compile.
        &lt;/p&gt;
        &lt;p&gt;I'm sure someone will correct me on this, but I cannot see a good reason to have "Rebuild as needed" set. I suspect this is a hangover from before the Delphi IDE
            allowed you to specify &lt;a href="https://docwiki.embarcadero.com/RADStudio/Sydney/en/Project_Dependencies" target="_blank"&gt;Project Dependencies&lt;/a&gt; and it slows down builds.
        &lt;/p&gt;

        &lt;h3&gt;Use Search Paths for includes&lt;/h3&gt;

        &lt;p&gt;I often see includes with either hard coded paths, or relative paths like this :&lt;/p&gt;
        &lt;pre class="brush:delphi; toolbar:false;"&gt;
{$I '..\..\MyDefines.inc'}
        &lt;/pre&gt;
        &lt;p&gt;That's great, if the installer delivers the files in the right place - but they often don't - I hit this issue today, where the package just would not compile. I eventually
            figured out that the relative path was wrong.
        &lt;/p&gt;

        &lt;p&gt;There's a simple fix for this, and that is to remove the path in the $I statement, and use the Project Search Paths feature instead. &lt;/p&gt;

        &lt;img src="https://cdn.finalbuilder.com/blog/vincent/advice-for-d/searchpath.png" alt="Search Paths"&gt;
        &lt;p&gt;&lt;/p&gt;
        &lt;p&gt;I have also seen libraries where there are mulitple copies of the include file and they are slightly different!&lt;/p&gt;

        &lt;h3&gt;Mark packages as Runtime only or Designtime only&lt;/h3&gt;
        &lt;p&gt;Some libraries have their packages marked as "Runtime and Designtime" (the default) - the impact of this is only minor, but it's a pet peeve of mine. The Delphi IDE (in recent versions at
            least) provides a nice indication of whether packages are runtime or designtime in the project tree, and for designtime packages, whether they are installed. &lt;/p&gt;
        &lt;p&gt;This makes it simple for me to determine which ones need to be installed or not.&lt;/p&gt;
        &lt;p&gt;Not Installed&lt;/p&gt;
        &lt;img src="https://cdn.finalbuilder.com/blog/vincent/advice-for-d/not-installed.png" alt="Not Installed"&gt;
        &lt;p&gt;Installed&lt;/p&gt;
        &lt;img src="https://cdn.finalbuilder.com/blog/vincent/advice-for-d/installed.png" alt="Installed"&gt;
        &lt;p&gt;&lt;/p&gt;

        &lt;h3&gt;Summing up&lt;/h3&gt;

        &lt;p&gt;One of the major reasons people do not upgrade Delphi versions is because it's too hard to deal with the third party libraries and all the changes required just to
            get to the point of compiling. That eventually results in a lack of Delphi sales which results in a lack of investment in Delphi which feeds back into.... well you get the idea ;)&lt;/p&gt;

        &lt;p&gt;Making third party libraries easier to work with in Delphi has been a bit of a crusade for me, I've been &lt;a href="/resources/blogs/delphi-package-manager-rfc"&gt;working on this for a while
                now&lt;/a&gt;,
            and I'm getting closer to a solution - &lt;a href="https://github.com/DelphiPackageManager/DPM"&gt;DPM - A package manager for Delphi&lt;/a&gt; - if you are a library author, I encourage you
            to take a look. For examples on how to create a package spec (dspec) take a look at our open source projects &lt;a
               href="https://github.com/vsoftTechnologies/"&gt;https://github.com/vsoftTechnologies/&lt;/a&gt;
        &lt;/p&gt;
</description><guid isPermaLink="false">841</guid></item><item><title>Introducing DPM - a Package Manager for Delphi</title><link>https://www.finalbuilder.com/resources/blogs/postid/837/introducing-dpm-a-package-manager-for-delphi</link><category>Delphi,DPM,Open Source</category><pubDate>Thu, 12 Dec 2019 09:41:00 GMT</pubDate><description>&lt;p&gt;Back in Feb 2019, I &lt;a href="/resources/blogs/delphi-package-manager-rfc" target="_blank"&gt;blogged&lt;/a&gt; about the need for a Package Manager for Delphi. The blog post garnered lots of mostly useful feedback and encouragement, but until recently I could never find a solid block of time to work on it. Over the last few weeks I've been working hard to get it to an mvp stage.&lt;/p&gt;

&lt;p&gt;DPM is an &lt;b&gt;open source&lt;/b&gt; package/library manager for Delphi XE2 or later. It is heavily influenced by Nuget, so the cli, docs etc will seem very familiar to nuget users. Delphi’s development environment is quite different from .net, and has different challenges to overcome, so whilst I drew heavily on nuget, DPM is not identical to nuget. I also took a close look at many other package managers for other development eco systems.&lt;/p&gt;

&lt;h2&gt;What is a Package Manager&lt;/h2&gt;

&lt;p&gt;A package manager provides a standard for developers to share and consume code. Authors create packages that other developers can consume. The package manager provides a simple way to automate the installation, upgrading or removal of packages. This streamlines the development process, allowing developers to get up and running on a project quickly, without needing to understand the (usually adhoc) way the project or organization has structured their third party libraries. This also translates into simpler build/CI processes, with less ‘compiles on my machine’ style issues.&lt;/p&gt;

&lt;h2&gt;Who and Why&lt;/h2&gt;

&lt;p&gt;DPM’s initial developer is Vincent Parrett (author of DUnitX, FinalBuilder, Continua CI etc). Why is discussed in &lt;a href="https://www.finalbuilder.com/resources/blogs/delphi-package-manager-rfc"&gt;this blog post&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;DPM Status&lt;/h2&gt;

&lt;p&gt;DPM is still in development, so not all functionality is ready yet. At this time, it's at the stage where we I would encourage library authors to take a look and play with it and provide feedback (and perhaps get involved in the development). It's very much at a minimum viable product stage. Potential users are of course welcome to look at it and provide feedback, it's just that, well, there are no packages for it yet (there's some test packages in the repo, and I'll be creating ones for my open source libraries). .&lt;/p&gt;

&lt;h3&gt;What works&lt;/h3&gt;

&lt;ul&gt;
	&lt;li&gt;Creating packages&lt;/li&gt;
	&lt;li&gt;Pushing packages to a package source.&lt;/li&gt;
	&lt;li&gt;Installing packages, including dependencies&lt;/li&gt;
	&lt;li&gt;Restoring packages, including dependencies.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;How do I use it&lt;/h3&gt;

&lt;p&gt;The documentation is at &lt;a href="https://docs.delphi.dev"&gt;https://docs.delphi.dev&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;See the &lt;a href="https://docs.delphi.dev/getting-started/installing.html"&gt;getting started guide&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The command line documentation can be found &lt;a href="https://docs.delphi.dev/commands/commands.html"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The Source is on GitHub &lt;a href="https://github.com/DelphiPackageManager/DPM"&gt;https://github.com/DelphiPackageManager/DPM&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;Is DPM integrated into the Delphi IDE&lt;/h3&gt;

&lt;p&gt;Not yet but it is planned. If you are a wiz with the open tools api and want to contribute then let us know.&lt;/p&gt;

&lt;h3&gt;Is there a central package source&lt;/h3&gt;

&lt;p&gt;Not yet but it is planned. At the moment, only local folder based &lt;a href="https://docs.delphi.dev/concepts/package-sources.html"&gt;sources&lt;/a&gt; are supported. The client code architecture has a provision for http based sources in the future, however right now we are focused on nailing down the package format, dependency resolution, installation, updating packages etc.&lt;/p&gt;

&lt;h3&gt;Is my old version of delphi supported&lt;/h3&gt;

&lt;p&gt;Maybe, &lt;a href="https://docs.delphi.dev/compiler-versions.html"&gt;see here&lt;/a&gt; for supported compiler versions. All target &lt;a href="https://docs.delphi.dev/platforms.html"&gt;platforms&lt;/a&gt; for supported compiler versions are supported.&lt;/p&gt;

&lt;h3&gt;What about C++ Builder or FPC&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://docs.delphi.dev/compiler-versions.html"&gt;see here&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;Does it support design time components&lt;/h3&gt;

&lt;p&gt;Not yet, but that is being worked on.&lt;/p&gt;

&lt;h3&gt;How does it work&lt;/h3&gt;

&lt;p&gt;See &lt;a href="https://docs.delphi.dev/concepts/how-it-works.html"&gt;this page&lt;/a&gt;&lt;/p&gt;
</description><guid isPermaLink="false">837</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>New VSoft Forums</title><link>https://www.finalbuilder.com/resources/blogs/postid/831/new-vsoft-forums</link><category>Delphi,General,Web Development</category><pubDate>Mon, 10 Sep 2018 15:13:04 GMT</pubDate><description>&lt;p&gt;TLDR; Our forums have moved to &lt;a href="https://www.finalbuilder.com/forums"&gt;https://www.finalbuilder.com/forums&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After years of frustration with Active Forums on Dotnetnuke, we finally got around to moving to a new forums platform. &lt;/p&gt;

&lt;p&gt;The old forums had zero facilities for dealing with spammers, and sure enough every day, spammers would register on the website and post spam on the forums. Even after turning on email verification (where registration required verifying your email), spammers would verify their emails and post spam.&lt;/p&gt;

&lt;p&gt;The old forums were also terrible at handling images, code markup etc, and will often completely mangle any content you paste in.&lt;/p&gt;

&lt;p&gt;So the hunt was on for a new platform. I've lost count of the number of different forum products I've looked at over the years, none of which totally satisfied my needs/wants. I've even contemplated writing my own, but I have little enough free time as it is, and would much rather focus on our products. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://discourse.org"&gt;Discourse&lt;/a&gt;  looked interesting, so I installed it on a Ubuntu Server 18.04 virtual machine (it runs in a Docker container). After some initial trouble with email configuration (it didn't handle subdomains properly) it was up and running. I'm not great with linux, I've tinkered with it many times over the years but never really used it for any length of time. I was a little apprehensive about installing Discourse, however their guide is pretty good and I managed just fine. &lt;/p&gt;

&lt;p&gt;The default settings are pretty good, but it is easy to configure. After experimenting with it for a few days (there are a LOT of options), we we liked it a lot, and decided to go with it. &lt;/p&gt;

&lt;p&gt;Discourse is Excellent at handling bad markup, I'm astounded at how well it deals with malformed html and just renders a good looking post (most of the time). Inserting images is a breeze, the editor will accept Markdown or html, and gives an accurate preview while you are writing a post. Posting code snippets works well usng the same markup as github, with syntax highlighting for a bunch of languages (C#, delphi, javascript, vbscript, xml etc). The preview makes it easy to tell when you have things just right. Discourse also works very well on mobile, although our website does not (the login page is usable) - more work to be done there (like a whole new site!). &lt;/p&gt;

&lt;p&gt;Discourse is open source (GPL), so you can either host it yourself (free) or let Discourse.org host if for you (paid, starting at $100pm). Since we had spare capacity on our web servers (which run hypver-v 2016) I chose to host it ourselves. That was 11 days ago. &lt;/p&gt;

&lt;p&gt;My goal was to import the content from the old forums, there are 12 years of valuable posts there which I was loath to lose. &lt;/p&gt;

&lt;p&gt;The first challenge was that Discourse requires unique emails, and our dotnetnuke install did not. After 12 years of upgrades, our database was in a bit of a sorry state. There were many duplicate accounts (some users had 5 accounts), I guess if you can't remember your login you just create a new one, right? I can't totally blame users for that, the password reset email system was unreliable in the past (it should be ok now, check your spam folder!). So we cleaned up the database, removed old accounts that had no licenses and no forum posts. &lt;/p&gt;

&lt;p&gt;The next challenge was enabling single sign on with the website. Someone had written a dotnetnuke extension for it, but I wasn't able to get it working (it was written for an older version), so I spent 2 days writing my own (and almost losing the will to live!). Once that was sorted, I got to work on importing the data. Discourse does have a bunch of import code on &lt;a href="https://github.com/discourse/discourse/tree/master/script/import_scripts"&gt;github&lt;/a&gt; - none of which are for dotnetnuke, and they are all written in Ruby (which I have zero experience with). Fortunately, Discourse does have a &lt;a href="https://docs.discourse.org/"&gt;rest api&lt;/a&gt; - so using C# (with dapper &amp; restsharp) I set about writing a tool to do the import. Since Discourse doesn't allow you to permanently delete topics, this needed to work first time, and be restartable when an error occurred. This took 4 days to write, much of which was just figuring out how to get past the rate limits Discourse imposes. I did this all locally with a back up of the website db and a local discourse instance. The import took several hours, with many restarts (usually due to bad content in the old forums, topics too short etc). &lt;/p&gt;

&lt;p&gt;Backing up the local instance of Discourse was trivial, as was restoring it on the remote server (in LA). We did have to spend several hours fixing a bunch of posts, and then some time with sql fixing dates (editing a post sends it to the top of a category). I did also have to ssh into the container to "rebake" the posts to fix image url issues. Fortunately theres is a wealth of info on &lt;a href="https://meta.discourse.org"&gt;Discourse's own forums&lt;/a&gt; - and search works really well!&lt;/p&gt;

&lt;p&gt;We chose not to migrate the FinalBuilder Server forum (the product was discontinued in 2013) or the Action Studio forum (which gets very few posts).  &lt;/p&gt;

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

&lt;p&gt;I'm sure we'll still be tweaking the forums over the next few weeks, but on the whole we are pretty happy with how they are. Let us know what you think (in the &lt;a href="https://www.finalbuilder.com/forums/c/site-feedback"&gt;Site Feedback&lt;/a&gt; forum!).&lt;/p&gt;
</description><guid isPermaLink="false">831</guid></item><item><title>Delphi Package Manager RFC</title><link>https://www.finalbuilder.com/resources/blogs/postid/777/delphi-package-manager-rfc</link><category>Delphi,DPM,Open Source</category><pubDate>Mon, 16 Jul 2018 01:58:00 GMT</pubDate><description>&lt;p&gt;Delphi/Rad Studio desperately needs a proper package/library/component manager. A package manager provides a standardized way of consuming third party libraries. At the moment, use of third party libraries is very much adhoc, and in many cases this makes it difficult to move projects between machines, or to get a new hire up and running quickly.&lt;/p&gt;

&lt;p&gt;Other developement environments, like the .net and javascript eco systems, recognised and solved this problem many years ago. Getting a .net or javascript project up an running, in a new working folder or new machine is trivial.&lt;/p&gt;

&lt;p&gt;With Delphi/Rad Studio, it's much harder than it should be. In consulting work, I've made it a point to see how clients were handling third party code, and every client had a different way. The most common technique was... well, best described as adhoc (with perhaps a readme with the list of third party products to install). Getting that code compiling on a CI server was a nightmare.&lt;/p&gt;

&lt;h2&gt;Existing Package Managers&lt;/h2&gt;

&lt;p&gt;Embarcadero introduced their GetIt package manager with XE8, and the GetIt infrastructure has certainly has made the installation of RAD Studio itself a lot nicer. But as a package manager for third party libraries, it comes up short in a number of areas.&lt;/p&gt;

&lt;p&gt;There is also Delphinus, which is an admirable effort, but hasn't gotten much traction, possibly due to it being strongly tied to github (you really need github account to use it, otherwise you get api rate limiting errors).&lt;/p&gt;

&lt;p&gt;Rather than pick apart GetIt or Delphinus, I'd like to outline my ideas for a Delphi package manager. I spend a lot of time working with .net (nuget) and javascript (npm, yarn), so they have very much influenced what I will layout below.&lt;/p&gt;

&lt;p&gt;I have resurrected an old project (from 2013) that I shelved when GetIt was announced, and I have spent a good deal of time thinking about package management (not just in Delphi), but I'm sure I haven't thought of everything, I'd love to hear feedback from people interested in contributing to this project, or just potential users.&lt;/p&gt;

&lt;h2&gt;Project Ideals&lt;/h2&gt;

&lt;p&gt;These are just some notes that I wrote up when I first started working on this back in 2013, I've tried to whip them into some semblance of order for presentation here, but they are just just rough outline of my ideas.&lt;/p&gt;

&lt;h3&gt;Open Source&lt;/h3&gt;

&lt;p&gt;The Project should be Open Source. Of course we should welcome contributions from commercial entities, but the direction of the project will be controlled by the community (ie users). The project will be hosted on GitHub, and contributions will be made through Pull Requests, with contributions being reviewed by the Steering committee (TBA).&lt;/p&gt;

&lt;h3&gt;Public Package Registry&lt;/h3&gt;

&lt;p&gt;There will be a public website/package server, where users can browse the available packages, and package authors can upload packages. This will be a second phase of the project, with the initial phase being focused on getting a working client/package architecture, with a local or network share folder for the package source.&lt;/p&gt;

&lt;p&gt;The package registry should not be turned into a store. Once a public package registry/server is available, evaluation packages could be be allowed, perhaps by providing a fee (web hosting is not free). Commercial vendors will of course be able to distribute commercial packages directly to their customers, as the package manager will support hosting of packages in a shared network or local directory. Package meta data will include flags to indicate if the packages are commercial, eval or free/open source. Users will be able to decide which package types show up in their searches.&lt;/p&gt;

&lt;h3&gt;Package Submission&lt;/h3&gt;

&lt;p&gt;Package submission to the public registry should be a simple process, without filling in and signing and faxing of forms! We will follow the lead of nuget, npm, ruby etc on this. There should be a dispute process for package names, copyright infringement etc. There will also be the ability to assign ownership of a package, for example when project ownership changes.&lt;/p&gt;

&lt;p&gt;Package Authors will be able to reserve a package prefix, in order to prevent other authors from infringing on their names or copyrights. For example, Embarcadero might reserve Emb. as their prefix, TMS might reserve TMS. as theirs. (of course I'm hoping to get both on board). The project will provide a dispute resolution process for package prefixes and names.&lt;/p&gt;

&lt;h2&gt;Delphi specific challenges&lt;/h2&gt;

&lt;p&gt;Delphi presents a number of challenges when compared to the .net or nodejs/javascript world.&lt;/p&gt;

&lt;h3&gt;Compatibility&lt;/h3&gt;

&lt;p&gt;With npm, packages contain source (typically minimized and obfuscated) which is pure javascript. Compatibility is very high.&lt;/p&gt;

&lt;p&gt;With Nuget, packages contain compiled (to .NET IL) assemblies. A package might contain a few different versions, that target different the versions of the .net framework. Again, compatibility is pretty good, an assembly compiled against .net 2.0 will work on .net 4.7 (.net core breaks this, but it has a new compatibility model, netstandard).&lt;/p&gt;

&lt;p&gt;If we look at Delphi, binary compatibility between Delphi compiler versions is pretty much non existent(yes, I know about 2006/7 etc). The dcu, dcp and bpl files are typically only compatible with the version they were compiled with. They are also only compatible with the platform they were generated for (so you can't share dcu's between 32 and 64 bit windows, or between iOS and Android). So we would need to include binaries for each version of Delphi we want our library to support. This also has major implications for library dependencies. Where as npm and nuget define dependencies as a range of versions, a binary dependency in Delphi would be fixed to that specific version. There is a way to maintain binary compatibility between releases, provided the interfaces do not change, however exactly what the rules are for this is hard to come by, so for now we'll ignore that possibility.&lt;/p&gt;

&lt;p&gt;That limits the scope for updating to newer versions of libraries, but that can also be overcome by including the source code in package, and providing on the fly compilation of the library during install. My preference would be for pre-compiled libraries, as that speeds up the build process (of course, since that's an area I have a particular interest in). In Continuous Integration environments, you want to build fast and build often, rebuilding library code with each CI build would be painful (speaking from experience here, 50% of time building FinalBuilder is building the third party libraries).&lt;/p&gt;

&lt;p&gt;There's also the consideration of Debug vs Release - so if we are including binaries, compiled for Release would be required, but Debug optional? The size of a package file could be problematic. If the package contains pre-compiled binaries for multiple compiler versions, it could get rather large. So perhaps allow for packages that either support a single compiler version, or multiples? The compilers supported would be exposed in the package metadata, and perhaps also in the package file name. Feedback, ideas around this would be welcome.&lt;/p&gt;

&lt;p&gt;Package files would be (like with other package managers), a simple zip file, which include a metadata (xml) file which describes the contents of the package, and folders containing binaries, source, resources etc. Packages will not contain any scripts (ie to build during install) for security reasons (I don't want to be running random scripts). We will need to provide a way to compile during install (using a simple dsl to describe what needs to be done), this still needs a lot of thought (and very much involves dependencies).&lt;/p&gt;

&lt;h3&gt;Library/Search Paths&lt;/h3&gt;

&lt;p&gt;Say goodbye to the IDE's Library path. It was great back in 1995, when we had a few third party libraries and a few projects and we just upgraded the projects to deal with library versioning (just get on the latest). It's simply incompatible with the notion of using multiple versions of the same libraries these days.&lt;/p&gt;

&lt;p&gt;I rarely change major versions of a library during the lifespan of a major release of my products, I might however take minor updates for bugfixes or performance improvements. The way to deal with this is simply to use the Project Search path. Project A can use version 1 of a library, Project 2 can use version 9, all quite safely (design time components do complicate this).&lt;/p&gt;

&lt;p&gt;Where a project targets multiple platforms, installing a package should install for all platforms it supports, but it should be possible for the user to specify which platforms they need the package installed for.&lt;/p&gt;

&lt;h3&gt;Design time Component Installation&lt;/h3&gt;

&lt;p&gt;The Rad Studio IDE only allows one version of a design time package to be installed at a time. So when switching projects, which might use different versions of a component library, we would need a system that is aware of component versions, and can uninstall/install components on the fly, as projects are loaded.&lt;/p&gt;

&lt;p&gt;I suspect this will be one of the biggest project hurdles to overcome, it will requires someone with very good open tools api knowledge (ie, not me!).&lt;/p&gt;

&lt;h3&gt;Dependencies&lt;/h3&gt;

&lt;p&gt;Libraries that depend on other libraries will need to specify those dependencies in a metadata file, such that they can resolved during installation. As I mentioned above, binary compatibility issues make dependency resolution somewhat more complicated, but not insurmountable. The resolution algorithm will need to take into account compiler version and platform. The algorithm will also need to handle when a package is compiled from source, for example, binary only packages should not be allowed to depend on source only packages (to ensure compatibility). If we end up with install time package compilation, then some serious work will be needed on the dependency tree algorithm to work our what else needs to be done during install (ie, do any dependencies need to be recompiled?).&lt;/p&gt;

&lt;p&gt;This is certainly more complicated than other platforms, and a significant amount of work to get right (ps, if you think it isn't, you haven't considered all the angles!)&lt;/p&gt;

&lt;h2&gt;General Considerations&lt;/h2&gt;

&lt;h3&gt;Package Install/Restore&lt;/h3&gt;

&lt;p&gt;The user should be able to choose from a list packages to install. When installing the package, this would be recorded either in the dproj, or a separate file alongside the drproj. The install process will update the project search paths accordingly. Package meta data would control what gets added to the search paths, my preference would be for 1 folder per package, as that would keep the search path shorter which improves compile times.&lt;/p&gt;

&lt;p&gt;When a project is loaded, the dproj (or packages config file) would be checked, and any missing packages restored automatically. This should also handle the situation where a project is loaded in a different IDE version.&lt;/p&gt;

&lt;h3&gt;Security&lt;/h3&gt;

&lt;p&gt;We should allow for signing of packages, such that the signatures can be verified by the client(s). Clients should be able to chose whether to only allow signed packages, or allow signed and unsigned, and what to do when signature verification fails. This will allow users certainty in the authenticity and integrity of the package (ie where it comes from and whether it's been modified/tampered with).&lt;/p&gt;

&lt;h2&gt;Clients&lt;/h2&gt;

&lt;p&gt;It is envisaged that will be at least 2 clients, a command line tool, and a Rad Studio IDE plugin. Clients will download packages, add those packages to project/config search paths. A local package cache will help with performance, avoiding repetitive package downloads and also reduce disk space demands. The clients will also detect available updates to packages, and package dependency conflicts.&lt;/p&gt;

&lt;h3&gt;Command line Client&lt;/h3&gt;

&lt;p&gt;The command like tool will be similar to nuget or npm, which provide the ability to create packages, install or restore missing packages, update packages etc. The tool should allow the specification of compiler versions and platforms, as this is not possible to detect from the dproj alone. This is where the project is currently focused (along with the core package handling functionality).&lt;/p&gt;

&lt;h3&gt;RAD Studio IDE Client&lt;/h3&gt;

&lt;p&gt;An IDE plugin client will provide the ability to search for, install, restore, update or remove packages, in a similar manner to the Nuget Visual Studio IDE support (hopefully faster!). This plugin will share the core code with the the command line client (ie, it will not call out to the command line tool). I have not done any work on this yet (help wanted).&lt;/p&gt;

&lt;h2&gt;Delphi/Rad Studio Version Support&lt;/h2&gt;

&lt;p&gt;Undecided at the moment. I'm developing with XE7, but it's possible the code will compile with earlier versions, or be made to compile with minor changes.&lt;/p&gt;

&lt;h2&gt;Summary&lt;/h2&gt;

&lt;p&gt;Simply put, I want/need a package manager for Delphi, one that works as well as nuget, npm, yarn etc. I'm still fleshing out how this might all work, and I'd love some feedback, suggestions, ideas etc. I'd like to get some people with the right skills 'signed up' to help, particularly people with open tools api expertise.&lt;/p&gt;

&lt;h2&gt;Get Involved!&lt;/h2&gt;

&lt;p&gt;I have set up a home for the project on GitHub - &lt;a href="https://github.com/DelphiPackageManager/PackageManagerRFC"&gt;The Delphi Package Manager Project - RFC&lt;/a&gt;. We'll use issues for discussion, and the wiki to document the specifications as we develop them. I have created a few issues with things that need some dicusssion. I hope to publish the work I have already done on this in the next few days (needs tidying up).&lt;/p&gt;
</description><guid isPermaLink="false">777</guid></item></channel></rss>