Jim Rogers

Lives in Baton Rouge, LA, with two dogs, one cat, and one lovely wife. I'm a lead developer for GCR Incorporated.

Katrin and Jim

Month List

Images in SQL

by Jim Jun 16, 2008 9:43 AM

StudbilFirst you gotta get those suckers in there. It's someone else's job to write the admin app, and we aren't at that stage of development yet.

To insert an image file straight into an image or varbinary field:

INSERT Users (UserName, Photo) 
SELECT 'Joe', * FROM OPENROWSET(BULK 'C:\temp\studbil.jpg', SINGLE_BLOB) AS X

Or to update an existing field:

UPDATE Users SET Photo = (
SELECT * FROM OPENROWSET(BULK 'C:\temp\studbil.jpg', SINGLE_BLOB) AS X
)
where ID = 32

Now you might want to check the size of the binary field to see if it matches the file:

SELECT DATALENGTH(Photo) FROM Users

To get the photo out of the database, in C#:

if (row["Photo"] != DBNull.Value)
{
    MemoryStream imgStream = new MemoryStream((byte[])row["Photo"]);

    // According to MSDN, we're supposed to keep the stream open for the lifetime
    // of the image, which we can't do. So copy the original image by constructing
    // a new one.
    user.Photo = new Bitmap(Bitmap.FromStream(imgStream));

    imgStream.Close();
}

Many people forget the "keeping the stream open" issue when loading images, and in most cases it won't bite you. But in the case of my WCF service, I get this error if I close the stream and then try to serialize the image:

System.Runtime.InteropServices.ExternalException: A generic error occurred in GDI+. 
 at System.Drawing.Image.Save(Stream stream, ImageCodecInfo encoder, 
EncoderParameters encoderParams) 
 at System.Drawing.Image.Save(MemoryStream stream) 
 at System.Drawing.Image.System.Runtime.Serialization.ISerializable.GetObjectData(
SerializationInfo si, StreamingContext context) 
 at System.Runtime.Serialization.XmlObjectSerializerWriteContext.WriteISerializable(
XmlWriterDelegator xmlWriter, ISerializable obj) 
 at WriteBitmapToXml(XmlWriterDelegator , Object , XmlObjectSerializerWriteContext , 
ClassDataContract ) 
. . . 

Tags:

Code

Failing a Build

by Jim Jun 15, 2008 12:28 PM

Batch files are one of those things I work with so infrequently that I have to research some aspect of them every time.

Today's problem: How do I intentionally fail the build in Visual Studio when my utility program fails?

To bubble an error from a command-line utility, return an error code from the Main() method:

static int Main(string[] args)
{
    int retval = 0;     // success code

    try
    {
        ...
    }
    catch (Exception ex)
    {
        // Return an error code so the caller knows there was a problem
        retval = 1;
        ...
    }
    return retval;
}

If the pre- or postbuild event called the utility directly, you're done; the build will fail.

But if a batch file called it, you need to catch the error in the batch file and bubble it back up:

MyUtility.exe %arg1% %arg2%
:: In case of error, bubble up to visual studio
IF ERRORLEVEL 1 EXIT 1

That link will also explain how to catch different error codes, in case you need the batch file to do more intelligent processing.

It's also possible to mess around with how Visual Studio handles error codes.

Viewbox Template

by Jim Jun 12, 2008 8:18 AM

The Visual Studio designer doesn't show the contents of a viewbox. I've got entire pages in viewboxes, so this is inconvenient...

I've just realized that this problem can be solved by creating a template for the page, in App.xaml:

<Style x:Key="viewboxedPage" TargetType="Page">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="Page" >
                <Viewbox Stretch="Fill">
                    <ContentPresenter
                        Content="{TemplateBinding ContentControl.Content}" 
                        ContentTemplate="{TemplateBinding ContentControl.ContentTemplate}" 
                        Margin="{TemplateBinding Control.Padding}" 
                        SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}"
                        />
                </Viewbox>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

The designer doesn't try to render a dynamic resource template at design time, so you're free to edit the contents of the page. Presumably this would work with user controls or other containers that use a viewbox.

Tags:

Code

WCF Services and SSL

by Jim Jun 05, 2008 6:32 AM

Your WCF service's web.config settings and the IIS application settings must remain in sync for SSL to work correctly.

Setting the endpoint address to https doesn't force clients to use SSL:

<endpoint address="https://machine.domain.com/path/Application.svc"

To require SSL in the web.config, you'll want to change the behavior:

 

<behaviors>
    <serviceBehaviors>
        <behavior name="generalBehaviorConfiguration">
            <serviceMetadata httpsGetEnabled="true" />

At this point if the client tries to access with https, all is well - but if they try with https, they get a somewhat confusing error:

The resource cannot be found

Turning on "Require SSL" in the IIS settings for the site will result in the client getting a 403 error, which makes more sense.

image

Now if you have followed the above steps to require SSL, then Visual Studio won't immediately find the service reference when you try to add it (or update, if you've reconfigured.) It will try to use http.

The solution is simple enough: In the Add Service Reference dialog, discover the services and select the one you wish to add. Then add an 's' to the http in the Address box.

 

image A related note:

I've been deleting the .disco, .wsdl, and .xsd files from my project after adding and updating service references. They aren't needed to compile the project, and we had issues with source control (Team Foundation Server) with multiple developers updating the service references.

To see these you'll need to turn on the "show all files" option in solution explorer.

Favorizer Source

by Jim Jun 04, 2008 6:12 AM

FavScreen I recently received an email asking me to publish the source for my Favorizer program. I don't think it works correctly in Vista, and I'm not using or maintaining it anymore. So here it is:

Favorizer Source (Zip) - Visual Studio 2005 Solution

The primary interesting thing in the code, and the main reason I wrote the program to begin with, is its ability to determine the ordering of favorites in Internet Explorer. This order is encoded into binary information in the registry, which I partially reverse-engineered:

public class FavHeader : WritableObject
{
    public int int1;       // 8 for root...
    public short lenData;  // (total length - 8) bytes?
    public int int2;
    public int int3;
    public short short4;
    public int count;       // number of items in the data
}

public class FavItem : WritableObject
{
    public int int4;        // Size of item? ... or related to same
    public short rank;      // 0-based index of this item under the parent
    public int int5;
    public short int6;
    public short int7;
    public int int8;
    public short int9;
    public short int10;
    public short int11;
    public string shortname;// DOS name, up to 8 chars
    public byte[] between;    // Miscellaneous stuff
    public string name;        // Full name of folder or link
    public int int13;
    public int int14;
    
    public FavItem()
    {
        between = new byte[20];
    }
}

As you can see, I guessed at the structure of the data, but have no idea what most of it means. I think there are actually a couple of strangely formatted dates in there. The important thing was figuring out how to determine the boundaries, and which bytes represented the order of the items.

The other potentially useful chunk of code in there concerns loading of favicons. Doing this in a generic and failsafe way for a broad range of sites is surprisingly difficult, because of all the sites that implement it incorrectly. They return the wrong content type, or the wrong image type, or say they're returning an image while sending 404 text.

Tags:

Code