Archive for the ‘Programming’ Category

Nant xmlpoke whole blocks

Monday, November 16th, 2009

It took me awhile today to use the nant/xmlpoke/xpath to update our copyright message in our application so I’ll document it here.

The xmlpoke documentation explains whole to replace parameters but not children nodes. The simple answer is just define the parent in the xpath.

Thus to update/repalce the copyright string to have the correct current year, in a  resource file (strings.resx) which looks like:

<?xml version="1.0" encoding="utf-8"?>
<root>
  <!-- other stuff -->
  <data name="About_Copyright" xml:space="preserve">
    <value>Copyright © 2008-2009 Company Name.</value>
  </data>
  <!-- more stuff -->
</root>

You would want use this xmlpoke/xpath

<xmlpoke
file="${sourceDir}\Resources\Strings.resx"
xpath="/root/data[@name = 'About_Copyright']/value"
value="Copyright © 2008-${datetime::get-year(datetime::now())} Company Name." />

Simple really (the xpath), but until I got it, it wasn’t.

Cool-stuff™ can be done in Java

Thursday, August 27th, 2009

Baiting title I know, but I’m am a C# fan-boy.

Anyway Shannon shows again that ‘cool-stuff ™ can be done in Java‘ with his newest synth WebGuitar.

SafeArrayTypeMismatchException

Tuesday, August 11th, 2009

We extended our legacy C++ DCOM application last week, and when the developer wrote the C#.Net end to call the new method, we were getting a  System.Runtime.InteropServices.SafeArrayTypeMismatchException.

The developer that had added the method stated it work, and pointed to his Delphi test app that worked happily.

Reviewing the method code it all looked fine. Single stepping through the code there where no problems.

The help for this exception says:

The exception thrown when the type of the incoming SAFEARRAY does not match the type specified in the managed signature.

But as we are dynamically calling the method like this:

objAddType = Type.GetTypeFromProgID("DCOM_OBJECT_NAME.COMPANY_CLASS_A");
objAdd = Activator.CreateInstance(objAddType);

object[] input = {};

object result = objAddType.InvokeMember("MethodName", BindingFlags.InvokeMethod, null, objAdd, input);

There was no was no signature.

This is for this Method:

VARIANT CompanyClassAObject::MethodName(void)
{
    VARIANT vaResult;
    VariantInit(&vaResult);

    SAFEARRAY* sfa = GetSafeArray();

    vaResult.vt = VT_UI1 | VT_ARRAY;
    vaResult.parray = sfa;

    return vaResult;
}

with the body of GetSafeArray looked like:

    SAFEARRAYBOUND sfabounds[1];
    sfabounds[0].lLbound = 0;
    sfabounds[0].cElements = bytes_needed;
    SAFEARRAY *sfa = SafeArrayCreate(VT_I1, 1, sfabounds);
    if(sfa)
    {
        void *data;
        if(SafeArrayAccessData(sfa, &data) == S_OK)
        {
            memcpy(data, buffer, bytes_needed);
            SafeArrayUnaccessData(sfa);

            delete buffer;
            return sfa;
        }
    }

The problem ended up being that the SafeArray is created as VT_I1 type but when it is put into the variant type it was typed as VT_UI1.  So the .Net runtime was picking up the conflict and correctly complaining, and once you know what the error is, the exception message make sense.  Funny that!

Setting the SafeArrayCreate to use VT_UI1 and every thing worked.

When removing columns rebuild your views

Friday, April 3rd, 2009

If remove a column from a table in your Oracle DB, and you have a views that select * from tablename, you need to recreate the view.

I was comparing my old schema and new schema, and had all the correct column changes, and index changes, but was still having some views marked invalid and therefore failing to run.

It was noticed by a co-worker (via the DDL) that the view was still referring to the dropped column.

I had assumed that the code received back from the DB was verbose (every selected item named) because the tools were lazy, but this makes sense once you think about how select * may get compiled by the DB, but can catch you out when just comparing SQL text changes.

Creating Palette based GIFs

Monday, January 26th, 2009

A question was asked on the mailing list (ages ago) about creating 8-bit GIF files.  I proved this code for simple palette based GIFs, so here it is:

using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;

namespace Project
{
    class ProjectMain
    {
        public static void Main()
        {
            GenerateBackgroundImage(Color.AliceBlue, Color.Beige, Color.Cyan, 10, 10, 10, @"c:\image.gif");
        }

        public static void GenerateBackgroundImage(Color leftColour, Color centerColour,
            Color rightColour, int leftWidth, int centerWidth, int rightWidth, string path)
        {

            int width = leftWidth + centerWidth + rightWidth + 2;
            int height = 10;

            using (Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format8bppIndexed))
            {
                Color backColour = Color.White;
                byte idxBackground = 0;
                byte idxLeft = 1;
                byte idxCenter = 2;
                byte idxRight = 3;

                ColorPalette cp = bitmap.Palette;
                cp.Entries[idxBackground] = backColour;
                cp.Entries[idxLeft] = leftColour;
                cp.Entries[idxCenter] = centerColour;
                cp.Entries[idxRight] = rightColour;

                bitmap.Palette = cp;

                fillrect(idxBackground, bitmap, new Rectangle(0, 0, width, height));
                fillrect(idxLeft, bitmap, new Rectangle(0, 0, leftWidth, height));
                fillrect(idxCenter, bitmap, new Rectangle(leftWidth + 1, 0, centerWidth, height));
                fillrect(idxRight, bitmap, new Rectangle(leftWidth + 2 + centerWidth, 0, rightWidth, height));

                bitmap.Save(path, ImageFormat.Gif);
            }
        }

        static void fillrect(byte colorIndex, Bitmap b, Rectangle r)
        {
            BitmapData bmpData = b.LockBits(new Rectangle(0, 0, b.Width, b.Height), ImageLockMode.WriteOnly, b.PixelFormat);

            // Get the address of the first line.
            IntPtr ptr = bmpData.Scan0;

            // Declare an array to hold the bytes of the bitmap.
            // This code is specific to a bitmap with 8 bits index per pixels.
            int bytes = b.Width * b.Height;
            byte[] Values = new byte[bytes];

            // Copy the RGB values into the array.
            Marshal.Copy(ptr, Values, 0, bytes);

            for (int y = r.Top; y < r.Bottom; y++)
            {
                for (int x = r.Left; x < r.Right; x++)
                {
                    Values[(y * b.Width) + x] = colorIndex;
                }
            }

            // Copy the values back to the bitmap
            Marshal.Copy(Values, 0, ptr, bytes);

            // Unlock the bits.
            b.UnlockBits(bmpData);
        }
    }
}

I would change fillrect, to seperate out the locking, and Marshal calls, to CreateTempBuffer, FillTempBuffer, and WriteTempBuffer functions, if you were to use fillrect more than a couple times.  But as it stands, the code is correct after each call.