VSoft Technologies Blogs

rss

VSoft Technologies Blogs - posts about our products and software development.


Nancyfx is a Lightweight, low-ceremony, framework for building HTTP based services on .Net and Mono. It's open source and available on github. 

Nancy supports Forms Authentication, Basic Authentication and Stateless Authentication "out of the box", and it's simple to configure. In my application, I wanted to be able to handle mixed Forms and NTLM Authentication, which is something nancyfx  doesn't support. We have done this before with asp.net on IIS, and it was not a simple task, involving a child site with windows authentication enabled while the main site had forms (IIS doesn't allow both at the same time) and all sorts of redirection. It was painful to develop, and it's painful to install and maintain. 

Fortunately with Nancy and Owin, it's a lot simpler. Using Microsoft's implementation of the Owin spec, and Nancy's Owin support, it's actually quite easy, without the need for child websites and redirection etc. 

I'm not going to explain how to use Nancy or Owin here, just the part needed to hook up NTLM support. In my application, NTLM authentication is invoked by a button on the login page ("Login using my windows account") which causes a specific login url to be hit. We're using Owin for hosting rather than IIS and Owin enables us to get access to the HttpListener, so we can control the authentication scheme for each url. We do this by adding an AuthenticationSchemeSelectorDelegate.

internal class Startup
{
    public void Configuration(IAppBuilder app)
    {
        var listener = (HttpListener)app.Properties["System.Net.HttpListener"];
       //add a delegate to select the auth scheme based on the url 
        listener.AuthenticationSchemeSelectorDelegate = request =>
        {
            //the caller requests we try windows auth by hitting a specific url
            return request.RawUrl.Contains("loginwindows") ? AuthenticationSchemes.IntegratedWindowsAuthentication : AuthenticationSchemes.Anonymous;
        }
        app.UseNancy();
    }
}

What this achieves is to invoke the NTLM negotiation if the "loginwindows" url is hit on our nancy application. If the negotiation is successful (ie the browser supports NTLM and is able to identify the user),  then the Owin environment will have the details of the user, and this is how we get those details out of Owin (in our bootstrapper class).

protected override void ApplicationStartup(TinyIoCContainer container, IPipelines pipelines)
{
  pipelines.BeforeRequest.AddItemToStartOfPipeline((ctx) =>
  {
      if (ctx.Request.Path.Contains("loginwindows"))
      {
          var env = ((IDictionary<string,>)ctx.Items[Nancy.Owin.NancyOwinHost.RequestEnvironmentKey]);
          var user = (IPrincipal)env["server.User"];
          if (user != null && user.Identity.IsAuthenticated)
          {
              //remove the cookie if someone tried sending one in a request!
              if (ctx.Request.Cookies.ContainsKey("IntegratedWindowsAuthentication"))
                  ctx.Request.Cookies.Remove("IntegratedWindowsAuthentication");
              //Add the user as a cooking on the request object, so that Nancy can see it.
              ctx.Request.Cookies.Add("IntegratedWindowsAuthentication", user.Identity.Name);
          }
      }
      return null;//ensures normal processing continues. 
  });
}

Note we are adding the user in a cookie on the nancy Request object, which might seem a strange thing to do, but it was the only way I could find to add something to the request that can be accessed inside a nancy module, because everything else on the request object is read only. We don't send this cookie back to the user. So with that done, all that remains is the use that user in our login module

 Post["/loginwindows"] = parameters => 
    {
        string domainUser = "";
        if (this.Request.Cookies.TryGetValue("IntegratedWindowsAuthentication",out domainUser))
        {
            //Now we can check if the user is allowed access to the application and if so, add 
            //our forms auth cookie to the response.             
            ...
        }
    }

Of course, this will probably only work on Windows, not sure what the current status is for System.Net.HttpListener is on Mono. This code was tested with Nancyfx 1.2 from nuget. 

FinalBuilder 8 Beta

It's almost 5 years since FinalBuilder 7 was released. Since it's release we have shipped 44 official updates, nearly every update including new features or improvements. This program of continuous improvement has worked well, with customers not having to wait for major new versions to arrive to get support for new versions of Visual Studio or Delphi etc, but it has limited our ability to make major changes. So it's time for a new major version of FinalBuilder. 

What's new in FinalBuilder 8

IDE Themes

The IDE has two new themes, Dark and Light (yes, imaginatively named!). The IDE defaults to Dark on first run, however you can change the theme in the options quite easily. The themes are still a work in progress, we are waiting on an update from a third party control vendor to resolve some issues.

IDE Light theme IDE Light theme

 

Debugger

One of the most asked for features now available in FinalBuilder 8, stepping into included projects. In FinalBuilder 7 and earlier, you could only step over included projects, and wait for them to return. In FinalBuilder 8, you can step into the included project, if it is not already opened the IDE will open the project and switch to it automatically. To make this possible, there are now "Step Into" and "Step Over" functions. The Step into/over now also applies to targets (see below).

Debugger breakpoints now have conditions :

IDE Light theme

Actionlists renamed to Targets

ActionLists have been renamed to Targets. Targets can now also define dependencies, so you can for example define Clean, Build, Test, and have Test depend on Build. If you execute the Test target, and Build has not already been executed, it will be executed first before Test. Targets can be specified on the command line.

IDE Light theme


In FinalBuilder 7 and earlier, projects had a Main and an OnFailure (global error handler) actionlist. In FinalBuilder 8, projects just have a Default Target. Older projects will be imported such that the Main and OnFailure Targets are called from the Default Target inside a try/catch block.

Run Target Action

You can now return values from Targets (ie out parameters) .

IDE Light theme

New Help System

The help has moved online in the form of a wiki. This enables us to do inline help updates without needing to ship new builds. The new help is still being worked on, lots of screenshots are missing etc.. 

Non Visible Changes

Stepping Engine

The stepping engine was rewritten to enable stepping into included projects, and to enable target dependencies. This, work, together with the new variables architecture is where the bulk of effort/time was spent in the FinalBuilder 8 development cycle.

Variables Architecture

The variables architecture and the expression evaluator were rewritten to resolve several corner case issues that we were not able to resolve in FinalBuilder 7. The expression evaulator has a new parser that will allow us to more easily extend the syntax in the future. The User variable namespace was removed, it caused too many problems with projects not running under other users, not running on the build server etc. Use Project variables instead.

Core Messaging

Changes to the messaging has allowed us to improve the performance of the stepping engine and logging, with much less thread switching. This also improved the IDE performance.

CLR Hosting

The minimum CLR version is now .NET 4.0 (ie FinalBuilder requires .net 4.0 to be installed).

Code Changes

In addition to the architectural changes, we also spent a lot of time refactoring the code, running static analysis tools over the source, looking for memory leaks, potential bugs etc. One of the results of this is reduced memory usage during a build compared to FB7. The FB8 IDE does use slightly more memory than the FB7 IDE at startup (mostly due to the heavy use of delphi generics), however the runtime memory usage is much lower.A large  part of the refactoring involved unit testing (we created a new unit test framework to suite our needs!) and creating a suite of integration tests. 

FBCmd

The command line parameters have changed to be more consistent and easier to specify. You can also specify one or more targets to execute (when not specified, the default target is executed).

New Project File Formats

FinalBuilder has used an xml file format since version 1, however a common complaint over the years, has been that it is difficult to diff file versions. FinalBuilder 8 has tackled this in two ways.

A new DSL style project file format (.fbp8) is now the default format, it is very easy to diff.

project
begin
    projectid = {04710B72-066E-46E7-84C7-C04A0D8BFE18}
    target
    begin
        name = Default
        targetid = {E6DE94D6-5484-45E9-965A-DB69885AA5E2}
        rootaction
        begin
            action.group
            begin
                id = {D860420B-DE46-4806-959F-8A92A0C86429}
            end
        end
    end
end

A new xml format (.fbx8), much less verbose than the old format.

<?xml version="1.0" encoding="UTF-8"?>
<finalbuilder>
    <project>
        <projectid>{6A717C24-D00F-4983-9FD0-148B2C609634}</projectid>
        <target>
            <name>Default</name>
            <targetid>{E6DE94D6-5484-45E9-965A-DB69885AA5E2}</targetid>
            <rootaction>
                <action.group>
                    <id>{D860420B-DE46-4806-959F-8A92A0C86429}</id>
                </action.group>
            </rootaction>
        </target>
    </project>
</finalbuilder>

Compressed project files (.fbz8) use the dsl format internally (compressed projects are just a zip file with a project.fbp8 inside it).

The default project file encoding is now UTF-8, which is more version control friendly (some version control systems treat utf-16 as binaries).

New Actions

There are no new actions at the moment, although several are in development, they will be added to the beta builds as they are completed. 

How do I get the Beta?

Links to the beta downloads will be published to the FinalBuilder Downloads page. 

What if I find a bug?

We have created a Beta forum on our forums, or you can email support (please added Beta to the subject). When reporting an issue, be sure to include the beta build number and details about your environment. Please test with the latest beta build before reporting bugs. 

We are particularly keen for people to load up their existing projects from older (ie 7 or earlier) versions of FinalBuilder, save them in FB8 format, and load them again and confirm that everything loaded ok. 

When will it be released?

When it's ready ;)

Update : Still the same situation with XE8. 

The Windows Path environment variable has a limit of 1023 * 2,048 characters, a stupidly short limit in this day and age, and when this limit is exceeded the path is truncated. Why this limit still exists on windows I have no idea.. for that matter why it ever existed... anyway, we're stuck with it (along with it's best buddy, MAX_PATH). 


Each version of Delphi adds over 200 characters to your system path. Worst still, they add those 200+ characters to the front of the path, not the end. What happens, is that eventually, important entries get truncated off end of the path, and strange things happen. You will find programs will not run, the task bar displays the wrong icons for programs, even getting to the control panel can be problematic. 

If you look at the entries that XE7 added to the start of your path you will see something like this :

C:\Program Files (x86)\Embarcadero\Studio\15.0\bin;
C:\Program Files (x86)\Embarcadero\Studio\15.0\bin64;
C:\Users\Public\Documents\Embarcadero\Studio\15.0\Bpl;
C:\Users\Public\Documents\Embarcadero\Studio\15.0\Bpl\Win64;

Fortunately this can be shortened by the use of junction points. Sadly, this will polute your C: drive with new folders but it's better than the alternative.

The trick is to create links for the most common paths, so on mine I created these
For XE5 and earlier :
mklink /j RS C:\Program Files (x86)\Embarcadero\RAD Studio
mklink /j rspub C:\Users\Public\Documents\RAD Studio

XE6 and above 

mklink /j Studio C:\Program Files (x86)\Embarcadero\Studio
mklink /j spub C:\Users\Public\Documents\Embarcadero\Studio

Once you have those junction points, you can then edit your path and replace the long paths, for example (for XE7) :

C:\Program Files (x86)\Embarcadero\Studio\15.0\bin -> C:\Studio\15.0\bin
C:\Program Files (x86)\Embarcadero\Studio\15.0\bin64 -> C:\Studio\15.0\bin64
C:\Users\Public\Documents\Embarcadero\Studio\15.0\Bpl -> C:\spub\15.0\Bpl
C:\Users\Public\Documents\Embarcadero\Studio\15.0\Bpl\Win64 - > c:\spub\15.0\Bpl\Win64

So for XE7, that cuts it down from 218 to 80 characters, if like me you also have multiple versions of Rad Studio installed, this can be a big saving.

As for Rad Studio, it's extremely rude to add things to the start of the path, the truncation it causes can ruin a machine.. I wasted several hours again today after installing XE7. Embarcadero were told about this issue many times over several releases.. according to the doco, XE7 will popup a message about this.. I didn't see it so not sure when that is supposed to appear, but in any event, if your installer or progam needs to add something to the path environment variable, PLEASE ADD IT TO THE END!! and save us all a bunch of time. 

* Correction, max path length is 2048 - very difficult to find a difinitive source of this information on the microsoft site - the max size of an env variable is 2048, however I have seen the path variable truncated at 1024 many times.

Continua 1.5 released



Continua Version 1.5 is now available for download

Today marks a milestone in Continua CI as we release version 1.5 of the product. Its been many months in the making, we hope you enjoy the update as much as we enjoyed making it.

There are many features that we think you'll benefit from by updating to v1.5, some of these include:

Reworked UI:

  • Now using bootstrap framework for styling
  • Redesigned dashboards that show more information including graphs.
  • Added stages information to the Project tile and list views
  • Disabled configurations are now displayed as faded

Cloning:

  • Can now clone whole projects and clone configurations between projects.

Stage Conditions:

  • Auto Promote conditions - stages can now use conditions to control whether to auto-promote to the next stage.
  • Skip conditions - you can now provide conditions for skipping stages or disable a stage completely.

New Actions:


Repository Tags: (Git, Mercurial and Subversion repositories only)

  • Continua CI can now detect and list repository tags.
  • Tags are now displayed in changeset tabs on configuration and build views.
  • Repository trigger can now be set to trigger on tag changes (new tags, edits and deletions) changes).
  • You can now run a build on a tagged changeset.

Build Event Handlers:


and many more changes including:

  • Styling changes for improved handling on small screen sizes
  • Report ordering: you can choose which one is displayed first on the build view.
  • New expression functions: Utils.NewGuid() and Utils.RandomNumber() can be used for generation of temporary paths for example
  • Additional LatestChangeset object within the repository object with Branch, BranchName, Comment, CommitterUserName, CommitterFullName, Created, FileCount, Id and RepositoryUsername properties to use in expressions
  • Continua now supports DUnitX enhanced Command Line Options

Updating

Updating to this new release is the same regardless if you are using v1.0.X or a recent build from the beta or release candidate. Simply download the installer and run it, the setup will guide you through the install process. As usual we are available on support@finalbuilder.com if you run into any troubles.

For this release you will need to update both the server and agents.

A word of thanks

The team wishes to thank everyone who has participated in the beta and release candidate stages for this release. Your positive feedback has been invaluable in shaping the features and functionality of the product. Thank you for your continued support.


Command line parsing

Pretty much every delphi console application I have ever written or worked on had command line options, and every one of the projects tried different ways for defining and parsing the supplied options. Whilst working on DUnitX recently, I needed to add some command line options, and wanted to find a nice way to add them and make it easy to add more in the future. The result is VSoft.CommandLineParser (copies of which are included with the latest DUnitX).

Defining Options

One of the things I really wanted, was to have the parsing totally decoupled from definition and the storage of the options values. Options are defined by registering them with the TOptionsRegistry, via TOptionsRegistry.RegisterOption<T> - whilst it makes use of generics, only certain types can be used, the types are checked at runtime, as generic constraints are not flexible enough to specify which types we allow at compile time. Valid types are string, integer, boolean, enums & sets and floating point numbers.

Calling RegisterOption will return a definition object which implements IOptionDefinition. This definition object allows you to set various settings (such as Required). When registering the option, you specify the long option name, the short option name, help text (will be used when showing the usage) and a TProc<T> anonymous method that will take the parsed value as a parameter.

procedure ConfigureOptions;
var
  option : IOptionDefintion;
begin
  option := TOptionsRegistry.RegisterOption<string>('inputfile','i','The file to be processed',
    procedure(value : string)
    begin
        TSampleOptions.InputFile := value;
    end);
  option.Required := true;

  option := TOptionsRegistry.RegisterOption<string>('outputfile','o','The processed output file',
    procedure(value : string)
    begin
        TSampleOptions.OutputFile := value;
    end);
  option.Required := true;

  option := TOptionsRegistry.RegisterOption<boolean>('mangle','m','Mangle the file!',
    procedure(value : boolean)
    begin
        TSampleOptions.MangleFile := value;
    end);
  option.HasValue := False;

  option := TOptionsRegistry.RegisterOption<boolean>('options','','Options file',nil);
  option.IsOptionFile := true;
end;

For options that are boolean in nature, ie they have do not value part, the value passed to the anonymous method will be true if the option was specified, otherwise the anonymous method will not be called. The 'mangle' option in the above example shows this scenario.

You can also specify that an option is a File, by setting the IsOptionFile property on the option definition. This tells the parser the value will be a file, which contains other options to be parsed (in the same format as the command line). This is useful for working around windows command line length limitations.

Currently the parser will accept
-option:value
--option:value
/option:value

Note the : delimiter between the option and the value.

Unnamed parameters are registered via the TOptionsRegistry.RegisterUnNamedOption<T> method. Unlike named options, unnamed options are positional, but only when more than one is registered, as they will be passed to the anonymous methods in the order they are registered.

Parsing the options.

Parsing the options is as simple as calling TOptionsRegistry.Parse, which returns a ICommandLineParseResult object. Check the HasErrors property to see if the options were valid, the ErrorText property has the parser error messages.

Printing Usage

If the parser reports errors, then typically you would show the user what the valid options are and exit the application, e.g:

    parseresult := TOptionsRegistry.Parse;
    if parseresult.HasErrors then
    begin
      Writeln(parseresult.ErrorText);
      Writeln('Usage :');
      TOptionsRegistry.PrintUsage(
        procedure(value : string)
        begin
          Writeln(value);
        end);
    end
    else
        ..start normal execution here

The TOptionsRegistry.PrintUsage makes it easy to print the usage to the command line.

When I started working on this library, I found some really complex libraries (mostly .net) out there with a lot of options, but I decided to keep mine as simple as possible and only cover off the scenarios I need right now. So it's entirely possible this doesn't do everything people might need, but it's pretty easy to extend. The VSoft.CommandLineParser library (just three units) is open source and available on Github, with a sample application and unit tests (DUnitX) included.