Tom Goff's .Net Musings

Tidbits of information regarding .Net, C#, and SQL Server.

Archive for the ‘Gotcha’ Category

Dependency Property Annoyance

leave a comment »

While I’m in the blogging mood, can you spot the bug with the code below?

public static readonly DependencyProperty MyCoolProperty = DependencyProperty.Register("MyCool",
    typeof(double),
    typeof(MyCoolObject),
    new FrameworkPropertyMetadata(0));

It’s not an obvious problem and unless you’re really into WPF it’s even less obvious. The problem is that when setting the default value of 0 (zero). The framework rightfully assumes it should be an int, but it will throw an exception when it tries to assign it to the associated dependency property during runtime. Why? Because it cannot implicitly convert the int type to a double type.To fix it you need to declare the dependency property like (notice the 0.0 in place of the 0):

public static readonly DependencyProperty MyCoolProperty = DependencyProperty.Register("MyCool",
    typeof(double),
    typeof(MyCoolObject),
    new FrameworkPropertyMetadata(0.0));

Written by Tom

April 4, 2008 at 11:53 am

Posted in .Net, C#, Gotcha, WPF

The Catch with VS 2008 Multi-Targeting Support

leave a comment »

With the recent release of Visual Studio 2008, I have been trying to tinker with the new features when I have time. One of the features I especially like is the Multi-Targeting Support. You may have read about it before, but if not check out this blog. Using this feature, I could then benefit from the bug fixes, speed improvements, pretty interface changes, etc in Visual Studio 2008 with only minor changes to my applications. Unfortunately, there is a small catch.

If you read Scott Hanselman’s blog, then you may have read this entry. In order to install Visual Studio 2008, you obviously must install .Net 3.5 (which is all part of the Visual Studio setup). In order to install .Net 3.5, you must install .Net 3.0 SP1 and .Net 2.0 SP1. As Scott describes, there are new properties/methods that are added to the .Net 2.0 framework as part of SP1.

So if you develop an application that targets .Net 2.0 in Visual Studio 2008 and use one of the new methods or properties, then obviously your application will not run on a computer with .Net 2.0 RTM. Since the assembly versions from the RTM and SP1 are the same, your application will load the RTM assemblies and then throw an exception when it can’t find the required method or property. If you do not use any of the new properties or methods, then your application will run on a computer with .Net 2.0 RTM. In addition, you could simply apply the .Net 2.0 SP1 to the target computers.

There are a few ways to determine if a property, method, or class is new. The first is obviously the documentation. For example, the INotifyPropertyChanging interface is new to .Net 2.0 SP1 and you can see that .Net 2.0 is not included in the “Version Information” section at the bottom. The second option is to use a new optional FxCop rule (as described here) to flag items. Finally, you can test your assemblies on a computer with .Net 2.0 RTM. This last step really requires that you perform full test coverage of your assembly though.

Written by Tom

November 27, 2007 at 3:33 pm

Posted in .Net, C#, Gotcha, Visual Studio

String.IsNullOrEmpty Issue & Solution

with 2 comments

I’m sure everyone has heard of the static IsNullOrEmpty[^] method that is available in the String class. Although, you may not have heard about the JIT optimizer bug[^] relating to that method. Essentially, the JIT optimizer is generating “optimized” code that accesses a null variable, thus throwing an exception. You may be tempted to write your own version of this method to get around the bug, like so:

public class StringHelper {
    public static Boolean IsNullOrEmpty(String x) {
        return (null == x || 0 == x.Length);
    }
}

Unfortunately, the JIT optimizer will generate the same null access exception with this method. There is a solution that relies on the fact[^] that the JIT optimizer (sometimes?) skips try blocks. Meaning it does not apply it’s optimizations to the code inside the try block. If we change our custom version of IsNullOrEmpty as shown below, then it will no longer generate the offending code or the exception.

public class StringHelper {
    public static Boolean IsNullOrEmpty(String x) {
        try {
            return (null == x || 0 == x.Length);
        }
        catch (Exception) {
            throw;
        }
    }
}

Although, this may be too much trouble for a method that is suppose to be a convenience. Microsoft has said[^] that this issue is fixed in the next version of Visual Studio.

Written by Tom

September 30, 2007 at 4:58 pm

Posted in .Net, C#, Gotcha, Visual Studio

XML Serialization Sorrows

with 11 comments

One of the features of our flagship product allows the user to save the results from a T-SQL script (run against one or more SQL Server databases) to a file. These results are stored in XML and can be re-opened and viewed by the user. One problem we have run into is that the XML standard does not allow certain characters[^]. For example, the null (0x00) character is not technically allowed even when encoded as “�” in the XML file.

Before I coded a work-around or fix, I wanted to understand where the problem data was coming from. In one instance, the null character was clearly coming from a string (or varchar) column. The SELECT statement was:

SELECT TOP 1 filename FROM sysaltfiles WITH (NOLOCK)

It turned out that the filename column included a trailing null character, but only on SQL Server 2000. I was able to verify this with Microsoft’s Query Analzyer.

There was another instance of an invalid character showing up, but this time the SELECT statement was:

SELECT password FROM syslogins WITH (NOLOCK)

It appears that syslogins is a view on top of sysxlogins, which defines the password column as a varbinary. When syslogins selects the password from sysxlogins it converts it as-is to a varchar. This produces the invalid characters, because the binary data cannot be converted in this manner.

Beyond these two tables a user can still write a valid SELECT statement which would produce an invalid character like so:

SELECT CHAR(0) AS InvalidChar

Now, I’ve been calling the characters “invalid” when really they are perfectly valid. SQL Server, .Net, ADO.Net, and all the controls used to display this data perfectly supports these characters. Even more, when saving these characters the XML serializer would properly encode them using their hexadecimal value (e.g. “�” for the null character). The problem was with the XML deserialization process.

When loading an XML file with one of these invalid characters, an InvalidOperationException[^] would be thrown with the following message:

There is an error in XML document (<Line>, <Column>). 

This exception had an inner exception of type XmlException[^] and the following message:

‘.’, hexadecimal value 0x00, is an invalid character. Line <Line>, position <Column>.

The code used to deserialize the file was similar to the following:

TestObject testObject = null; 
if (true == File.Exists(Form1.fileName)) { 
    XmlSerializer xs = null; 
    TextReader tr = null; 

    try { 
        xs = new XmlSerializer(typeof(TestObject)); 
        tr = new StreamReader(Form1.fileName); 
        testObject = xs.Deserialize(tr) as TestObject; 
    } 
    catch (Exception ex) { 
        //... Exception caught here ... 
    } 
    finally { 
        if (null != tr) 
            tr.Close(); 
    } 
}

The solution was very simple, but not obvious. Simply wrapping a XmlTextReader[^] around the StreamReader[^] allows the code to properly decode the invalid characters. This change is shown here:

TestObject testObject = null; 
if (true == File.Exists(Form1.fileName)) { 
    XmlSerializer xs = null; 
    TextReader tr = null; 

    try { 
        xs = new XmlSerializer(typeof(TestObject)); 
        tr = new StreamReader(Form1.fileName); 

        // Wrap stream with an XmlTextReader so bad chars are accepted 
        XmlTextReader xtr = new XmlTextReader(tr); 
        testObject = xs.Deserialize(xtr) as TestObject; 
    } 
    catch (Exception ex) { 
        // ... No exception thrown ... 
    } 
    finally { 
        if (null != tr) 
            tr.Close(); 
    } 
}

I’m unsure why the XML standard doesn’t allow all characters (even the null character, when properly encoded), but I’m sure they had/have their reasons. The only down side is that XML files that contain these invalid characters will still be considered invalid by other applications.

I’ve put together a sample project[^] that demonstrates the XML portion of this blog.

Written by Tom

August 23, 2007 at 1:59 pm

Posted in .Net, Ado.Net, C#, Gotcha, SQL Server, Xml

Wanna Crash Visual Studio?

with one comment

I believe that I found an interesting bug in Visual Studio. I was designing a progress dialog for use in our application. I wanted the dialog to be threaded, so the user could cancel the operation or continue to work in our application.

Since there were going to be a handful of “operations” that would require the progress dialog, I was going to encapsulate most of the functionality in a base form. Each operation (which may or may not require user input) would then have it’s own derived form.

NOTE: I’ve put together a sample project[^] that reproduces the issue so you can follow along if you like.

If you open the sample project in VS and run it, you will see the following window:

If you click the execute button, then you will get the following confirmation dialog (which is presented by the progress dialog):

If you click no, then the progress dialog is dismissed and the “operation” is not executed. If you click yes, then the operation will be performed and you will see the following:

So, the code works great, but doesn’t work so well in the VS designer. The progress dialog is made up of two forms: BaseDialog and DerivedDialog. The former provides the bulk of the functionality and the latter does the actual “operation”.

If you open BaseDialog in the VS designer, then all is well. If you try to open DerivedDialog in the VS designer, then you will see the same “Confirm” message box you see during execution. After you click the “Yes” or “No” button, then VS will crash.

Keep in mind that all of the code that shows the message box is located in BaseDialog. So this means that VS must be suppressing this code when the BaseDialog is loaded in the designer, but is not suppressing it when derived dialogs are loaded in the designer.

We can fix this by wrapping the offending code in an “if” statement that verifies that the DesignMode[^] property of the form is false. This means that the code will not be executed if the form is being loaded in the designer.

Written by Tom

July 4, 2007 at 10:36 am

Posted in Gotcha, Visual Studio

Custom Setup Action Woes

with 3 comments

We use custom setup actions in our Visual Studio Setup project in order to create shortcuts to our application on the Quick Launch toolbar and the Desktop, if the user so chooses. The managed custom action is easy to get setup and running, but troubleshooting issues can be a real pain.

NOTE: If you don’t know what a custom action is then check out this link[^]

The main source of pain is the fact that the errors only occur at the very end of the installation of the application. This means that I have to build an installer every time I want to try to test a “fix”. When diagnosing the issue, there are a few areas to check for information on the problem.

Generally, the first thing to do is enable logging for the MSI. If you know that it’s a problem with your custom action, then this probably won’t help. Next, it’s best to verify that the assembly holding your custom action does not have any binding issues. To determine this you need to use fuslogvw[^]. If your assembly cannot load because of a missing reference, then this will point out the problem. The latest technique in my arsenal is to use installutil[^]. Let me explain how this helps.

The message box below is one error I was receiving. Again, this error occurred during installation and would force a rollback of the installation. So, once I clicked OK then the installed files would be removed. There is generally a second dialog after this with the same information because it is trying to perform the rollback of the custom action. In order to use installutil, I would leave the dialog open so the offending files would be (temporarily) left on my system.

I’m sure we have all seen this error in the Visual Studio designer. In fact, when searching for a solution to this issue, all of the sites I found dealt with the designer. Anyway, I used installutil to “re-run” my custom install. Since the files were still on my system, I could just open command-prompt  (with the VS directories in the PATH) to my application’s folder and type the following:

C:...>installutil /logtoconsole=true /showcallstack CustomActionTest.exe

 This allowed me to see the callstack of the exception that was being thrown:

System.Reflection.ReflectionTypeLoadException: Unable to load one or more 
of the requested types. Retrieve the LoaderExceptions property for 
more information. 
at System.Reflection.Module.GetTypesInternal(StackCrawlMark& stackMark) 
at System.Reflection.Module.GetTypes() 
at System.Configuration.Install.AssemblyInstaller.GetInstallerTypes(Assembly assem) 
at System.Configuration.Install.AssemblyInstaller.InitializeFromAssembly()

Now we know the type of exception that is being thrown and where it’s being thrown from. The first thing to note here is that the ReflectionTypeLoadException[^] class has a LoaderExceptions property. This property returns an  “array of exceptions thrown by the class loader.” What I really wanted was the information in the LoaderExceptions property. Unfortunately, this information is not logged or reported anywhere. So my only option was to build my own application that could reproduce the exception.

Luckily, the code that threw the exception was simply opening the assembly, iterating over it’s modules, then iterating over the types in each module. The basic code is shown here:

    Module[] modules = assembly.GetModules(); 
    foreach (Module module in modules) { 
        Type[] types = module.GetTypes(); 
        // ... 
    }

After building an application that loaded my assembly and performed the code above, I was able to view the contents of the LoaderExceptions property. It turns out that some old, unfinished, and unused code was causing the problem. Specifically, I had been building P/Invoke calls to the Windows shell interface IShellFolder[^]. This interface uses a structure with a union called STRRET[^].

The quick conversion of STRET to C# equates to:

    [StructLayout(LayoutKind.Explicit)] 
    public struct STRRET { 
        [FieldOffset(0)] 
        public Int32 uType;  

        [FieldOffset(4)] 
        public IntPtr pOleStr;  

        [FieldOffset(4)] 
        public Int32 uOffset;  

        [FieldOffset(4)] 
        public IntPtr cStr; 
    }

At the time, I was trying to tweak the signature to use a .Net char array, like so:

    [StructLayout(LayoutKind.Explicit)] 
    public struct STRRET { 
        [FieldOffset(0)] 
        public Int32 uType;  

        [FieldOffset(4)] 
        public IntPtr pOleStr;  

        [FieldOffset(4)] 
        public Int32 uOffset;  

        [FieldOffset(4), MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] 
        public Char[] cStr; 
    }

Now as I said the code was unfinished and was not used anywhere in our application. In addition, the code compiles without any warnings or errors. Yet, this code completely disables the ability for my assembly to have it’s types reflected. I’m guessing this is an issue with the C# compiler, since it does not report this as invalid.

Anyway, I’ve put together a sample project[^] that illustrates all the points talked about above.

Written by Tom

May 24, 2007 at 9:18 am

Posted in .Net, C#, Gotcha

Double Initialization

leave a comment »

I was playing around with FXCop and ran into an interesting rule it was reporting on my code. The rule is called DoNotInitializeUnnecessarily, and reports a warning when you initialize a field member to it’s “default value”. The default value depends on the data type: zero (0) for integers, false for Booleans, null for reference types, etc. For example, the default value for the String field below is null, so there is no reason to explicitly set it to null:

    public class Class1 { 
        /// <summary> 
        /// Holds my string. 
        /// </summary> 
        private String myString = null; 

        /// <summary> 
        /// Gets my string. 
        /// </summary> 
        /// <value>My string.</value> 
        public String MyString { 
            get { 
                return this.myString; 
            } 
        } 
    }

Now, this isn’t much of a problem because this will get optimized out of release builds. Unfortunately, I almost always initialize Strings to String.Empty. So if I write:

    public class Class1 { 
        /// <summary> 
        /// Holds my string. 
        /// </summary> 
        private String myString = String.Empty; 

        /// <summary> 
        /// Gets my string. 
        /// </summary> 
        /// <value>My string.</value> 
        public String MyString { 
            get { 
                return this.myString; 
            } 
        } 
    }

Then the initialization will occur, regardless of whether it’s a release build. Obviously in this example, it’s not a problem because we want the string to be non-null. But, if we were to write:

    public class Class1 { 
        /// <summary> 
        /// Initializes a new instance of the <see cref="Class1"/> class. 
        /// </summary> 
        /// <param name="myString">My string.</param> 
        public Class1(String myString) { 
            this.myString = myString ?? String.Empty; 
        } 

        /// <summary> 
        /// Holds my string. 
        /// </summary> 
        private String myString = String.Empty; 

        /// <summary> 
        /// Gets my string. 
        /// </summary> 
        /// <value>My string.</value> 
        public String MyString { 
            get { 
                return this.myString; 
            } 
        } 
    }

Then the myString field will be initialized twice. First time, the field initializer sets it to String.Empty. Then in the constructor it’s initialized to the given parameter if it’s non-null, otherwise it’s set to String.Empty again.

To remove the double initialization, we need to remove the field initializer. I doubt that there are many cases were this would result in a noticeable speed improvement. Although, when things are running in long loops every little bit helps.

Things like this generally dictate how I will write code. I will probably avoid field initializers now, just so I don’t have to worry about double, or potentially triple, initialization. Field initializers were just a convenient way to set fields, but I didn’t realize there was a potential (albeit small) problem.

Written by Tom

May 11, 2007 at 12:54 pm

Posted in C#, Gotcha