Damir Arh's Corner
Search
Categories
  Development
 .NET
 Batch
 C++
 SQL
 VB6
 Vista
 Web
 Win32
  Downloads
 Amiga
 Articles
 Presentations
 Sources
 Windows
  Personal
 Education
 Software
 Website
Archives
July, 2008 (1)
June, 2008 (1)
April, 2008 (2)
December, 2007 (1)
November, 2007 (3)
July, 2007 (4)
June, 2007 (1)
May, 2007 (2)
March, 2007 (3)
January, 2007 (1)
December, 2006 (4)
October, 2006 (5)
September, 2006 (3)
August, 2006 (2)
June, 2006 (8)
May, 2006 (5)
April, 2006 (1)
March, 2006 (4)
February, 2006 (3)
January, 2006 (3)
March, 2003 (1)
February, 2002 (1)
January, 2002 (2)
August, 2001 (1)
July, 2001 (1)
February, 2001 (1)
December, 2000 (1)
September, 2000 (1)
July, 2000 (1)
Other Sites
Potepanja v naravi (sl)
Picasa Web Albums (sl)
moj-album.com Gallery (sl)
Bolha.com Auctions (sl)
My Game Space
LinkedIn Public Profile
My GamerTag
Sponsored Links
Administration
Sign In
Saturday, July 05, 2008

Gama System eArchive accredited (Development | .NET | Personal | Software)

Gama System eArchive, one of the two products in our document product line, received accreditation from the Archives of the Republic of Slovenia last week. This acknowledgement by our national body means that any document stored in Gama System eArchive is automatically legally valid.

This is important for both our company and other companies looking for a long term electronic document storage solution. Our product is the first service oriented solution to receive the accreditation.

Congratulations to everyone involved in the product. Well done!

7/5/2008 9:37:14 PM (Central Europe Standard Time, UTC+01:00)  #  Comments [1]

Tuesday, April 29, 2008

Old ActiveX controls under .NET 2.0 SP1 (Development | .NET | Vista)

A .NET application in the company I work for recently started crashing under Windows Vista when trying to open a window implemented in an ActiveX DLL. Investigations showed that they were caused by an AccessViolationException "Attempted to read or write protected memory. This is often an indication that other memory is corrupt.". The cause was one of the ActiveX controls in the window. When instantited directly in a .NET Form the exception above was contained in a TargetInvocationException "Unable to get the window handle for the '<control name>' control. Windowless ActiveX controls are not supported.". Knowing that the control didn't suddenly turn windowless we dug deeper.

It turned out that the problem appeared with .NET Framework 2.0 Service Pack 1. Apparently it caused the C# compiler in Visual Studio 2005 and later to set the NXCOMPAT bit for all build targets without an option to turn this new behavior off. For those who don't know, this means that DEP (data execution prevention) will kick in unless it is turned off completely in the operating system. This wouldn't be a big deal unless ATL before Visual Studio 2005 didn't have a bug which caused the heap allocated memory not to be flagged as executable, which under the new circumstances results as the already mentioned exception. Windows XP has DEP turned off by default therefore everything still works but in Windows Vista it is turned on and prevents such application from functioning properly.

The best solution would of course be to recompile the ActiveX controls in Visual Studio 2005 or later but this might not be possible if they are supplied by a third party. In this case the most obvious approach to dealing with the situation is to disable DEP in Vista. There is a Data Execution Prevention tab in the Performance Options which open when you click the Settings button in the Performance frame of the Advanced tab in the System Properties dialog but it only allows switching between DEP for all processes with defined exceptions and DEP for essential Windows programs and services, i.e. executables flagged with the NXCOMPAT bit. The only way to turn DEP completely off is executing the following command with administrative privileges:

bcdedit.exe /set {current} nx AlwaysOff

After restart DEP will be turned off and problematic binaries will work once again. To restore the previous (default) state replace AlwaysOff with OptIn. The AlwaysOn option enables DEP for all processes and might cause additional problems (e.g. Google Calendar Sync in its current version 0.9.3.2 doesn't work in this mode).

Unfortunately, this solution would require all your Vista using customers to disable DEP as well which really isn't an option for commercial software. Fortunately, there is another solution. Although there is no compiler option to turn keep the NXCOMPAT bit unset, you can still do this after compilation using the editbin.exe which comes with C++ compiler for Visual Studio 2005 and later:

editbin.exe /NXCOMPAT:NO <filename.exe>

This command removes the NXCOMPAT bit and restores the behavior before .NET 2.0 SP1. If your assembly was signed it also invalidates the signature so you'll have to resign it:

sn.exe -R <filename.exe> <keyfile.snk>

You can automate this by putting the two commands in the Post-build event command line for the project:

editbin.exe /NXCOMPAT:NO "$(TargetPath)"
sn.exe -R "$(TargetPath)" "$(ProjectDir)<keyfile.snk>"

You might need to call vcvars32.bat before that to put the required executables in path and enable editbin.exe dependencies to be resolved. Note that in a completely automated build scenario using MSBuild you'll have to specify full path for the vcvars32.bat because $(DevEnvDir) resolves to *Undefined* outside Visual Studio 2005. Also your strong name key should be in a snk file instead of a password protected pfx file because sn.exe doesn't allow the password to be read from a redirected standard input.

4/29/2008 2:29:08 PM (Central Europe Standard Time, UTC+01:00)  #  Comments [1]

Monday, April 14, 2008

MonthCalendar BoldedDates in Windows Vista (Development | .NET | Vista)

The MonthCalendar control's BoldedDates functionality doesn't appear to work properly on Windows Vista. The dates added to any of the BoldedDates, MonthlyBoldedDates and AnnuallyBoldedDates collections are rendered just the same as those not added to any of the collections. The same code works just fine on Windows XP and causes those dates to be rendered bold. The only workaround i've managed to find is disabling visual styles in the application, i.e. commenting out the first line in the Program.Main() method of a new Windows Application:

Application.EnableVisualStyles();

4/14/2008 8:54:58 PM (Central Europe Standard Time, UTC+01:00)  #  Comments [0]

Saturday, November 24, 2007

Notes about RSACryptoServiceProvider (Development | .NET)

In my opinion RSACryptoServiceProvider class is seriously under-documented in MSDN. Since there is also no abundance of examples on the web, I spent more time than I should figuring out how to use it correctly. For future reference I'm listing below the solution to two problems I had.

The maximum byte array length for encrypting without OAEP padding is Modulus size - 11 which is written somewhere in the Encrypt() method documentation. If you pass it a larger array it will return a not so informative Unspecified error. To encrypt a larger chunk of data you have to split it in smaller parts, encrypt them individually and concatenate them back together. You have to do the same when decrypting the data, with the only difference that each part has the size of Modulus in stead of Modulus - 11. To get the modulus size you can use the following piece of code (rsa is an instance of RSACryptoServiceProvider):

RSAParameters rsaParams = rsa.ExportParameters(false);
int modulusSize = rsaParams.Modulus.Length;

Each time you instantiate RSACryptoServiceProvider it generates a new pair of keys. If you want to use existing ones, you can import them by calling:

rsa.FromXmlString(key);

The key parameter is a string with the XML representation of the keys. You can get it by calling the ToXmlString() method once and storing its results. It's only parameter specifies whether to also export the private key. I guess I don't have to remind you that you need the private key only for decryption and that you should always keep it private for the encryption to make any sense at all.

11/24/2007 5:31:53 PM (Central Europe Standard Time, UTC+01:00)  #  Comments [0]

Always close DeflateStream before reading results (Development | .NET)

Is the code below correct? Will inputString and outputString be equal?

string inputString = "The text to compress and decompress";
byte[] inputArray = Encoding.UTF8.GetBytes(inputString);

MemoryStream stream = new MemoryStream();
DeflateStream compressionStream =
    new DeflateStream(stream, CompressionMode.Compress);
compressionStream.Write(inputArray, 0, inputArray.Length);
compressionStream.Flush();

stream.Position = 0;

DeflateStream decompressionStream =
    new DeflateStream(stream, CompressionMode.Decompress);
byte[] outputArray = new byte[inputArray.Length];
decompressionStream.Read(outputArray, 0, outputArray.Length);
string outputString = Encoding.UTF8.GetString(outputArray);

Console.WriteLine(outputString == inputString);
Console.ReadLine();

As it turns out, they won't. The reason for it being that compressionStream.Close() was not called before reading from stream started. Calling compressionStream.Flush() is not enough in this case. I haven't managed to find this documented anywhere but the example in the DeflateStream documentation does it correctly. You can find the fixed code below. Notice the additional last parameter in the first call to the DeflateStream constructor. Without it stream will also be closed when compressionStream gets closed.

string inputString = "The text to compress and decompress";
byte[] inputArray = Encoding.UTF8.GetBytes(inputString);

MemoryStream stream = new MemoryStream();
DeflateStream compressionStream =
    new DeflateStream(stream, CompressionMode.Compress, true);
compressionStream.Write(inputArray, 0, inputArray.Length);
compressionStream.Close();

stream.Position = 0;

DeflateStream decompressionStream =
    new DeflateStream(stream, CompressionMode.Decompress);
byte[] outputArray = new byte[inputArray.Length];
decompressionStream.Read(outputArray, 0, outputArray.Length);
string outputString = Encoding.UTF8.GetString(outputArray);

Console.WriteLine(outputString == inputString);
Console.ReadLine();

Thanks once again to my coworker for suggesting this when I was already running out of ideas.

11/24/2007 4:44:37 PM (Central Europe Standard Time, UTC+01:00)  #  Comments [0]

Tuesday, July 24, 2007

Creating custom tasks for CruiseControl.NET (Development | .NET)

Once you start putting CruiseControl.NET to production use you'll sooner or later encounter the need for custom build tasks. There's only a limited set of them in the package and Executable Task can only do so much. Unfortunately there is not much information available on development of custom tasks. Your best sources will be:

  • Online documentation contains an article on the subject describing the first steps to get you going. It should be your first stop.
  • There's a high level architectural overview of a simple task available at Josh's Blog.
  • Lutz Roeder's Reflector for .NET will be your best friend. The source of the tasks in ThoughtWorks.CruiseControl.Core will soon become your best resource.

Apart from that I feel obliged to mention a few of the most important points I've come across during the development of a few custom tasks:

  • ThoughtWorks.CruiseControl.Core.Util.ProcessExecutor is a nice little wrapper around System.Diagnostics.Process class you'll end up using quite a lot.
  • You can add your own information to the build log by calling AddTaskResult on the IIntegrationResult instance passed to your ITask.Run method. There are two overloads available: one accepting a System.String and another one accepting ITaskResult to which you can pass a new FileTaskResult instance to quickly include a complete file.
  • If you're doing any checkins to your source control system as a part of the build you should call the MarkStartTime method of your IIntegrationResult instance afterwards to prevent triggering another build of the same project by setting the last build start time after the last checkin time.
  • Make sure you use a unique ReflectorType name for your task. The service will just silently fail to start in case of a duplicate value.

This information should make your first attempts at making your own custom task a little easier.

7/24/2007 12:57:26 PM (Central Europe Standard Time, UTC+01:00)  #  Comments [0]

Sunday, July 22, 2007

MSBuild.xsl problem in CruiseControl.NET 1.3 (Development | .NET | Downloads | Sources) msbuild.zip (1.33 KB)

The 1.3.0.2918 build of CruiseControl.NET has an error in msbuild.xsl file which causes an XslLoadException to be thrown when trying to view the MSBuild output in the web dashboard. One of the users was nice enough to describe the changes to the file necessary to fix the problem. Unfortunately even the latest version of the file on the CruiseControl.NET Live site doesn't include the changes therefore I'm attaching the file to this post as convenience.

7/22/2007 12:24:07 PM (Central Europe Standard Time, UTC+01:00)  #  Comments [0]

Saturday, June 02, 2007

OCR with Microsoft Office Document Imaging (Development | .NET)

If you need cheap and simple OCR functionality Microsoft Office Document Imaging Type Library (MODI) is a nice option if its requirements (Microsoft Office 2003 or later) and limitations (limited language support) don't bother you. Here is a simple C# function that does OCR on the image with the specified path:

static string OCR(string path)
{
    MODI.Document doc = new MODI.Document();
    doc.Create(path);
    doc.OCR(MODI.MiLANGUAGES.miLANG_ENGLISH, false, false);
    string result = ((MODI.Image)doc.Images[0]).Layout.Text;
    System.Runtime.InteropServices.Marshal.ReleaseComObject(doc);
    return result;
}

However, there is another Microsoft Office object model related problem. For Office 2003 users to be able to use your application, the MODI 11.0 (2003 version) must be referenced in the project and the release version of the application must be compiled on a machine with Office 2003 installed. In such a case VB6 still managed to compile the project on a machine with a newer version of Office installed, since the newer version of the type library was automatically used (MODI 12.0 for Office 2007 in this case). On the other hand strong type checking at compile time prevents that in C#.

If you want to keep using Office 2007 and be able to compile such a project, the only solution is to install Microsoft Office Document Imaging as the only component of Office 2003 along the existing Office 2007 installation. Unfortunately this overwrites the Microsoft Office Document Image Writer printer driver from 2007 with the older version, therefore you'll have to start a lengthy process of repairing the Office 2007 installation afterwards. And don't forget to apply all the service packs and updates for Office 2003 before that since this will also overwrite the printer driver and you'll have to repair Office 2007 once again. I learned that the hard way.

6/2/2007 9:39:34 AM (Central Europe Standard Time, UTC+01:00)  #  Comments [1]

Monday, December 25, 2006

MCP Exam 70-536 Experiences (Development | .NET | Personal | Education)

I’ve recently passed the MCP exam 70-536: TS: Microsoft .NET Framework 2.0 – Application Development Foundation. My overall experience has been very positive. Although there are a few not so relevant topics I think that most of them are a must-know if you’re a .NET developer. I found the exam quite easy with only a few really nitpicking questions. Maybe I was just lucky but it was a pleasant surprise for me.

I used the Microsoft Self-Paced Training Kit as the study guide. In spite of the mistakes it contains (see errata) I still find it a useful overview of the topics covered by the exam. I even think of it as a great overview of .NET framework for every developer even if he’s not considering taking the exam. On the other hand it really shouldn’t be your only resource, more of a starting point to direct you to the topics you realize you don’t know enough about. MSDN or a more specialized book can help you from there on.

If you’re interested, I’m selling my own copy of the book at a reduced price. It is in mint condition, I’ve even left the 15% off voucher unused. On a side note: here you can always see the list of items I am selling. The link is listed among my other sites in the left column of this page.

12/25/2006 9:49:24 AM (Central Europe Standard Time, UTC+01:00)  #  Comments [3]

Friday, October 20, 2006

Application roles and connection pooling (Development | .NET | SQL)

One would have thought this to be a well known fact but since one of our developers stumbled upon it yesterday I thought it might be useful to someone else.

As soon as a pooled connection with enabled application role gets reused an exception gets thrown and its description is not really helpful if you’re not aware of the problem: General Network Error. This happens because the security context of the connection doesn’t get properly reset when it is closed. To work around the problem you can either avoid using application roles or disable connection pooling (by adding Pooling=False to the connection string). You can find more details in this knowledge base article.

It might be worth mentioning that the above is completely accurate only for SQL Server 2000. SQL Server 2005 comes with a new stored procedure sp_unsetapprole which can be used to reset the security context. I haven’t tried it but by calling it before closing the connection you should be able to make application roles work together with connection pooling.

10/20/2006 3:09:17 PM (Central Europe Standard Time, UTC+01:00)  #  Comments [1]

Tuesday, September 19, 2006

Configuration.Save requires Full Control access to a file (Development | .NET)

Don’t use Configuration.Save in scenarios where users might only have read and write permissions for the configuration file as UnauthorizedAccessException will be thrown if full control is not granted. More details are available in the following MSDN Forum posting.

9/19/2006 10:32:34 PM (Central Europe Standard Time, UTC+01:00)  #  Comments [0]

Sunday, September 17, 2006

Mapping URLs in ASP.NET (Development | .NET)

ASP.NET offers several ways of mapping nice public URLs to cryptic internal URLs matching the actual implementation.

The simplest way is to match each public URL to its internal value. You can do this by either creating dummy pages which do the redirecting or by adding them to the urlMappings section of the web.config file (brought by framework 2.0). The latter solution is preferable because of simpler maintenance but both of them have the downside of being completely static (an entry is necessary for each mapped page).

A better solution is to implement an IHttpHandler or IHttpModule and do the mapping by calling HttpContext.RewritePath(). You could also change the requested page by using Server.Transfer() or maybe even Response.Redirect() but they have their disadvantages when used for URL mapping.

To avoid having to recompile your IHttpHandler implementation every time the mapping logic changes or extends you could configure it through a custom section in the web.config file. Regular expressions are a nice tool for defining such mappings as demonstrated by here (also check the comments) or implemented in dasBlog sources (check newtelligence.DasBlog.Web.Core.UrlMapperModule). You could even use UrlRewritingNet.UrlRewrite if you don’t like reinventing the wheel.

9/17/2006 12:33:22 PM (Central Europe Standard Time, UTC+01:00)  #  Comments [0]

Thursday, September 07, 2006

Last modification time of a web page (Development | .NET)

The following code returns the time when a web resource was last modified:

static DateTime GetModificationTime(string url)
{
   WebRequest request = WebRequest.Create(url);
   HttpWebResponse response = (HttpWebResponse) request.GetResponse();
   DateTime lastModified = response.LastModified;
   response.Close();
   return lastModified;
}

It’s quite a simple piece of code actually and very similar to a sample in MSDN. But maybe it will be useful to someone since a member of my developer team was convinced that there is just no way to get this information in .NET.

9/7/2006 10:41:34 PM (Central Europe Standard Time, UTC+01:00)  #  Comments [1]

Saturday, August 05, 2006

Too many projects in a solution slows down Visual Studio 2005 (Development | .NET)

Once the number of projects in a solution comes up to thirty or more, most of the project related operations become really slow: setting the default project, building a project starting and stopping a debug session etc. There are no noticeable slowdowns with up to twenty projects in a solution though.

Although usually no solution with real projects should reach such numbers (I stumbled upon it by just adding sample projects to the same solution), it is something to have in mind when deciding how to group projects in solutions.

8/5/2006 1:16:42 PM (Central Europe Standard Time, UTC+01:00)  #  Comments [0]

Saturday, June 10, 2006

DasBlog macro development (Development | .NET | Web | Personal | Website)

DasBlog – the weblog engine this site is running on – allows extensibility through macros. You’ll need to use them as soon as you want any additional dynamic content on your site. (The ads you can see at the bottom of the right side bar are an example of a macro which I’ve recently updated to make the ad selection a little more advanced.) The documentation doesn’t mention their development at all therefore the following post by Vasanth Dharmaraj is probably the best source of information available on it. It actually discusses everything you need to know to get going. Make sure you read it before trying to write your first macro.

6/10/2006 10:42:10 PM (Central Europe Standard Time, UTC+01:00)  #  Comments [0]

Friday, June 09, 2006

Writing to EventLog (Development | .NET)

Before using EventLog.WriteEntry for adding events to event log you should consider calling EventLog.CreateEventSource to make your application a valid source of events. Keep in mind though that you need administrative privileges for it succeed, therefore it is best to call it at installation time. So, if you want to write to the application event log by calling:

EventLog.WriteEntry("MyApplicationName", "My event text");

don’t forget doing this first:

if (!EventLog.SourceExists("MyApplicationName"))
   EventLog.CreateEventSource("MyApplicationName", "Application");

6/9/2006 4:34:50 PM (Central Europe Standard Time, UTC+01:00)  #  Comments [0]

Sunday, June 04, 2006

Implementing plug-ins with late binding (Development | .NET)

Essentially everything you need to implement plug-ins in your application is some way to dynamically instantiate classes at runtime. As long as they all implement the same interface, you just use it to access its properties and methods.

In COM world this was achieved by calling the CreateObject function. In the managed world you should use AppDomain.CreateInstanceAndUnwrap as demonstrated by the following example:

IBind pluginInstance = (IBind)AppDomain.CurrentDomain.CreateInstanceAndUnwrap("MCPP", "DamirsCorner.Samples.LateBinding.MCPP");

Everything you need to know at runtime is the full class name (including the namespace) and the containing assembly. To get those you can either require their previous registration within the application or you can dynamically discover them by loading assemblies from a predefined location (Assembly.Load or Assembly.LoadFrom) and enumerating their classes (Assembly.GetTypes) whichever suits you situation best.

6/4/2006 10:22:32 AM (Central Europe Standard Time, UTC+01:00)  #  Comments [0]

Sunday, May 28, 2006

Marshalling System.String to char* and vice-versa (Development | .NET | C++)

By switching from C# with P/Invoke calls to Managed C++ when implementing a managed wrapper for the ANSI C style library I stumbled upon, I wanted to avoid the tedious and error-prone task of writing the P/Invoke signatures for function calls and user-defined types for the structures they used. As a side result I also managed to avoid most of the advanced marshalling issues with complex data structures.

With simple value types not needing any explicit marshalling only strings need special attention since char* and System::String can’t be implicitly converted between. The Marshal class implements the methods necessary for doing this as demonstrated in the following snippet:

String^ MCPP::Together(String^ first, String^ second)
{
   // marshal managed strings to unamanged memory
   IntPtr firstPtr = Marshal::StringToHGlobalAnsi(first);
   IntPtr secondPtr = Marshal::StringToHGlobalAnsi(second);

   // cast unmanaged buffer to a characer array
   char* firstNative = static_cast<char*>(firstPtr.ToPointer());
   char* secondNative = static_cast<char*>(secondPtr.ToPointer());

   // perform some unmanaged calls
   int bufferSize = strlen(firstNative) + strlen(secondNative) + 4;
   char* resultBuffer = new char[bufferSize];
   sprintf_s(resultBuffer, bufferSize, "%s + %s", firstNative, secondNative);
  
   // marshal unmanaged character array to managed string
   String^ result = Marshal::PtrToStringAnsi(static_cast<IntPtr>(resultBuffer));
  
   // free all unmanaged buffers
   delete[] resultBuffer;
   Marshal::FreeHGlobal(firstPtr);
   Marshal::FreeHGlobal(secondPtr);
  
   // return managed string
   return result;
}

It should be noted that it wouldn’t make any sense switching to unmanaged code to do some string operations only as shown above. This is for demonstration purposes only and you would usually call some unmanaged libraries or the like instead of it. But it is a nice demonstration how cumbersome string operations were in C. If you were doing this once, the sprintf_s function call might have caught your attention. It’s a safe implementation of sprintf which prevents buffer overflows.

Another point worth mentioning is that you have to take care of allocated memory for the conversion since your character array is now allocated on the unmanaged heap. Make sure you use the FreeHGlobal method to do it, not the free (used for freeing memory allocated by *alloc calls – ANSI C style) or delete (used for freeing memory allocated by new calls – C++ style) functions.

To reduce the code overhead of string conversions between managed and unmanaged world you might consider wrapping it into a helper class. This should also help preventing unwanted memory leaks during the conversions.

5/28/2006 1:41:03 PM (Central Europe Standard Time, UTC+01:00)  #  Comments [2]

Sunday, May 14, 2006

Implementing a managed interface in C++ (Development | .NET | C++)

Less than a month ago I was certain I’d never have to write managed code in C++. With such a set of mind I didn’t really care about the new features being added and improvements being made to managed C++ since the first Visual Studio .NET. Luckily there were people thinking otherwise and as a result this – often overlooked – member of the .NET family got better with every release and is actually quite nice in the 2005 version. Don’t get me wrong – it still is C++ and you probably wouldn’t want to use it if you could get away with C# or VB. But if platform invoke is giving you too many headaches you might want to take a look at it. It could be the easiest way to solve your problem.

To make this a little bit easier for those of you who haven’t used C++ for some time and didn’t bother to check managed C++ at all, I’ll provide a small sample to help out with the beginner’s problems I had when starting out.

In a situation like mine you’ll usually want to write a class library to wrap the unmanaged calls for undisturbed use within you managed project. In my case I’ll be implementing an interface but writing a standalone class is not much different.

Let’s start with the header file. You might remember that C++ requires the separation of class declaration from method definition, the former being done in a header (*.h) file and the latter in a code (*.cpp) file. I admit being a little bit spoiled by not having to do that any more in C#. Let’s name our header MCPP.h (fell free to guess what it stands for):

using namespace System;

namespace DamirsCorner
{
   namespace Samples
   {
      namespace LateBinding
      {
         public ref class MCPP : IBind
         {
         public:
            virtual String^ Together(String^ first, String^ second);
         };
      }
   }
}

It looks like a hybrid between C++ and C# and one could argue that’s what it actually is. I’d like to point out the following:

  • The using directive has an additional keyword namespace. Also a double colon (static separator in C++) would be used to separate nested namespaces instead of a dot. You’ll see this in the code file which follows.
  • To put your own code into a nested namespace, you’ll have to actually nest the namespace declarations. Separating several of them with double colons won’t work.
  • To declare a managed class, use the additional keyword ref.
  • Don’t forget the different use of the public keyword for the members in C++ compared to C#.
  • The ^ character denotes a reference to a managed object (stored on the managed heap), separating it from unmanaged pointers (* character).
  • Notice the interface IBind being implemented by the class. A standalone class wouldn’t need this of course. The virtual keyword in the method declaration would also be skipped in this case.

This is it for the header file. Let’s look at the code file now:

#include "MCPP.h"

using namespace System;
using namespace DamirsCorner::Samples::LateBinding;

String^ MCPP::Together(String^ first, String^ second)
{
   return String::Empty;
}

It’s pretty obvious the method doesn’t really do anything but it’s the skeleton we’re focusing on at the moment. You should turn your attention to the following:

  • The code file must include the header file it implements (i.e. defines its methods). To refresh your C++ knowledge: it’s a good habit to use quotes for internal project header files and pointy brackets for external library header files. The compiler looks in the project directory first for the former and in the include directories first for the latter. It checks the other location if it doesn’t find the file but it will work faster if you use the right one (not to mention that by doing it you’re avoiding the problem of locating the wrong include with the same name).
  • You can notice the double colons as namespace separators as I mentioned before.
  • The methods you’re implementing are not within the class declaration any more. You already declared the class in the header file therefore you only set the method class membership here by prefixing its name with the class name and a colon, just like you were calling a static method.
There’s a reason I used String for parameter and return value type. While value types can be directly used in unmanaged code, reference types have to be correctly marshaled. But that’s a complex enough topic to justify a separate posting. The only thing left for this one is to make the code above compile. Just start a new Class Library project in C++ (you’ll find it in the CLR group) and paste the code to the right files. After you reference the assembly containing the interface used (similar to doing it in C#) the code should build successfully.

5/14/2006 6:11:27 PM (Central Europe Standard Time, UTC+01:00)  #  Comments [0]

Wednesday, May 03, 2006

Useful PInvoke resources (Development | .NET)

Completely unexpectedly I stumbled across Platform Invocation Services today when I was introduced to the IBM Tivoli Storage Manager API. It should have been a simple case of getting to know the API and writing a sample application with it, but it turned out that there’s no managed wrapper available for it (in spite of first being told otherwise). Combine that fact with an abundance of low level calls and large structs as their parameters and you can imagine that after one day there’s still a long way to that sample application, not to mention the final solution.

For anybody else like me out there who hasn’t done more than an occasional DllImport call or two the following resources should help getting to grips with the PInvoke basics:

  • Platform Invoke Tutorial – a must read for anyone starting with PInvoke. As usual, the follow-up links provide lots of additional useful information.
  • PINVOKE.NET – an indispensable source of information on WinAPI PInvoke calls. Not exactly what I needed but still the abundance of example calls turned out helpful.
  • The P/Invoke Wizard – a simple tool for converting C/C++ include files to PInvoke declarations. Not perfect and a bit pricy for what it does but still worth it due to the time it can save you when dealing with many large include files.
I hope you find these useful just as I did.

5/3/2006 10:34:25 PM (Central Europe Standard Time, UTC+01:00)  #  Comments [0]

Wednesday, March 22, 2006

Unit testing for beginners (Development | .NET | Personal | Education)

Ever since I attended a lecture on test driven development I’ve been trying to find a way to use its essential part – unit testing – in real development environment. I realized this isn’t completely trivial after assigning a developer to write ad hoc unit tests for the class library of a recent project and failing at it completely because the tests turned out to make sure the method functionality wouldn’t change instead of making sure the functionality is actually correct.

Since a new project is coming up and we really need more security when changing the code in its later phases I decided to dedicate some more time to exploring and deriving the concepts of using unit testing in a not really development driven project. Well, I happened to stumble upon Pragmatic Unit Testing in C# with NUnit, a book which turned out to be a perfect answer to my questions. All that’s left now is to make the developers read the book and grasp its concepts before starting their work on the project.

In a few months you’ll probably be able to read here how it turned out. In the meantime I recommend the book to everyone who wants to start with unit testing but just doesn’t know how to do it.

3/22/2006 11:04:36 PM (Central Europe Standard Time, UTC+01:00)  #  Comments [0]

Tuesday, February 28, 2006

Use Stopwatch to measure code execution time (Development | .NET)

One of the most common tasks when analyzing performance and optimizing code is measuring the time it takes to execute the code in question. Before .NET 2.0 you had to develop you own high resolution timer for the job by wrapping the unmanaged calls to QueryPerformanceCounter and QueryPerformanceFrequency.

I kept using the same class in .NET 2.0 but just the other day I stumbled across the Stopwatch class in the System.Diagnostics namespace. It implements the same high resolution timer functionality out of the box, so there’s no need to use unmanaged calls to achieve it anymore.

And the basic usage couldn’t be simpler:

using System.Diagnostics;
// ...
Stopwatch sw = new Stopwatch();
sw.Start();
// do some processing here
sw.Stop();
Debug.WriteLine("Time elapsed:" + sw.ElapsedMilliseconds.ToString());

One wonders what other hidden treasures lie in the class library yet to be discovered.

2/28/2006 10:21:00 PM (Central Europe Standard Time, UTC+01:00)  #  Comments [0]

Friday, February 24, 2006

Static class constructors should never throw an exception (Development | .NET)

I’ve spent a few hours today hunting down a mysterious bug which caused the program to keep reporting failed connections to database server although it was already available for hours. In the end it was a problem of incomplete exception handling but it’s interesting how the problem manifested itself. Let’s look at the following sample code.

using System;
using System.Collections.Generic;
using System.Text;

namespace DamirsCorner.Samples.StaticConstructor
{
   class Program
   {
      static string source;

      class Static
      {
         static Guid problem;

         static Static()
         {
            // will cause an exception if not a valid guid
            problem = new Guid(Program.source);
         }

         public static void Write()
         {
            // will only succeed after successful type initialization
            Console.WriteLine("Success!");
         }
      }

      static void Main(string[] args)
      {
         // setup invalid GUID source value
         source = String.Empty;
         Console.WriteLine("Invalid source value: \"" + source + "\"");
         try
         {
            // type initializer will fail here
            Static.Write();
         }
         catch (Exception e)
         {
            Console.WriteLine("Exception: " + e.Message + "\n\t" + e.InnerException.Message);
         }
         // setup valid GUID source value
         source = Guid.Empty.ToString();
         Console.WriteLine("Valid source value: \"" + source + "\"");
         try
         {
            // type initializer should succeed here
            Static.Write();
         }
         catch (Exception e)
         {
            Console.WriteLine("Exception: " + e.Message + "\n\t" + e.InnerException.Message);
         }
         Console.ReadKey();
      }
   }
}

Ok, there’s no database access here but just imagine that the Guid constructor call is the database access attempt. As you can see, the first call simulates that the server is down while at the second call the server is back up. Keeping that in mind the first call should fail while that second one shouldn't. (For those of you not familiar with static constructors: they get executed before the first (static or instance) property access or method call. As such they take care of type initialization.) Let’s take a look at the program output then.

Invalid source value: ""
Exception: The type initializer for 'Static' threw an exception.
        Guid should contain 32 digits with 4 dashes (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx).
Valid source value: "00000000-0000-0000-0000-000000000000"
Exception: The type initializer for 'Static' threw an exception.
        Guid should contain 32 digits with 4 dashes (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx).

Obviously both calls have failed. Why is that so?

It turns out that the static constructors are executed exactly once. If they throw an exception, it gets wrapped as an InnerException of the TypeInitializationException. Any attempts to use this class afterwards don’t cause the constructor to execute again, but just make it throw the same exception once again. Therefore the method call still reports an invalid GUID value (or in my case failed database connection attempt) although the problem has already been remedied. This makes the class effectively unusable within the AppDomain.

The lesson to be learned: no matter what you’re doing in the static constructor, never allow it to throw an exception unless the problem is indeed fatal and you intend to quit the program immediately. In all other cases provide reasonable defaults and handle changed circumstances elsewhere in the code.

You can find some additional technical details in Chris Brumme’s blog entry.

2/24/2006 12:19:47 AM (Central Europe Standard Time, UTC+01:00)  #  Comments [0]

Blog Feeds
RSS 2.0 RSS 2.0
Atom 1.0 ATOM 1.0
Fellow Bloggers
 Andrej Tozon
 Dejan Sarka
 Dusan Zupancic
 Matevz Gacnik
 Miha Markic
Disclaimer
The content of this site are my own personal opinions and do not represent my employer's view in anyway. In addition, my thoughts and opinions often change, and as a weblog is intended to provide a semi-permanent point in time snapshot you should not consider out of date posts to reflect my current thoughts and opinions.

Powered by:
newtelligence dasBlog 1.8.5223.2

© 2008 Damir Arh, M. Sc. Send mail to the author(s)

Microsoft Certified Professional
Currently Reading
Currently Playing
Currently Watching