Software Developer, Technology Enthusiast, Retro and Husband and Dad based in Melbourne.

Adam Craig Johnston

Delphi and .NET Interop with JVCL

There are different methods for Delphi to communicate with the .NET Framework:

  • Commercial projects e.g. Remobjects Hydra, Atozed CrossTalk and Managed VCL etc.
  • Importing .NET Assembly using the Import Component Wizard.
  • Or Open Source method using JVCL.

Why choose JVCL over the commercial projects and the Import Component Wizard which is part of Delphi?

  • Open Source e.g. free as in beer.
  • Independent of regasm.exe which registers Class Libraries into the Global Assemble Cache (GAC)

How does JclDotNet work?

JVCL provides communication to the .NET Framework using the JclDotNet unit, by providing variant based
late bound automation to the .NET class library.

This post will provide two examples by stepping through each part, which should provide a basic grounding on how the 
JVCL JclDotNet unit communicates with .NET Framework.

For these examples your Delphi must have JVCL 3.45 or higher installed and for  the C# Class Library .NET 4.5 Framework
 (Visual Studio 2012).

Example 1

This example demonstrates a basic adding of two numbers together, by calling the C# class library Example1ClassLibrary.DLL

Delphi Example
  • To start the TJclClrHost class must initialize a .NET Framework – Common Language Runtime (CLR) and start the host:
Host := TJclClrHost.Create('v4.0.30319');
Host.Start();
  • NOTE: By default if you leave the ClrVer variable blank, it defaults to v2.0.50727.
Host := TJclClrHost.Create;
  • For this example we will be using CLR v4.0.30319 which supports either .NET 4.5 or .NET 4 Framework.
  • C# Class Library must now be initialize and Obj: OleVariant for the access to method:
Obj := Host.DefaultAppDomain
.CreateInstance('Example1ClassLibrary' {.NET Assemble Name},

'Example1ClassLibrary.Example1' {Namespace.Classname})

.UnWrap();
  • First part is the name of .NET Assemble File ‘Example1ClassLibrary.dll’.
  • ‘Example1ClassLibrary.Example1‘ next part is the namespace and the classname
  • Accessing this method from the C# Class Library as simple has keeping the name and the parameters the same as the class library:
Result := Obj.AddFunction(aXValue, aYValue);
  • Release the CLR host just stop and free the TJclClrHost class:
Host.Stop();
Host.Free;
Full Function
function TfrmMain.AddFunction(aXValue: Integer; aYValue:Integer): Integer;
var
  Host: TJclClrHost;
  Obj: OleVariant;
begin
  try
    Host := TJclClrHost.Create('v4.0.30319');
    Host.Start();

    Obj := Host.DefaultAppDomain
        .CreateInstance('Example1ClassLibrary',
        'Example1ClassLibrary.Example1')
        .UnWrap();

     Result := Obj.AddFunction(aXValue, aYValue);

    Host.Stop();
    Host.Free;
  Except
     on E : Exception do
     begin
       ShowMessage('Exception class name = '+E.ClassName + ' ' + 'Exception message = '+E.Message);
     end;
  end;
end;

C# Class Library

Some basic setting up of example 1 Class Library allowing Delphi work with Interop Services:

  • Include in your namespace for the Interop Services
using System.Runtime.InteropServices;
  • To expose the class to COM access to Delphi
[ComVisible(true)]
public class Example1
  • All functions must be public
public int AddFunction(int aXValue, int aYValue)
{
return aXValue + aYValue;
}
Class Library
namespace Example1ClassLibrary
{
    [ComVisible(true)]
    public class Example1
    {
        public int AddFunction(int aXValue, int aYValue)
        {
            return aXValue + aYValue;
        }
    }
}

Example 2

In this example we take the basic adding of two numbers together and expand out how Delphi can access the Example2ClassLibrary.DLL using the mscorlib_TLB import library:

Delphi Example
uses
mscorlib_TLB, Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs,? StdCtrls, JclDotNet;
  • NOTE: mscorlib_TLB should be the first unit.
  • Initializing the host to .NET Framework in the formcreate event:
procedure TfrmMain.FormCreate(Sender: TObject);
begin
   FClrHost := TJclClrHost.Create('v4.0.30319');

   FClrHost.Start;
end;
  • Setup the access to the Class Library path and application:
Fads.ApplicationBase := '..\Example2\Debug\Win32\';
Fad := FClrHost.CreateAppDomain('myNET', Fads);
  • NOTE: CreateAppDomain(‘myNET’ should be a different name if two or more a being called.
  • The C# Class Library must now be initialize and Obj: OleVariant for the access to the method:
obj := (Fad as _AppDomain).CreateInstanceFrom('Example2ClassLibrary.dll',
     'Example2ClassLibrary.Example2');
ov := obj.Unwrap;result := ov.AddFunction(aXValue, aYValue);
  • To release the CLR host just stop and free has been setup on the FormDestory event:
procedure TfrmMain.FormDestroy(Sender: TObject);
begin
  FClrHost.Stop();
  FClrHost.Free;
end;
Full Function
function TfrmMain.AddFunction(aXValue: Integer; aYValue:Integer): Integer;
var
  Fads: TJclClrAppDomainSetup;
  Fad: TJclClrAppDomain;
  Ov: OleVariant;
  obj: _ObjectHandle;
begin
  try
    Fads := FClrhost.CreateDomainSetup;

    Fads.ApplicationBase := '..\Example2\Debug\Win32\';
    Fad := FClrHost.CreateAppDomain('myNET', Fads);
    obj := (Fad as _AppDomain).CreateInstanceFrom('Example2ClassLibrary.dll',
         'Example2ClassLibrary.Example2');
    ov := obj.Unwrap;
    result := ov.AddFunction(aXValue, aYValue);
  except
    on E : Exception do
     begin
       ShowMessage('Exception class name = '+E.ClassName +
          ' ' + 'Exception message = '+E.Message);     end;
  end;
end;

Download Examples

https://github.com/acj1971/DelphiDotNETInteropJVCLExamples

Links

JVCL
http://jvcl.delphi-jedi.org/

.NET 4.5 Framework
http://www.microsoft.com/en-au/download/details.aspx?id=30653

Common Language Runtime (CLR)
http://msdn.microsoft.com/en-us/library/8bs2ecf4.aspx

Remobjects Hydra
http://www.remobjects.com/hydra/

Atozed CrossTalk
http://www.atozed.com/CrossTalk/index.en.aspx

Managed VCL
http://www.managed-vcl.com/

Import Component Wizard
http://docwiki.embarcadero.com/RADStudio/XE3/en/Import_Component_Wizard

Encrypting ASP.NET appSettings Web.Config File

It is recommended to encrypt the AppSettings key in the ASP.NET Web.Config file for security reason. The simplest method is using aspnet_regiis.exe command-line utility; this command-line utility is available from .NET 2 Framework or higher, for this blog I will be using .NET Framework 4.0.

aspnet_regiis.exe

The location of aspnet_regiis.exe command-line utility is:
C:\Windows\Microsoft.NET\Framework\v4.0.30319\aspnet_regiis.exe

Encryption

To encrypt the appSettings key at the command-line:

C:\Windows\Microsoft.NET\Framework\v4.0.30319\aspnet_regiis.exe ?pef appSettings “c:\project\directory” -prov “DataProtectionConfigurationProvider”

  1. Specify the full path to aspnet_regiis.exe command-line utility
  2. Use -pef appSettings to set the appSettings key
  3. Use -prov “DataProtectionConfigurationProvider”

.NET Framework 4.0 has two built-in providers for encrypting the appSettings key in ASP.NET Web.Config file:

  • DataProtectionConfigurationProvider Windows data protection API (DPAPI)
  • RSAProtectedConfigurationProvider RSA encryption

The simplest provider to use is the DataProtectionConfigurationProvider, there are no RSA keys to be created and setup, with the DataProtectionConfigurationProvider it’s server -specific.

When copying the Web.Config file from your development environment, encrypt the appSettings key on the server using DataProtectionConfigurationProvider provider otherwise the appSettings key will not be decrypted correctly.

The RSAProtectedConfigurationProvider RSA encryption, the RSA keys can be copied from development environment to server without change.

Decryption

To decrypt the appSettings key at the command-line:

C:\Windows\Microsoft.NET\Framework\v4.0.30319\aspnet_regiis.exe -pdf appSettings “c:\project\directory ”

  1. Specify the full path to aspnet_regiis.exe command-line utility
  2. Use ?pdf appSettings to set the appSettings key

C# Example reading appSettings Key

With this example the appSettings key is read and decrypted automatically:

using System.Configuration;
using System.Web.Configuration;

private void EncryptAppSettings()        {
           Configuration objConfig = WebConfigurationManager.OpenWebConfiguration(
                  Request.ApplicationPath);
           AppSettingsSection objAppsettings =
            (AppSettingsSection)objConfig.GetSection("appSettings");
          if (!objAppsettings.SectionInformation.IsProtected)
            {
            objAppsettings.SectionInformation.ProtectSection
                            ("DataProtectionConfigurationProvider");
                  objAppsettings.SectionInformation.ForceSave = true;
                 objConfig.Save(ConfigurationSaveMode.Modified);
            }
        }

Links

ASP.NET IIS Registration Tool (Aspnet_regiis.exe)
http://msdn.microsoft.com/en-us/library/k6h9cz8h%28v=vs.100%29.aspx

How To: Encrypt Configuration Sections in ASP.NET 2.0 Using DPAPI
http://msdn.microsoft.com/en-us/library/ff647398.aspx

How To: Encrypt Configuration Sections in ASP.NET 2.0 Using RSA
http://msdn.microsoft.com/en-us/library/ms998283.aspx

DpapiProtectedConfigurationProvider Class
http://msdn.microsoft.com/en-us/library/system.configuration.dpapiprotectedconfigurationprovider%28v=vs.100%29.aspx

RsaProtectedConfigurationProvider Class
http://msdn.microsoft.com/en-us/library/system.configuration.rsaprotectedconfigurationprovider%28v=vs.100%29.aspx

Using WordPress on AWS EC2 Free Tier

Here is a guide on how to setup WordPress on Amazon EC2 Free Tier

Setup

  1. Sign up for a AWS Account at http://aws.amazon.com/

  2. Sign up for a Amazon EC2 at http://aws.amazon.com/ec2

  3. Sign into the AWS Console

  4. Choose a Region before launching your new EC2 instance.

     

  5. Create EC2 Linux Micro Instance for WordPress:
  6. To start a new EC2 instance click on the Launch Instance button.

  7. In the “Request Instances Wizard” tab to the Community AMI’s then filter using “wordpress” then choose the AMI:

    bitnami-wordpress-3.1-0-linux-ubuntu-10.04-ebs (ami-30f18f62)

  8. For your Free instance, choose the number of instances: 1, Availability Zone: No Preference and Instance Type: Micro (t1 micro, 613MB).

  9. Shutdown Behavior option should be stop, and all other options Use Default.

  10. Add in a tag key = Name and value = Webserver.

  11. Create a new Key Par call it the name of the website then create and save this file somewhere on your local machine that can be grabbed latter. E.g xyz.pem

  12. Adjust Security Groups,

    Add rules for SSH, HTTP, HTTPS but leave the source as 0.0.0.0/0

  13. Now Lunch the instance

  14. Assign Elastic IP then Associate Address with your EC2 Instance
  15. Click on Instances within the EC2 console to find the Public DNS.

  16. Install Open SSH on Windows
  17. Set pem file to Read by owner

     

    chmod 400 xyz.pem

  18. SSH in to the instance

    ssh -i xyz.pem bitnami@ec2-<public DNS>.ap-southeast-1.compute.amazonaws.com

  19. Move WordPress to run at the root of the apache web server by editing httpd.conf file using vi

     

    sudo vi /opt/bitnami/apache2/conf/httpd.conf

    DocumentRoot “/opt/bitnami/apache2/htdocs”

     

    To

     

    DocumentRoot “/opt/bitnami/apps/wordpress/htdocs”

    <Directory />

    Options Indexes MultiViews +FollowSymLinks

    AllowOverride All

    Order allow,deny

    Allow from all

    </Directory>

     

    <Directory “/opt/bitnami/apache2/htdocs”>

     

    To

     

    <Directory “/opt/bitnami/apps/wordpress/htdocs”>

     

    Comment out:

     

    #Include “/opt/bitnami/apps/wordpress/conf/wordpress.conf”

     

  20. Create an .htaccess file for WordPress

     

    This also enables you to have pretty permalinks like myblog.com/tour

     

    Add .htaccess file to WordPress dir

    in /opt/bitnami/apps/wordpress/htdocs/.htaccess

     

    # BEGIN WordPress

    <IfModule mod_rewrite.c>

    RewriteEngine On

    RewriteBase /

    RewriteCond %{REQUEST_URI} !=/server-status

    RewriteCond %{REQUEST_FILENAME} !-f

    RewriteCond %{REQUEST_FILENAME} !-d

    RewriteRule . /index.php [L]

    </IfModule>

    # END WordPress

     

  21. Configure WordPress to know its own DNS entry

     

    sudo vi /opt/bitnami/apps/wordpress/htdocs/wp-config.php

     

    define(‘WP_HOME’, ‘http://www.ringio.com’);

    define(‘WP_SITEURL’, ‘http://www.ringio.com’);

     

  22. Install Filezila

     

    Public DNS

    SSH Username: bitnami

    Password: <Blank>

     

  23. delete the /opt/bitnami/updateip file. Otherwise, restarting the instance, Bitnami resets the wp_options values to the Public DNS server name.

     

    sudo rm /opt/bitnami/updateip

     

  24. Install EMS MySQL Manager

     

    How to Connect to BitNami MySQL Remotely

    http://wiki.bitnami.org/cloud/how_to_connect_to_your_amazon_instance#How_to_connect_to_the_BitNami_MySQL_remotely.3f

     

     

  25. Run this SQL script to set the Pubic IP Address with WordPress

     

    update wp_options set option_value = ‘http://www.agileweboperations.com’ where option_name in (‘siteurl’, ‘home’);

     

  26. Configure WordPress with the Pubic IP Address

     

    sudo vi /opt/bitnami/apps/wordpress/htdocs/wp-config.php

     

    define(‘WP_HOME’, ‘http://www.ringio.com’);

    define(‘WP_SITEURL’, ‘http://www.ringio.com’);

     

  27. Reboot the instance
  28. In your Browser type the public ip and see if WordPress is running correctly at Root Directory
  29. Login into Woresspress using default bitnami username

    Username: user

    Password: bitnami

  30. Add a new use into WordPress with Role of Administrator
  31. Then remove default bitnami username from WordPress by login in as your new username
  32. Make a DNS A record for the domain host provider, and use the elastic IP.

Migration

  1. Both wordpress on your old site and on AWS are the same due to database compatible issues
  2. Copy your \wp-content\upload from your old site locally to reload on AWS

    sudo chmod 755 /opt/bitnami/apps/wordpress/htdocs/wp-content/

    Install and download all plugins to your AWS Worspress instance

  3. Download or install your old theme and plugins
  4. Export your Old WordPress database using MyPHPAdmin
  5. Run the Export SQL Script on the AWS WordPress Instance using your Remote SQL Manager
  6. The rerun the SQL script to set the Pubic IP Address with WordPress

    update wp_options set option_value = ‘http://www.agileweboperations.com’ where option_name in (‘siteurl’, ‘home’);

To Finish

  1. When your domain has delegated run this script again with your domain

    update wp_options set option_value = ‘http://www.website.com’ where option_name in (‘siteurl’, ‘home’);

     

  2. Configure WordPress with the Pubic IP Address

     

    sudo vi /opt/bitnami/apps/wordpress/htdocs/wp-config.php

     

    define(‘WP_HOME’, ‘http://www.website.com’);

    define(‘WP_SITEURL’, ‘http://www.website.com’);

 

Links

Amazon Web Services
http://aws.amazon.com/

AWS Management Console
http://aws.amazon.com/console/

Bitnami Wordpres Stack
http://bitnami.org/stack/wordpress

OpenSSH
http://www.openssh.com/
http://sshwindows.webheat.co.uk/

Filezilla
http://filezilla-project.org/

How to Connect to BitNami MySQL Remotely
http://wiki.bitnami.org/cloud/how_to_connect_to_your_amazon_instance#How_to_connect_to_the_BitNami_MySQL_remotely.3f

EMS MySQL Manager
http://www.sqlmanager.net/products/mysql/manager

 

 

Updates for Visual Studio 2010 Service Pack 1 and TFS 2010 Service Pack 1

Updates for Visual Studio 2010 Service Pack 1 and TFS 2010 Service Pack 1 are ready.

Visual Studio 2010 Service Pack 1
http://support.microsoft.com/kb/983509

Microsoft Team Foundation Server 2010 Service Pack 1
http://support.microsoft.com/kb/2182621

bharry’s WebLog – Everything you want to know about Visual Studio ALM and Farming
http://blogs.msdn.com/b/bharry/archive/2011/03/08/vs-tfs-2010-sp1-and-tfs-project-server-integration-feature-pack-have-released.aspx