Catfood.Shapefile is a .NET read-only, forward-only parser for Esri shapefiles. With Catfood.Shapefile it’s easy to enumerate all the shapes in a shapefile together with their metadata.
From version 2.00 Catfood.Shapefile is available via NuGet. It has also been migrated to .NET Standard 2.0. This means it is compatible with .NET Framework 4.61 or better and .NET Core 2.0 or better. If you use an older version of .NET then you should continue using Catfood.Shapefile 1.60. The source code is on GitHub.
Esri (originally Environmental Systems Research Institute) shapefiles are a GIS (geographic information systems) file format that can store a wide variety of geographic information. I originally started working with these files to add country borders to Catfood Earth.
Shapefiles actually consist of a number of different files with different extensions. There are three mandatory extensions: .shp, .shx and .dbf and so a shapefile containing borders might be distributed as borders.shp, borders.shx and borders.dbf. The .shp file contains the actual shape data in vector format, often lines or polygons. The .shx file is an index to the shapes. Finally the .dbf file is a database of metadata associated with the shapes. Catfood.Shapefile requires these three files.
There are several optional extensions that might be included with a shapefile. .prj contains the geographical projection, .xml is an alternate metadata format, .sbn and .sbx index for spatial queries, and .cpg defines the code page used by the shapefile.
Here is some sample code for a .NET 6 console application to print basic information about a shapefile and the first point in the first polygon:
To use this, create a new console application, paste the code into Program.cs and add Catfood.Shapefile via NuGet.
The default constructor uses a database connection string that uses the Jet driver. This is only available for 32-bit applications and you will need to target Windows x86 to use it. An overload is available that allows you to specify a custom connection string to access metadata.
Catfood.Shapefile supports Null, Point, MultiPoint, PolyLine, PolyLineM and Polygon shapes. Three dimensional shapes (PointZ, PolyLineZ and PolygonZ) are not currently supported. There is also currently no support for writing shapefiles. If you add any of this please send a pull request on GitHub!
I am grateful to the developers who have contributed to Catfood.Shapefile over the years. Most are credited in the release notes below. If you need help or have feedback please leave a comment on this post.
I just released Catfood.Shapefile 2.00, my .NET parser for ESRI Shapefiles.
The big change is that I have migrated to .NET Standard 2.0. This makes it possible to use from .NET Core as well as classic .NET Framework from 4.6.1 up. If you need to use an older version of .NET Framework then you'll want to stick with Catfood.Shapefile 1.60.
Catfood.Shapefile is now also available via NuGet. This is the recommended way to install. The source code is still available on GitHub.
Catfood.Shapefile 1.60
I just released Catfood.Shapefile 1.60. This contains a fix from Libor Weigl that factors out the enumerator so that you can still access the shapefile after enumeration.
Catfood.Shapefile is a .NET library for parsing ESRI Shapefiles.
A few people have asked for 3D shape support in my ESRI Shapefile library. I've never got around to it, but CodePlex user ekleiman has forked a version in his ESRI Shapefile to Image Convertor that supports PointZ, PolygonZ and PolyLineZ shapes. If that's what you need please check it out.
Catfood.Shapefile 1.50
I've just released a small update to my C# Shapefile library on Codeplex. Catfood.Shapefile 1.50 fixes a couple of bugs related to metadata and adds the ability to access metadata records directly via IDataRecord.
Catfood.Shapefile 1.40
I’ve just released a small update to Catfood.Shapefile. Stephan Stapel, who implemented PolyLineM support, has contributed a patch that improves the class hierarchy. CodePlex user originSH suggested supporting the ACE driver for 64-bit systems. I’ve added a constructor overload that allows you to use predefined Jet and ACE connection strings or provide your own templates if necessary. Thanks to Stephan and originSH.
Catfood.Shapefile is a .NET library for enumerating ESRI shapefiles. I originally wrote the library to help me build some complex layers in Catfood Earth. Since then it’s picked up thousands of users and some really valuable suggestions and patches from the CodePlex community. I’m very glad a took a couple of hours to open source the library back in 2009.
PolyLineM support in Catfood.Shapefile
I’ve just updated Catfood.Shapefile, my ESRI Shapefile parser for .NET, with PolyLineM support thanks to a contribution from Stephan Stapel. The solution for the new version has also been updated to Visual Studio 2010.
I've just released a small update for my ESRI Shapefile Reader project on GitHub. The only change is a patch from SolutionMania that fixes a problem when the shapefile name is also a reserved name in the metadata database. The patch escapes the name preventing an exception from being thrown.
Catfood.Shapefile.dll is a .NET 2.0 forward only parser for reading an ESRI Shapefile. Download 1.20 from GitHub.
Catfood.Shapefile.dll 1.10
I've just released v1.10 of my ESRI Shapefile Reader (Catfood.Shapefile.dll). This is a .NET 2.0 forward only parser for reading shapefile content.
Sharon Tickell was kind enough to report two bugs with suggested updates. These have both been fixed in 1.10.
While working on these fixes I also discovered that there are no 64-bit Jet drivers (since releasing the first version I've upgraded to a 64-bit box for development). This is an easy fix, just target any application using Catfood.Shapefile.dll at x86. I've updated the demo application accordingly.
Just got back from the StackOverflow DevDays event in San Francisco.
I was a bit worried that this would be overly focused on marketing FogBugz and StackOverflow. There were brief pitches on each (and I learned that
FogCreek is launching hosted source control and code reviews called Kiln, now in beta and looking pretty
nifty with tight integration with FogBugz) but this wasn't the focus.
I was also a little concerned that I'd be the only one there without a StackOverflow profile t-shirt.
Luckily I didn't see any reputation toting pod people at the conference.
Happily the day was very code oriented, and very diverse. Spell checking in Python, smartphone development for iPhone, Nokia
(via Qt) and Android, ASP.NET MVC and jQuery. I spend most of my time at the moment in C#/.NET and it was really valuable to spend a day
briefly diving into different stacks and platforms.
Joel said that they'd be back next year and I'm hoping that it offers a similar diverse range of topics.
(Published to the Fediverse as:
StackOverflow DevDays #code#stackoverflow#c##.net Review of the StackOverflow DevDays conference in San Francisco, California.)
I've just migrated this blog from catfood.net to its own domain. In the process I needed to port the template from classic ASP to ASP.NET and I also wanted to end up with valid XHTML.
If you're using blogger on your own domain then you're using the classic templates. There is a known issue with the template tag that causes Blogger to emit unwanted JavaScript - this causes havoc, especially if you're using the tag in the section of a page.
Google recommends using the <$blogpagetitle$> tag in the page title. This works, but it's not great from a usability or SEO perspective. For item pages you get the post title after the blog name and you probably want to put the post title first - the earlier that keywords appear in the title the better for search engine ranking.
Luckily there's an easy fix - just comment out the closing Blogger tag:
This doesn't interfere with the template rendering correctly and the JavaScript is then commented out on the rendered page. It's still an unpleasant bug, so if you use the classic templates please report it here and also star or comment on this forum topic to encourage Google to fix it.
If you use labels then Blogger includes them in a paragraph rendered with <$blogitembody$>. This means that wrapping <$blogitembody$> in a paragraph will cause XHTML validation errors for posts with labels because you can't nest another block element inside the paragraph.
The other XHMTL nasty I fixed was the post comments link. My template used the recommended Blogger code:
p>ahref="$BlogItemCommentCreate$>" $BlogItemCommentFormOnClick$>>Post a Commenta>p>
This renders as:
p>ahref="https://www.blogger.com/comment.g?blogID=12345678&postID=1234567890123456789" location.href=https://www.blogger.com/comment.g?blogID=12345678&postID=1234567890123456789;> Post a Commenta>p>
And you end up with a gazillion cascading XHTML errors, all caused by the illegal ampersand. I fixed this by constructing my own comment URL using the <$blogitemnumber$> tag (this emits the unique Post ID):
p>ahref="https://www.blogger.com/comment.g?blogID=12345678&postID=$BlogItemNumber$>"> Post a Commenta>p>
I've been experimenting with the best way to merge two images in C#. That is, paint one image on top of another with some level of transparency as opposed to using one color as a transparency mask. I tried three candidates, all included below:
SimpleBlend is the naive approach using GetPixel and SetPixel to add the desired alpha value to the second image before painting it on top of the first.
MatrixBlend configures a ColorMatrix to specify the desired alpha and then paints the second image on to the first using the matrix.
ManualBlend locks and directly manipulates the image data. This uses pointers and so introduces unsafe code (it's possible to marshal the image data into a managed array but I wanted to look at the performance with raw access).
I tested each approach ten times with a couple of large JPEG images. The results are:
I expect ManualBlend could be optimized further but both this and MatrixBlend are an order of magnitude faster than the naive approach. I'll be using MatrixBlend as no unsafe code is required.
(Published to the Fediverse as:
Fastest image merge (alpha blend) in GDI+ #code#gdi#matrix Compares the performance of GetPixe l/ SetPixel, ColorMatrix, and raw image data access for merging images in GDI+ (C# / System.Drawing APIs))
By Robert Ellison. Updated on Saturday, October 1, 2022.
I've been writing a play by text message version of battleships for Windows Mobile 6 using the MessageInterceptor class to receive messages. This works great on my AT&T Tilt but completely fails on my wife's Pantech device. The MessageInterceptor hooks up fine but never fires.
The 2.0 compact framework SmsAccount lets you send messages but unaccountably doesn't let you read them.
I avoided some unpleasant interop by grabbing the MAPIdotnet library. This implements a NewMessage event for MAPI stores, however as with MessageInterceptor the event hooks up OK but never fires on the damned Pantech.
MAPIdotnet does allow you to read the SMS inbox though, so the final answer is to fall back to looking for, processing and then deleting game related text messages on a timer. This is far from ideal as the game messages arrive and vibrate the phone before getting processed but at least it's now possible to play without buying a new phone.
To add to the frustration during development the Visual Studio 2005 toolbox lost all icons except for the pointer and a custom control that was part of the project. Resetting the toolbox didn't help, nor did restarting VS and the computer. The fix was to exit VS and then delete all the .tbd files from Microsoft\VisualStudio\8.0 in local application data. Sigh.
This has bitten me a few times. If you use Process.Start("url") it will work some of the time but you'll see a "The system cannot find the file specified" Win32Exception on some systems. Bummer.
Lots of people suggest looking up the HTTP handler in HKEY_CLASSES_ROOT but this is flawed as well - on my system for instance HTTP is registered to Firefox even though I'm actually using Chrome and I'd be unhappy waiting half an hour for Firefox to wake up and show the requested web page.
From XP there are a couple of registry settings tied to the current user's preferred browser.
First check HKEY_CURRENT_USER\Software\Clients\StartMenuInternet. This key will only exist if the user has overridden the system default browser - the default value is used to access the details (for me, it's chrome.exe).
If the user hasn't set a default then check HKEY_LOCAL_MACHINE\Software\Clients\StartMenuInternet. The default value here is the system default browser (on my system it's FIREFOX.EXE).
There is a set of subkeys under HKEY_LOCAL_MACHINE\Software\Clients\StartMenuInternet that contain details about each registered browser. The default value from StartMenuInternet (either HKCU or HKLM) is the subkey to look for. The path to my default browser is in this key:
Now I can Process.Start(path, url) to safely launch the default browser. You can fall back to Process.Start(url) if registry access fails for some reason, but be prepared for that Win32 exception.
(Published to the Fediverse as:
Launching a URL in the user's default browser #code#win32#registry Windows programming: how to launch a URL in the user's default browser. It's harder than you might think.)
I've been migrating my installers over to WiX. My only complaint with the WiX toolkit is that there's no bootstrapper included. This is important for installing any pre-requisites before passing control over to Windows Installer. Hopefully this will come after WiX 3.0 is released. For now, I've rolled my own bootstrapper to install .NET 2.0 if needed.
A couple of tips for screen savers. You can bring up the Windows screen saver settings using the following custom action. This is the same command that is launched when you right-click a screen saver (.scr) file and pick Install:
Sequence this in InstallExecuteSequence after InstallFinalize:
You can also add a shortcut to your Program Files folder to configure the screen saver. This is really helpful for people who aren't sure how to get to the screen saver dialog from Control Panel or right-clicking the Desktop:
Unlike a shortcut to a file that you install you need to specify the Target. The example above assumes that ProgramMenuDir is the Id of your Start Menu folder. The shortcut should be in a Directory but not as a child of a File node.
Updated 2020-05-26 20:22:
It looks like something changed in Windows 10, around build 1903, that stops this from working on 64-bit systems. The screensaver will preview OK but does not start as expected (system screensavers start OK, so it's not some sort of power management problem). I could reproduce this on one box running 1909 but not another so maybe there is something else going on. The snippets above will run rundll32.exe from the SysWOW64 folder and at some point this seems to have stopped working. Changing to [System64Folder]rundll32.exe launches the System32 version which then causes the screensaver to load normally. If your screensaver is 32-bit and installed to SysWOW64 then you need a command that looks like this on a 64-bit system: [System64Folder]rundll32.exe desk.cpl,InstallScreenSaver [SystemFolder]the.scr
(Published to the Fediverse as:
WiX Tricks for Screen Savers #code#c# How to run the screen saver install dialog from Windows Installer XML or WiX and add a program menu shortcut.)
I'm updating a screensaver so that it stops work once the monitor switches off. This seemed like a really simple requirement but it took some time to find an API that works on both XP and Vista.
My first attempt was ReadPwrScheme(). The documentation suggests using a different method on Vista - it should say so more strongly because on Vista you get back some default information that bears no relationship to reality.
Next I tried CallNtPowerInformation(). This doesn't mention any alternatives but also doesn't work on Vista. I've added comments on both MSDN pages pointing to the answer.
GetCurrentPowerPolicies() is just the ticket - it returns a wealth of information including the video timeout on AC and battery power and works on both XP and Vista.
(Published to the Fediverse as:
Video timeout on XP and Vista (power management) #code#win32 How to tell when the monitor is going to get switched off on XP and Vista (power management, Win32 for C#))