Image to byte array and vice-versa

Posted October 5th, 2010 in .NET, Source Code by Sam Beauvois

This is an old code snippet I posted on the www.developpez.com faq a few years ago.

I needed it today, and I decided to post it here

Image to byte array :


public static Byte[] ImageToByteArray(Image img)
{
try
{
MemoryStream mstImage = new MemoryStream();
img.Save(mstImage, System.Drawing.Imaging.ImageFormat.Jpeg);
Byte[] bytImage = mstImage.GetBuffer();
return bytImage;
}
catch (Exception ex)
{
// do something smart
return null;
}
}

Image to Byte array


public static Image ByteArrayToImage(Byte[] BArray)
{
try
{
MemoryStream mstImage = new MemoryStream(BArray);
Image img = Image.FromStream(mstImage);
return img;
}
catch (Exception ex)
{
// do something smart
return null;
}
}
http://dotnet.developpez.com/faq/csharp/?page=gdiplus#gdip_convert_image_bytes

Bring a bit of the Subsonic power to Linq to sql by adding automatic audit and logical delete fields

Posted September 14th, 2010 in .NET, Linq, SubSonic by Sam Beauvois

[Update]
You cand find the code to do the same with entity framework here
[/Update]

Recently I had to work on a project using Linq to sql  and I was suprised to see that Linq to SQL has no built-in auditing ability.

There is no support for logical deletion neither.

With the SubSonic’s ActiveReccord, all these features are built in (see the documentation page).

So, I decided to add this ability for the project, because I doesn’t want to change all the existing request to add these informations.

In my BLL layer, I have a manager object for my DAL Linq objects, so by Example if I have an “User” Object in my DAL layer, I have an “UserManager” object in my BLL layer.

All my managers objects inherit a “ManagerBase” Object, which contains only a “DataContext” Property, which can be used in the child classes.

So my first approach was to add a “SubmitChanges”  method in that class and call it from my child classes instead of directly call the one from the DataContext.

In my SubmitChanges method I add the needed logic before calling the one from the DataContext.

But I realized that when there are more than one developper working on an application, it can be difficult to ensure that everybody use the same technique. A person may not use the base class, another may forget to use the base class method, or other things..

Then I investigated the DataContext object with Reflector, and I noticed that the SubmitChanges(void) method directly call the SubmitChanges(ConflictMode) one


public void SubmitChanges()
{
 this.CheckDispose();
 this.SubmitChanges(ConflictMode.FailOnFirstConflict);
}

And if I take a look at the generated DataContext, I see that the DataContext is a partial class


public partial class MyContext: System.Data.Linq.DataContext
{
 // ...
}

So, I decided to add a new file in my DAL layer and extend the DataContext

partial class MyContext
{
// ...
}

Then override the SubmitChanges(ConflictMode) DataContext method


public override void SubmitChanges(System.Data.Linq.ConflictMode failureMode)
 {
SetSystemFields(); // notice this method call !
base.SubmitChanges(failureMode);
 }

In the SetSystemFields method, I retrieve the pending changes


private void SetSystemFields()
 {
ChangeSet changeset = this.GetChangeSet();

// ...
}

Then I retrieve the user identity in order to be able to set the CreatedBy and ModifiedBy properties of my data objects


System.Security.Principal.WindowsIdentity identity = System.Security.Principal.WindowsIdentity.GetCurrent();
 string userName = "Unknow";
 if (identity != null)
 {
userName = identity.Name;
 }

Then I loop over the objects that have to be inserted


int maxInserts = changeset.Inserts.Count;
for (int i = 0; i < maxInserts; i++)
{

// ...

}

and I use reflection to get the audit properties and set their values


object entity = changeset.Inserts[i];
 Type objectType = entity.GetType();
 PropertyInfo[] properties = objectType.GetProperties();

foreach (PropertyInfo property in properties)
 {
switch (property.Name.ToUpper())
{
case SystemFields.CreatedOn:
case SystemFields.ModifiedOn:
{
property.SetValue(entity, DateTime.Now, null);
} break;
case SystemFields.CreatedBy:
case SystemFields.ModifiedBy:
{
property.SetValue(entity, userName, null);
} break;
case SystemFields.IsDeleted:
{
property.SetValue(entity, false, null);
} break;
default:
break;
}
 }

Remark : “SystemFields” is a struct I defined with the audit column names but you may as well make it come from a config file.


private struct SystemFields
{
 public const string CreatedOn = "CREATEDON";
 public const string ModifiedOn = "MODIFIEDON";
 public const string CreatedBy = "CREATEDBY";
 public const string ModifiedBy = "MODIFIEDBY";
 public const string IsDeleted = "ISDELETED";
}

I do the same treatment for the update and deletes (if I want to enable them).

Now everytime that the DataContext’s SubmitChanges method is called, the audit fields are automaticaly set!

Here is the full partial class for the DataContext

using System;
using System.Data.Linq;
using System.Reflection;

namespace MyNamespace.DAL
{
 partial class MyContext
 {
  /// <summary>
  /// system fields for automatic audit and logical delete
  /// </summary>
  private struct SystemFields
   {
        public const string CreatedOn = "CREATEDON";
        public const string ModifiedOn = "MODIFIEDON";
        public const string CreatedBy = "CREATEDBY";
        public const string ModifiedBy = "MODIFIEDBY";
        public const string IsDeleted = "ISDELETED";
  }

public override void SubmitChanges(System.Data.Linq.ConflictMode failureMode)
{

SetSystemFields();

base.SubmitChanges(failureMode);
}

private void SetSystemFields()
{
ChangeSet changeset = this.GetChangeSet();

// retrieve the user name
System.Security.Principal.WindowsIdentity identity = System.Security.Principal.WindowsIdentity.GetCurrent();
string userName = "Unknow";
if (identity != null)
{
userName = identity.Name;
}

// insert
int maxInserts = changeset.Inserts.Count;
for (int i = 0; i < maxInserts; i++)
{
object entity = changeset.Inserts[i];
Type objectType = entity.GetType();
PropertyInfo[] properties = objectType.GetProperties();
foreach (PropertyInfo property in properties)
{
switch (property.Name.ToUpper())
{
case SystemFields.CreatedOn:
case SystemFields.ModifiedOn:
{
property.SetValue(entity, DateTime.Now, null);
} break;
case SystemFields.CreatedBy:
case SystemFields.ModifiedBy:
{
property.SetValue(entity, userName, null);
} break;
case SystemFields.IsDeleted:
{
property.SetValue(entity, false, null);
} break;
default:
break;
}
}
}

// update
int maxUpdates = changeset.Updates.Count;
for (int i = 0; i < maxUpdates; i++)
{
object entity = changeset.Updates[i];
Type objectType = entity.GetType();
PropertyInfo[] properties = objectType.GetProperties();
foreach (PropertyInfo property in properties)
{
switch (property.Name.ToUpper())
{
case SystemFields.ModifiedOn:
{
property.SetValue(entity, DateTime.Now, null);
} break;
case SystemFields.ModifiedBy:
{
property.SetValue(entity, userName, null);
} break;
default:
break;
}
}
}

// deletes (logical deletes)
int maxDeletes = changeset.Deletes.Count;
for (int i = 0; i < maxDeletes; i++)
{
object entity = changeset.Deletes[i];
Type objectType = entity.GetType();
PropertyInfo[] properties = objectType.GetProperties();
foreach (PropertyInfo property in properties)
{
switch (property.Name.ToUpper())
{
case SystemFields.ModifiedOn:
{
property.SetValue(entity, DateTime.Now, null);
} break;
case SystemFields.ModifiedBy:
{
property.SetValue(entity, userName, null);
} break;
case SystemFields.IsDeleted:
{
property.SetValue(entity, true, null);
} break;
default:
break;
}
}
}
}
}
}

Debugging ADO.NET Datatables

Posted May 14th, 2010 in .NET, ADO.NET, Debug, Development by Sam Beauvois

Do you ever had the famous error message :

“Failed to enable constraints. One or more rows  contain values violating non-null, unique, or foreign-key  constraints.”

when using ADO.NET Datasets ?

Tthis is an incredibly useful message isn’t it ?

So what can you do to spare you some headaches ? Retrieve a more useful message sure !

You have to know that a Datatable object have a “HasError” property, this property allows you to know if the datatable has one ore more rows in error.

When HasError is true, you can retrieve the rows havin an error with the DataTable’s “GetErrors()” method wich return an array with all datarow having an error.

The “in errror” rows can inform you about errors with the “RowError” property.

Here is a simple helper class which can be used to debug a single DataTable or an entire DataSet:

using System;
using System.Data;

public class DataSetErrorRevealer
{

   /// <summary>
   /// Get errors on rows of a DataTable
   /// </summary>
   /// <param name="errorDataTable">The DataTable to be checked</param>
   public static void RevealTableErrors(DataTable errorDataTable)
   {
      if (errorDataTable == null)
      {
         Console.WriteLine("The provided DataTable object is null");
         return;
      }

      if (errorDataTable.HasErrors)
      {
         DataRow[] rowsInError = errorDataTable.GetErrors();
         if (rowsInError.Length <= 0)
         {
            Console.WriteLine("There is no problem with table {0}", errorDataTable.TableName);
         }
         else
         {
            foreach (DataRow errorRow in rowsInError)
            {
               Console.WriteLine(errorRow.RowError);
            }
         }
      }
   }

   /// <summary>
   /// Get errors on row for all tables of a DataSet
   /// </summary>
   /// <param name="errorDataSet">The Dataset to be checked</param>
   public static void RevealDataSetErrors(DataSet errorDataSet)
   {
         if (errorDataSet == null)
         {
            Console.WriteLine("The provided DataSet is null");
            return;
         }

         foreach (DataTable errorTable in errorDataSet.Tables)
         {
            RevealTableErrors(errorTable);
         }
      }
   }

Use it this way :


   TestDataSet dataset = new TestDataSet();
   try
   {
      using (SqlConnection sqlCon = new SqlConnection("MyConnectionString"))
      {
         SqlCommand sqlComm = sqlCon.CreateCommand();
         sqlComm.CommandType = CommandType.StoredProcedure;
         sqlComm.CommandText = "Select Stored procedure";
         SqlDataAdapter sqlDa = new SqlDataAdapter(sqlComm);
         sqlDa.Fill(dataset);
      }
   }
   catch (Exception ex)
   {
   // Will provide the error message :
   // "Failed to enable constraints. One or more rows
   // contain values violating non-null, unique,
   // or foreign-key  constraints."
   Console.WriteLine("Error : {0}", ex);

   // will provide a more helpful message
   DataSetErrorRevealer.RevealDataSetErrors(dataset);
   }

If you prefer, you can use an extension method :


using System.Data;
using System;

public static class DataSetExtensions
{
   public static void RevealErrors(this DataSet errorDataSet)
   {
      if (errorDataSet == null)
      {
         Console.WriteLine("The provided DataSet is null");
         return;
      }

      foreach (DataTable errorTable in errorDataSet.Tables)
      {
         errorTable.RevealErrors();
      }
   }

   public static void RevealErrors(this DataTable errorDataTable)
   {
      if (errorDataTable == null)
      {
         Console.WriteLine("The provided DataTable object is null");
         return;
      }

      if (errorDataTable.HasErrors)
      {
         DataRow[] rowsInError = errorDataTable.GetErrors();
         if (rowsInError.Length <= 0)
         {
            Console.WriteLine("There is no problem with table {0}", errorDataTable.TableName);
         }
         else
         {
            foreach (DataRow errorRow in rowsInError)
            {
               Console.WriteLine(errorRow.RowError);
            }
         }
      }
   }
}

use :


catch (Exception ex)
{
   // will provide an helpful message
   dataset.RevealErrors();
}

Hope this helps !

using System;
using System.Data;public class DataSetErrorRevealer
{

/// <summary>
/// Get errors on rows of a DataTable
/// </summary>
/// <param name=”errorDataTable”>The DataTable to be checked</param>
public static void RevealTableErrors(DataTable errorDataTable)
{
if (errorDataTable == null)
{
Console.WriteLine(“The provided DataTable object is null”);
return;
}

if (errorDataTable.HasErrors)
{
DataRow[] rowsInError = errorDataTable.GetErrors();
if (rowsInError.Length <= 0)
{
Console.WriteLine(“There is no problem with table {0}”, errorDataTable.TableName);
}
else
{
foreach (DataRow errorRow in rowsInError)
{
Console.WriteLine(errorRow.RowError);
}
}
}
}

/// <summary>
/// Get errors on row for all tables of a DataSet
/// </summary>
/// <param name=”errorDataSet”>The Dataset to be checked</param>
public static void RevealDataSetErrors(DataSet errorDataSet)
{
if (errorDataSet == null)
{
Console.WriteLine(“The provided DataSet is null”);
return;
}

foreach (DataTable errorTable in errorDataSet.Tables)
{
RevealTableErrors(errorTable);
}
}
}

FreeImage and x64 projects : Yes you can !

Posted May 14th, 2010 in .NET, CPP, Libs by Sam Beauvois

A few words about FreeImage

According to the website, FreeImage (http://freeimage.sourceforge.net) is an Open Source library project for developers who would like to support popular graphics image formats like PNG, BMP, JPEG, TIFF and others as needed by today’s multimedia applications.

FreeImage is easy to use, fast, multithreading safe, compatible with all 32-bit versions of Windows, and cross-platform (works both with Linux and Mac OS X).

FreeImage is written in C++ but can be used in .NET by using a wrapper (which is provided on the site in the download section)

Using FreeImage in a .NET project

To use FreeImage with a .NET project, you have to include the native C++ library (FreeImage.dll) in the same folder as the executable or in a folder contained in the PATH variable (“%WINDIR%\System32” can be a good choice).
A good way to include the FreeImage dll in the executable’s folder is to add it to your visual studio projet, and set the Build Action property to “none” and the Copy to Output Directory property to “Copy always”

image

You have to add a reference to the wrapper library too, which is “FreeImageNET.dll”.

Now, using the library is easy.

Add an using directive:

using FreeImageAPI;

Check if the library is available :

if (!FreeImage.IsAvailable())
{
   Console.WriteLine("FreeImage.dll seems to be missing. Aborting");
   return;
}

Do something with your pictures:


FIBITMAP myImage= new FIBITMAP();
myImage= FreeImage.Load( [parameters] );

// some smart actions

Don’t forget to dispose your images when finished to use them

if (!myImage.IsNull
{
   FreeImage.Unload(myImage);
}
myImage.SetNull();

Well, this is nice but it still has a problem with that library (there is always one):

And with a x64 project ?

The executable you build has to be the same architecture as the library. The library is x86 so you can use it for win32 applications. What if you have (for some reasons) to build an x64 application?

In that case, you have to rebuild the library to target X64 architectures.

Here is how to do that with Visual Studio 2010 (I assume that it’s more or less the same procedure with other visual studio versions).

Grab the latest FreeImage sources on  the download site (go to the http://freeimage.sourceforge.net/download.html page and click to the link in the Source Distribution section. Once you have the sources, unzip the archive (obvious but…)

In the FreeImage folder there is a visual studio 2005 and a visual studio 2003 solutions, pick the 2005.

image

Convert the solution

image
image
image
image
image

Notice the compilation configuration

image

By default, Win32 is set : we don’t want that !

Go to the Configuration Manager

image
image

As you can see, all FreeImage libs are set to target the Win32 platform, we want 64 bits !

Add a new solution platform

image

Choose to target the x64 platform

image

Just select x64 then click OK

image

Close the manager

Build the solution (keyboard shortcut : ctrl-shift-B).

image

And at this point you will see that there is a problem, yes, you don’t really think it would be that easy ;-)

image

It seems that the compilation encounters a problem especially with the “LibOpenJpeg” project

So, to be sure, try to compile the library one at the same time

image

We see that it is the LibOpenJPEG the big source of problems :

image

A quick Google search allows to find a post on the Google user group for OpenJPEG that helps:
http://groups.google.com/group/openjpeg/browse_thread/thread/64b89cdb1a44bb3b/fd4db2f74c76db87?lnk=gst&q=x64#fd4db2f74c76db87

The problematic file is the “opj_include.h” wich use a keyword non supported by the x64 architecture (the “_asm” keyword if you want to know. It’s because the c++ compiler does not support inline x64 assembly)

image

We have to change :

/* MSVC does not have lrintf */
#ifdef _MSC_VER
static INLINE long lrintf(float f){
 int i;

 _asm{
 fld f
 fistp i
 };

 return i;
}
#endif

to

/* MSVC does not have lrintf */
#ifdef _MSC_VER
static INLINE long lrintf(float f){
#ifdef _M_X64
	return (long)((f>0.0f) ? (f + 0.5f):(f -0.5f));
#else
	int i;

	_asm{
		fld f
		fistp i
	};

	return i;
#endif
}
#endif

Now compile

image

The project compiles pretty well, there is some remaining warnings . . . but it works.

Now you can use that library (mine can be downloaded at  http://www.sambeauvois.be/Demos/FreeImage/x64/FreeImageX64.zip) in your x64 applications

Attention anyway : the library will be slower !

Additional links :

FreeImage download page : http://freeimage.sourceforge.net/download.html
FreeImage API documentation: http://freeimage.sourceforge.net/fnet/Index.html

/* MSVC does not have lrintf */

#ifdef _MSC_VER

static INLINE long lrintf(float f){

#ifdef _M_X64

return (long)((f>0.0f) ? (f + 0.5f):(f -0.5f));

#else

int i;

_asm{

fld f

fistp i

};

return i;

#endif

}

#endif

The IX509CertificateRequestPkcs10 InitializeFromTemplateName adventure

Posted April 28th, 2010 in .NET, Security, Source Code by Sam Beauvois

This week has been researches, tests and headaches to be able to make request on a Certificate Authority server from a web application.

My client has a Win server 2008 CA server for my developments

On this server I have a certificate template named “User Template”

Certificate_server_templates

My assignment was to request a certificate via an ASP.NET application.

After researches on how to do that, I found this blog post that helped me a lot : http://blogs.msdn.com/alejacma/archive/2008/09/05/how-to-create-a-certificate-request-with-certenroll-and-net-c.aspx

In my development environment, I create a request for a certificate by using  this code

 CERTENROLLLib.CX509CertificateRequestPkcs10Class request = new CERTENROLLLib.CX509CertificateRequestPkcs10Class();
 string templateName = "User Template";
 try
 {
    request.InitializeFromTemplateName(CERTENROLLLib.X509CertificateEnrollmentContext.ContextUser, templateName);
 }
 catch (Exception ex)
 {
   log.DebugFormat("Error InitializeFromTemplateName : message {0}, inner : {1}, stack : {2}, source : {3}, target : {4} ",
    ex.Message,
    ex.InnerException,
    ex.StackTrace,
    ex.Source,
    ex.TargetSite);
 }

And it worked just fine !

Then we moved the published solution to the staging environment, and the problems arrived . . .

It didn’t worked !

The error message said:

“CertEnroll::CX509CertificateRequestPkcs10::InitializeFromTemplateName: The requested certificate template is not supported by this CA. 0×80094800 (-2146875392)”

stack :

“at CERTENROLLLib.CX509CertificateRequestPkcs10Class.InitializeFromTemplateName(X509CertificateEnrollmentContext Context, String strTemplateName)”

cererror

We checked the security everywhere ( CA server, Certificate templates, IIS Account, …), give access to everyone on the CA, on the template, … without any success

Then, after days and hours of search and tests, I decided to re-read the method documentation : http://msdn.microsoft.com/en-us/library/aa377533%28v=VS.85%29.aspx

And I noticed the second parameter description:

strTemplateName [in]
Pointer to a BSTR variable that contains the Common Name (CN) of the template as it appears in Active Directory or the dotted decimal object identifier.

I had never tried using the dotted decimal object identifier, so i give it a shot.

I retrieved the object identifier on a certificate previously created with the “User Template”

On the CA server, I had a certificate request with the template “User Template”, so I right-click on it, go to All Tasks and click on the “View attributes/Extensions. . .” menu item.

image

image

A property windows opened, I go to the Extensions tab and click on the “Certificate Template Information” item.

image

In the information panel, I can see the famous dotted decimal object identifier between brackets.

I copy-paste this identifier in my code :

 CERTENROLLLib.CX509CertificateRequestPkcs10Class request = new CERTENROLLLib.CX509CertificateRequestPkcs10Class();
 string templateName = "1.3.6.1.4.1.311.21.8.3531346.8488945.6374567.164989.5001604.52.12582268.10747996";
 try
 {
    request.InitializeFromTemplateName(CERTENROLLLib.X509CertificateEnrollmentContext.ContextUser, templateName);
 }
 catch (Exception ex)
 {
    log.DebugFormat("Error InitializeFromTemplateName : message {0}, inner : {1}, stack : {2}, source : {3}, target : {4} ",
      ex.Message,
      ex.InnerException,
      ex.StackTrace,
      ex.Source,
      ex.TargetSite);
 }

I compiled, I tried in the development environment and it worked !!

(note: there is just a minimal change in my code since I put the “templateName” in a configuration file in order to be able to modify it)

So we moved the published solution to the staging environment,

retrieve the dotted decimal object identifier corresponding to the “User Template” on the staging CA server,

copy-pasted this identifier in the configuration file,

executed a “IISRESET” command and try to execute the application.

And it worked !

We can’t figured out why it worked in the development environment but not in the staging one while both are equals. So If anyone knows about it, please let me know.

So, don’t trust the template name and use the object identifier !