April 5, 2010

Too Many Temp Files!

Filed under: .Net — Jeff @ April 5, 2010 1:21 pm

Today my work computer started behaving badly…

image 

and SQL Server Management Console…

image

Nice error… “The file exists.”  Fortunately the details were actually helpful…

image

Calls to “GetTempFileName “ are failing and the word on the Intertubes is that will happen if you end up with > 65,000 files in your temp folder.

image

Which, apparently, I have accumulated.  Cleaning those out and everything works wonderfully again.

FAIL to all the developers of the software I use that are leaving all these files here…

February 10, 2010

DEP: The Return

Filed under: .Net — Jeff @ February 10, 2010 3:26 pm

We just migrated our project to Visual Studio 2008 today and… it stopped working.  Our application is a VB.NET/C# hybrid that makes use of a number of legacy ActiveX controls.  When we ran the freshly migrated project the ActiveX controls would fail with “Invalid Access to Memory Location” errors.

 image

This is a side effect of the C# compiler now generating executables with the NXCOMPAT bit set (with no option in the IDE to turn that off).  This setting on the EXE enabled DEP (Data Execution Protection) on our program which prevents the legacy DLLs from doing what they need to do.

We’ve encountered this before here with our build machine and were able to resolve it by tweaking the build script.  Unfortunately the IDE was now failing and that’s more complicated.

On of our developers came up with a fix:

Turn of NXCOMPAT bit on build output

There is a utility called “editbin” that lets you modify the EXE and turn the NXCOMPAT bit off.  You can add it to the post-build events and that fixes the generated EXEs.  Unfortunately, the application still will not run under the IDE because it’s inheriting DEP from the vshost process.

image 

Turn off NXCOMPAT bit on vshost32.exe

To make the application run under the IDE we can turn of NXCOMPAT on the vshost32 executable using “editbin”.

image

At this point the application seems to run like it always did under the IDE.

<grumble>

October 14, 2009

Self Extracting .NET Program Wrapper

Filed under: .Net — Jeff @ October 14, 2009 7:29 am

I posted a short little how-to on bundling up a .NET program in a NSIS self-extracting installer to make writing .NET based utilities (single EXE with no installer) a little bit nicer.

It handles:

  • Unpacking to a temporary directory, invoking the program, and cleaning up when it’s done
  • Installing .NET 3 if it’s not on the machine already
  • Passing through command line parameters to the .NET app

Article Here

September 25, 2009

Windows Update Killed Our Build

Filed under: .Net — Jeff @ October 9, 2009 2:09 pm

Our product build machine is running Windows XP.  On September 1st we ran Windows update which installed 28 updates (we were a bit behind) on that machine.  From that point forward builds on that machine no longer run on Windows Vista machines.

KB970653, KB970653, KB970653, KB890830, KB890830, KB973540, KB973354, KB973507, KB973507, KB973869, KB971633, KB971633, KB951847, KB973346, KB956744, KB971557, KB971557, KB961371, KB970483, KB960859

image

This error is encountered when loading any of our 3rd party Active X controls and is triggered by Digital Execution Protection (DEP).  If I turn off DEP on my machine completely the build works just fine (don’t do this though, it makes a mess).

c:\> bcdedit.exe /set nx AlwaysOff

Also curious is that, in the build immediately prior to the update, I can go into “System Properties / Advanced / Performance / Data Execution Prevention” and add an exclusion for our program binary.  For the build immediately after the updates I get the following:

image

From this forum post it looks like you would not be able to turn off DEP if the EXE is one of the following:

There are three possible causes for why you cannot add the app to the
exceptions list:
1.) This is a 64-bit application.
2.) The application is in the Windows directory.
3.) The application has been compiled for Vista and, therefore, DEP is
enforced for it.

Our application is compiled for Any-CPU and is not in the Windows directory and I have no idea what a “Vista” build is.

After way too much searching I came across this article that states:

The C# compiler in Visual Studio 2008 and the .NET 3.5 Framework (csc.exe) is now generating PE files with the NXCOMPAT bit set. What is that bit and who cares, you ask? You may very well care if your application interops with native binaries or exposes a plugin model to 3rd parties.

The .NET 2.0 and VS 2005 compilers are also affected

The fix seems to be to turn off the NXCOMPAT bit for our application until we can get rid of our ActiveX dependencies.

Naturally VC++ includes a setting for turning of this NXCOMPAT feature but C# and VB.NET do not:

image

We can execute the following command on our EXE after the build process and it seems to fix things up for us.

c:\> editbin.exe /NXCOMPAT:NO <insert EXE here>

Unfortunately our EXE is strong named because we use ClickOnce.  So doing this after the build invalidates our signed executable.

image

So now we need to turn resign the EXE after doing this.

c:\> sn –Ra <exe> <keyfile>

Trying to add editbin.exe to a post build action raised some error code that isn’t documented anywhere that I could find.  Grumble…

I settled on adding the following to our MSBuild script and that seems to have worked… for now.

<!– NX Hack –>
<Exec Command="editbin /NXCOMPAT:NO &amp;quot;$(BinDir)\Program.exe&amp;quot;" />
<Exec Command="sn -Ra &amp;quot;$(BinDir)\Program.exe&amp;quot; &amp;quot;$(MSBuildProjectDirectory)\Port\keypair.snk&amp;quot;"  />

That was a lot of work rummaging around to find this.  Why Microsoft would sneak this change into a hotfix and is beyond me.  Surely Visual Studio can tell if the assembly is using ActiveX controls and could, at least, warn me that it is going to break my build.  Go Microsoft!

October 24, 2008

Connecting to Oracle is slow on ADO.NET under Vista

Filed under: .Net — Jeff @ October 24, 2008 12:13 pm

Our application uses the “System.Data.OracleClient” library to connect to our Oracle database.  Something like this:

OracleConnection connection = new OracleConnection(     "Data Source=prod8a;User Id=bugnav;Password=bugnav");
DateTime startTime = DateTime.Now;
connection.Open();
Console.WriteLine(DateTime.Now - startTime);

Normally code like this would connect to Oracle in WELL under one second.  However, under Vista, the first time I run this it takes 12 seconds!  Subsequent executions are sub-second but, if I wait 60 seconds, the following connections are back up to 12 seconds.  Very odd!

It turns out that I see this behaviour if connection pooling is enabled (and it is my default) or if the “Min Pool Size” is not specified in the connection string. The following two snippets work perfectly.

OracleConnection connection = new OracleConnection(     "Data Source=prod8a;User Id=bugnav;Password=bugnav;Pooling=false");
DateTime startTime = DateTime.Now;
connection.Open();
Console.WriteLine(DateTime.Now - startTime);
OracleConnection connection = new OracleConnection(     "Data Source=prod8a;User Id=bugnav;Password=bugnav;Min Pool Size=10");
DateTime startTime = DateTime.Now;
connection.Open();
Console.WriteLine(DateTime.Now - startTime);

I have no idea why this is happening but at least it`s easy enough to work around.

June 7, 2007

Log4net?

Filed under: .Net — Jeff @ June 7, 2007 6:45 am

Just playing with Log4Net from the Apache project and I’m liking it. It’s a very configurable and sensible looking logging framework for .NET applications.

Sample configuration:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net" />
  </configSections>

  <log4net>

    <root>
      <level value="WARN" />
      <appender-ref ref="LogFileAppender" />
      <appender-ref ref="ConsoleAppender" />
    </root>

    <logger name="ConsoleApplication1.Program">
      <level value="DEBUG" />
    </logger>

    <appender name="LogFileAppender" type="log4net.Appender.FileAppender" >
      <param name="File" value="${APPDATA}\\Test App\\log-file.txt" />
      <param name="AppendToFile" value="true" />
      <layout type="log4net.Layout.PatternLayout">
        <param name="ConversionPattern" value="%d [%t] %-5p %c [%x] <%X{auth}> - %m%n" />
      </layout>
    </appender>

    <appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender" >
      <layout type="log4net.Layout.PatternLayout">
        <param name="ConversionPattern" value="%d [%t] %-5p %c [%x] <%X{auth}> - %m%n" />
      </layout>
    </appender>

  </log4net>
</configuration>

And the sample program:

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

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            log4net.Config.DOMConfigurator.Configure();
            log4net.ILog log = log4net.LogManager.GetLogger(typeof(Program));
            log.Error("An Error");
            log.Warn("An Warn");
            log.Debug("An Debug Message");
            Console.ReadLine();
        }
    }
}

What I like about this setup is that you can normally let your program just log warnings and errors to the default log file (using the “root” configuration) but for certain classes you can easily flip them, at run time, to log a higher level of detail.

June 6, 2007

Updating Version Numbers for all Projects in a Solution

Filed under: .Net — Jeff @ June 6, 2007 8:26 am

As part of our build scripts we need to update the version number of all projects within a solution. I couldn’t find an obvious way to do this so I wrote this script in Python to parse a solution, find the associated projects, find their AssemblyInfo.* files and update them. Kind of a crude hack but seems to work well enough.

import os
import glob
import string
import re
import sys

class SolutionVersionUpdater:
    def __init__(self, path, solutionFile):
        self._path = path
        self._solutionFile = solutionFile

    def _getProjects(self):
        out = []
        rProject = re.compile('^Project.*?,\s*\"(.*?)\".*')
        f = open(os.path.join(self._path, self._solutionFile), "r")
        for ln in f:
            match = rProject.match(ln)
            if match:
                if os.path.splitext(match.groups()[0])[1] in ('.csproj','.vbproj'):
                    out.append(match.groups()[0])
        return out

    def updateProject(self, projectFile, version):
        print "Updating project:", projectFile
        if os.path.splitext(projectFile)[1] == '.vbproj':
            self._updateVBProject(projectFile, version)
        if os.path.splitext(projectFile)[1] == '.csproj':
            self._updateCSProject(projectFile, version)

    def _updateVBProject(self, projectFile, version):
        rAssemblyInfo = re.compile('.*<compile include=\"(.*?AssemblyInfo.vb)\"\s+/>.*',
            re.MULTILINE | re.DOTALL | re.IGNORECASE)
        projectData = open(projectFile,'r').read()
        match = rAssemblyInfo.match(projectData)
        if not match:
            print " - no AssemblyInfo"
            return
        assemblyInfoPath = os.path.join(os.path.dirname(projectFile), match.groups()[0])

        rVersion = re.compile('<assembly: assemblyversion\(\".*?\"\)>', re.IGNORECASE)

        f = open(assemblyInfoPath,'r')
        assemblyInfoData = f.read()
        f.close()

        f = open(assemblyInfoPath,'w')
        for ln in assemblyInfoData.split('\n'):
            if rVersion.match(ln.strip()):
                f.write('<Assembly: AssemblyVersion("%s")>\n' % version)
            else:
                f.write(ln + '\n')
        f.close()

        print " - Updated ", assemblyInfoPath

    def _updateCSProject(self, projectFile, version):
        rAssemblyInfo = re.compile('.*<compile include=\"(.*?AssemblyInfo.cs)\"\s+/>.*',
            re.MULTILINE | re.DOTALL | re.IGNORECASE)
        projectData = open(projectFile,'r').read()
        match = rAssemblyInfo.match(projectData)
        if not match:
            print " - no AssemblyInfo"
            return
        assemblyInfoPath = os.path.join(os.path.dirname(projectFile), match.groups()[0])

        rVersion = re.compile('\[assembly: assemblyversion\(\".*?\"\)\]', re.IGNORECASE)
        rFVersion = re.compile('\[assembly: assemblyfileversion\(\".*?\"\)\]', re.IGNORECASE)

        f = open(assemblyInfoPath,'r')
        assemblyInfoData = f.read()
        f.close()

        f = open(assemblyInfoPath,'w')
        for ln in assemblyInfoData.split('\n'):
            if rVersion.match(ln.strip()):
                f.write('[assembly: AssemblyVersion("%s")]\n' % version)
            elif rFVersion.match(ln.strip()):
                f.write('[assembly: AssemblyFileVersion("%s")]\n' % version)
            else:
                f.write(ln + '\n')
        f.close()

        print " - Updated ", assemblyInfoPath

    def setVersion(self, version):
        oldPath = os.getcwd()
        os.chdir(self._path)

        for project in self._getProjects():
            self.updateProject(os.path.join(self._path, project), version)

        os.chdir(oldPath)

if __name__=='__main__':
    path = os.getcwd()
    project = sys.argv[1]
    version = sys.argv[2]

    print project

    s = SolutionVersionUpdater(path, project)
    s.setVersion(version)

We call the script from our MSBUILD script (invoked from Cruise Control) like so:

 <Target Name="CCLabel">
    <Exec ContinueOnError="false"
          Command="c:\python25\python d:\build\updateAssemblyVersion.py AfeNav_Net.sln $(CCNetLabel)"
          WorkingDirectory="$(MSBuildProjectDirectory)" />
    <!--
    <UpdateAssemblyInfoTask SolutionFile="AfeNav_net.sln" FullVersionString="$(CCNetLabel)" />
    -->
  </Target>

May 4, 2007

VB6 to VB.NET Conversion

Filed under: .Net — Jeff @ May 4, 2007 12:12 pm

We’re converting our fairly large VB6 project to VB.NET here at work. The eventual target is a re-write in C# but the first phase of that is to move all the code to VB.NET using the VB conversion wizard so that we can start refactoring bits and pieces using C# without relying on interop. Interop scares me. I’m not sure why.

The conversion wizard created a zillion bugs which we expected. We’ve had to hand tweak a LOT of code to even get the project compiling. But now we are getting into the weird stuff. Specifically there is a lot of strange stuff surrounding the UI. I thought I’d document it here for several reasons.

  1. It annoys me. I like ranting :)
  2. Someone else might have this problem and this might save them some time
  3. Sometimes people read my posts and explain why this stuff works the way it does. I’m very curious.

Issue #1 – Arial?!

After running the conversion we noticed a lot of the text on the dialogs was really ugly. Letters would butt together in some places and have goofy gaps in others. It turns out the VB.NET conversion wizard takes the default 8pt MS Sans Serif font from VB6 and turns it to a 8pt Arial. This is weird because the default font in .NET is 8pt MS Sans Serif so the conversion tool goes through and hard codes Arial on pretty much every control in the project.

Luckily this was fairly easy to fix. A simple regular expression search and replace across all the .Designer.vb files to delete lines with ‘.Font = “Arial….”‘ in them.

Issue #2 – The Widening Fonts

Another VERY annoying issue was that in the VB.NET designer we would create a label or checkbox with some text on it and size it accordingly. When we ran the project the font width would change ever so slightly and sometimes cause words to be wrapped. The result was words were pretty much randomly being cut off the end of our controls.

We could have just made the controls a tad wider but that’s not a very good fix. We have a lot of controls and having to run the program just to check your control size is stupid.

I spent a bunch of time making simplified projects in VB6, porting them to .NET and comparing them to projects (file level diffing) written from scratch in .NET and eventually found what was causing this.

The following image is an overlay of a screenshot of the form in the VB.NET Designer and a screenshot of the same form at run-time. Notice how the font is slightly wider in the run-time version.

Overlay of form in designer mode and run-time.

It turns out the resolution for this is to check off the “Enable application framework” button in the project properties. This adds a new class “Application.Designer.vb” that contains a very small amount of code and none of that code looks like it should have anything to do with font sizes but it does.

How does that make any sense?

Issue #3 – The stubborn Flexgrid

Another issue was we have a form with a flexgrid on it. This flexgrid is an old ActiveX version wrapped in .NET code. Not ideal but should do the job until we can replace with a native .NET control.

Unfortunately on this form we would make changes to the size of the control. Save. Reload the file and it would be right back to where it was.

We tried all sorts of things. We confirmed that the .Designer.vb file did reflect the changes in control size but as soon as you reloaded the form the control would be back to where it was.

It turns out there is a block of stuff in the form’s resX file called “OcxState”. This is a big blob of base-64 encoded data. No idea what’s really in there. As an experiment I just tried deleting that data and reloading the form and all of a sudden it works. The next time we saved the form it rewrote a blob of “OcxState” to the resX file but this time it did not interfere with the control sizing made in the designer.

I’m not sure what data was in that OcxState but hopefully we aren’t losing anything by deleting it. We haven’t come up with any other way around this.

Issue #4 – The resizing Forms

All our MDI child forms were having problems. These child forms are usually resizable and we’re taking advantage of the nifty control anchoring built into Windows Forms. Unfortunately, every time we opened one of these child forms they would change their form size and mess up the anchoring (pretty much the size of the form was changed before the anchors were enabled).

It turns out the the VB conversion wizard was setting the “StartPosition” property of all our forms to “WindowsDefaultBoundary” which for MDI children means their size gets screwed up. When we turned it back to the default value of “WindowsDefaultLocation” things behaved normally. Thanks Microsoft!

Anyways that’s it so far. I’m sure there will be more.

April 26, 2006

Boo!

Filed under: .Net,Python — Jeff @ April 26, 2006 9:02 am

No this isn’t a Halloween post or anything like that. This post is about a fancy Pythonic language for the .NET CLR called Boo.

Boo is a strongly typed programming language that has a very similar syntax to Python and it targets the .NET CLR. The syntax differs in quite a few places to make to Boo functionality mesh better with .NET and also there is a lot of syntactic “sugar” added that makes using Boo super fun. Boo comes with a compiler that can turn Boo code into standard executables/libraries. It also comes with an interpreter. Even more interesting is that the interpeter is available in a library that can be used in other software.

While I’m pretty sure we won’t be using Boo for our main software development tasks anytime soon it looks like a marvelous tool for providing user scriptability in our apps. The application I work on here requires vaste amounts of customization per client and having the flexibility of an embedded scripting language that can poke and prod our business objects would be swell. And with Boo it’s really easy.

For example: Say we have a business object that has a name property and we want to allow the user to manipulate that property we can create a Boo interpreter and pass the business object into the environment and let them provide a chunk of script to manipulate our object. It’s that easy. The following code shows how easy this is:

using System;
using System.Collections.Generic;
using System.Text;
using Boo.Lang.Interpreter;
using Boo.Lang.Compiler;

namespace ConsoleApplication1
{
    public class BusinessObject
    {
        private string m_name;

        public string Name
        {
            get { return m_name; }
            set { m_name = value; }
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            string code = "bo1.Name = bo1.Name.ToUpper()";

            // Create a play business object
            BusinessObject bo1 = new BusinessObject();
            bo1.Name = "Jeff Clement";

            // Setup the Boo Interpreter
            InteractiveInterpreter interp = new InteractiveInterpreter();
            interp.SetValue("bo1", bo1);

            // try running our script
            CompilerContext context;
            context = interp.Eval(code);

            // If compiler raised any errors throw them as exceptions
            if (context.Errors.Count > 0)
                throw new Exception(context.Errors.ToString());

            Console.WriteLine("New value of Name property is " + bo1.Name);
        }
    }
}

The output from the above is the string “New Value of Name property is JEFF CLEMENT” because the Boo script ran against that object and upper-cased the name property.

Anyways that’s about all I have to say. It looks like a very promising tool and I hope we get a chance to roll it out here :)