Archive for the ‘.NET Platform’ Category

No shell extensions with .NET 4?

Shell extensions (at least in Windows, I can’t speak to other platforms) are not easy to write and require some pretty ugly native code, requiring Win32 and COM code. For most applications, the .NET Framework can usually provide a nice wrapper for such code, but not for shell extensions. Prior to .NET 4, using the .NET Framework was dangerous because, as explained in this forum post, an extension would attempt to inject a version of the .NET Framework (the version the shell extension was written in) into every application affected by the extension (i.e. every application making use of the shell component extended), but only one version of the .NET Framework can be loaded in a process, potentially creating conflicts with other applications using different versions of .NET.

.NET 4 can be loaded side-by-side with other versions of the framework, so shell extensions are technically possible, and I was happy to find an article + code sample detailing how to write an extension as part of Microsoft’s All-In-One Code Framework. Unfortunately, the code sample has since disappeared and, regarding .NET 4 shell extensions, Jialiang Ge of the All-In-One Code Framework team explains:

In .NET 4, with the ability to have multiple runtimes in process with any other runtime. However, writing managed shell extensions is still not supported. Microsoft recommends against writing them.

No much of an explanation, to say the least.

Embedding WebKit in a WinForms application

This is how to embed a WebKit instance within a WinForms application. I promised, a long time ago, to show this, but never got around to it. The process itself is pretty simple, assuming you have WebKit compiled (which can be pretty difficult) because you’ll need to be able to link with the WebKit libraries, specificially: WebKit.lib and WebKitGUID.lib (which, of course, have dependencies on all of the other libraries produced in the compilation). I’m going to be using a older version of WebKit, the same one I played with in my previous blog posts, as I don’t have time to check out the newest version of WebKit. Hopefully, the interfaces are the same or similar and what I’m about to describe here can be adapted easily to work with the latest version.

What we’re going to do is create a CLI wrapper to allow the .Net application to access the native WebKit code. To mix managed and unmanaged code, we’re going to need to create a C++/CLI application. Yes, it is going to be ugly code, but it works and (I think) much simpler than trying to P/Invoke functions in WebKit.dll.

Here’s the wrapper code (I’ve also included a compiled dll in the /Release folder):
WebKitCLIWrapper.dll.zip

WebKitNativeController.h and WebKitNativeController.cpp is adapted from the demo code provided by Apple. WebKitCLIWrapper.h (shown below) is the C++/CLI .NET code that wraps the native controller.

#pragma once

#include
"WebKitNativeController.h"

namespace WebKitCLIWrapper
{
    
using namespace System;
    
using namespace System::Collections;

    
public ref class Wrapper
    {
        
public:
            Wrapper(IntPtr hwnd, String^ htmlContent)
            {
                webKitController =
new WebKitNativeController();

                IntPtr bstrPtr = System::Runtime::InteropServices::Marshal::StringToBSTR(htmlContent);
                webKitController->Init((HWND)(
int)hwnd, (BSTR*)&bstrPtr);
                System::Runtime::InteropServices::Marshal::FreeBSTR(bstrPtr);
            }

            ~Wrapper()
            {
                webKitController->UnInit();
                webKitController->Release();
            }

            
void LoadURL(String^ url)
            {

                IntPtr bstrPtr = System::Runtime::InteropServices::Marshal::StringToBSTR(url);
                webKitController->LoadURL(*((BSTR*)&bstrPtr));
                System::Runtime::InteropServices::Marshal::FreeBSTR(bstrPtr);
            }
            
        
protected:
            WebKitNativeController*        webKitController;
    };
}

Now, we can simply include WebKitCLIWrapper.dll in any .Net project as a reference and access the wrapper to create a WebKit instance. So if your in Visual C#, create a new WinForms app, create a Panel (panel1) on a form, and add the following to the form’s Load event:

WebKitCLIWrapper.Wrapper wrap = new Wrapper(panel1.Handle, "");
wrap.LoadURL(
"http://arstechnica.com/");

However, before running the application, you need all the necessary libraries and necessary resources referenced by WebKit.dll in the app’s working directory (I like to set it to Debug).

For convenience, here’s a zip containing all you’ll need:
WebKit_dlls+resources.zip
(as I mentioned, this is an older version of WebKit)

With all the necessary files in place, launch the app, and a WebKit instance should load in the specified panel (panel1) along with the web page specified in LoadURL() call.

arstechnica.com loaded in a webkit container within a WinForms application

If you’d like to display and process a specific piece of HTML code, get rid of the LoadURL() call, place the code to be embedded in a string, and pass it as the 2nd argument to the WebKitCLIWrapper.Wrapper constructor. For example, this will load and embed a youtube video:

string embed = "<object width=\"425\" height=\"344\"><param name=\"movie\" value=\"http://www.youtube.com/v/SuBqIrgKnNg&hl=en&fs=1\"></param><param name=\"allowFullScreen\" value=\"true\"></param><embed src=\"http://www.youtube.com/v/SuBqIrgKnNg&hl=en&fs=1\" type=\"application/x-shockwave-flash\" allowfullscreen=\"true\" width=\"425\" height=\"344\"></embed></object>";
WebKitCLIWrapper.
Wrapper wrap = new Wrapper(panel1.Handle, embed);

cookie monster npr interview, displayed in a webkit instance with a WinForms panel

The wrapper interface is very bare-bones, but it’s good enough if you just need to display some web or HTML content in your app or, if your looking to build a .NET web browser, it will hopefully provide a starting point for how to interact with WebKit.

File.OpenRead, FileShare issues

The following piece of C# code to open a file for reading (an MS Word document, opened by Word), generated an IOException.

FileStream fs = System.IO.File.OpenRead(oldFullPath);

The IOException:

The process cannot access the file ... because it is being used by another process.

Not too unusual, but curiously, the following code, to do the same same thing, did not generate any exceptions and the file was read successfully.

FileStream fs = System.IO.File.Open(oldFullPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);

I’d always assumed that File.OpenRead() was equivalent to the File.Open() call above.
Bad assumption.
It looks like the FileShare flag is set to FileShare.Read not FileShare.ReadWrite by File.OpenRead().

Note that the FileShare flag is a bit misleading as described by the docs, it doesn’t only apply to subsequent operations. Here’s a good explanation by Darin Dimitrov from stackoverflow:

In the case of future openers, a FileShare.Read means “future openers can open the file for reading”. In the case of past openers, FileShare.Read means “open this file for me only if it has past openers that opened it for reading only”. That’s why FileShare.ReadWrite needs to be used here, because Excel opens the file for writing.

A possible GDI+ bug

This involved drawing a filled rectangle with a TextureBrush, using a 1x[whatever] texture and setting it to be tiled.

TextureBrush tb = new TextureBrush(firesync.Properties.Resources.target_highlight2_run);
tb.WrapMode = System.Drawing.Drawing2D.
WrapMode.Tile;
e.Graphics.FillRectangle(tb, 0, 0, 32, 32);

The code above works correctly and here is what it produces,

GDI+ TextureBrush correct lines rendering

Unfortunately if the y (top) coordinate of the rectangle is changed to anything other than 0, the rendering gets screwed up. Here is what occurs if the y-coordinate is set to 1 (which should, effectively, push everything down 1 pixel),

GDI+ TextureBrush incorrect lines rendering

However, there is a way to hack around the issue, keep the y-coordinate at 0 and use Graphics.TranslateTransform() to do the y translation.

TextureBrush tb = new TextureBrush(firesync.Properties.Resources.target_highlight2_run);
tb.WrapMode = System.Drawing.Drawing2D.
WrapMode.Tile;
e.Graphics.TranslateTransform(0, 1);
e.Graphics.FillRectangle(tb, 0, 0, 32, 32);

MIME types in C#

The .NET Framework has no methods to get the MIME type of a file and, as I was in need of such functionality a while back, I’m glad I found this post on CSharpFriends.com (UPDATE: removed link, CSharpFriends.com is dead) which presents a switch statement that maps numerous filename extensions to the appropiate MIME type.

I was somewhat dismayed that someone mentioned using the system registry to lookup the MIME types, and the OP seemed to have gone with this method. Using the registry cuts down your codebase, but that’s little more than a convenience; there are some important issues that pop up when using the registry in this situation:

  • It only works if the file extension is known to Windows; either the version of Windows the app is running on knows of the file extension or an application puts the file extension into the registry.
  • It binds (read: couples) your app to a third-party component, in a situation where there is no need to.
  • It locks you into a specific platform (i.e. it won’t work with Mono). Even if it’s not a major issue, there’s no reason to lock your app to a certain platform when you don’t have to.

UPDATE: As CSharpFriends.com is dead, the code I derived from the original post is below. The FromFileName() function will take a filepath, get the extension from the filename, and return the MIME type of the file.

static public string FromFileName(string filepath)
{
switch (System.IO.Path.GetExtension(filepath).ToLower())
{
case ".3dm": retval = "x-world/x-3dmf"; break;
case ".3dmf": retval = "x-world/x-3dmf"; break;
case ".a": retval = "application/octet-stream"; break;
case ".aab": retval = "application/x-authorware-bin"; break;
case ".aam": retval = "application/x-authorware-map"; break;
case ".aas": retval = "application/x-authorware-seg"; break;
case ".abc": retval = "text/vnd.abc"; break;
case ".acgi": retval = "text/html"; break;
case ".afl": retval = "video/animaflex"; break;
case ".ai": retval = "application/postscript"; break;
case ".aif": retval = "audio/aiff"; break;
case ".aifc": retval = "audio/aiff"; break;
case ".aiff": retval = "audio/aiff"; break;
case ".aim": retval = "application/x-aim"; break;
case ".aip": retval = "text/x-audiosoft-intra"; break;
case ".ani": retval = "application/x-navi-animation"; break;
case ".aos": retval = "application/x-nokia-9000-communicator-add-on-software"; break;
case ".aps": retval = "application/mime"; break;
case ".arc": retval = "application/octet-stream"; break;
case ".arj": retval = "application/arj"; break;
case ".art": retval = "image/x-jg"; break;
case ".asf": retval = "video/x-ms-asf"; break;
case ".asm": retval = "text/x-asm"; break;
case ".asp": retval = "text/asp"; break;
case ".asx": retval = "video/x-ms-asf"; break;
case ".au": retval = "audio/basic"; break;
case ".avi": retval = "video/avi"; break;
case ".avs": retval = "video/avs-video"; break;
case ".bcpio": retval = "application/x-bcpio"; break;
case ".bin": retval = "application/octet-stream"; break;
case ".bm": retval = "image/bmp"; break;
case ".bmp": retval = "image/bmp"; break;
case ".boo": retval = "application/book"; break;
case ".book": retval = "application/book"; break;
case ".boz": retval = "application/x-bzip2"; break;
case ".bsh": retval = "application/x-bsh"; break;
case ".bz": retval = "application/x-bzip"; break;
case ".bz2": retval = "application/x-bzip2"; break;
case ".c": retval = "text/plain"; break;
case ".c++": retval = "text/plain"; break;
case ".cat": retval = "application/vnd.ms-pki.seccat"; break;
case ".cc": retval = "text/plain"; break;
case ".ccad": retval = "application/clariscad"; break;
case ".cco": retval = "application/x-cocoa"; break;
case ".cdf": retval = "application/cdf"; break;
case ".cer": retval = "application/pkix-cert"; break;
case ".cha": retval = "application/x-chat"; break;
case ".chat": retval = "application/x-chat"; break;
case ".class": retval = "application/java"; break;
case ".com": retval = "application/octet-stream"; break;
case ".conf": retval = "text/plain"; break;
case ".cpio": retval = "application/x-cpio"; break;
case ".cpp": retval = "text/x-c"; break;
case ".cpt": retval = "application/x-cpt"; break;
case ".crl": retval = "application/pkcs-crl"; break;
case ".crt": retval = "application/pkix-cert"; break;
case ".cs": retval = "text/x-csharp"; break;
case ".csh": retval = "application/x-csh"; break;
case ".css": retval = "text/css"; break;
case ".cxx": retval = "text/plain"; break;
case ".dcr": retval = "application/x-director"; break;
case ".deepv": retval = "application/x-deepv"; break;
case ".def": retval = "text/plain"; break;
case ".der": retval = "application/x-x509-ca-cert"; break;
case ".dif": retval = "video/x-dv"; break;
case ".dir": retval = "application/x-director"; break;
case ".dl": retval = "video/dl"; break;
case ".doc": retval = "application/msword"; break;
case ".docx": retval = "application/vnd.openxmlformats-officedocument.wordprocessingml.document"; break;
case ".dot": retval = "application/msword"; break;
case ".dp": retval = "application/commonground"; break;
case ".drw": retval = "application/drafting"; break;
case ".dump": retval = "application/octet-stream"; break;
case ".dv": retval = "video/x-dv"; break;
case ".dvi": retval = "application/x-dvi"; break;
case ".dwf": retval = "model/vnd.dwf"; break;
case ".dwg": retval = "image/vnd.dwg"; break;
case ".dxf": retval = "image/vnd.dwg"; break;
case ".dxr": retval = "application/x-director"; break;
case ".el": retval = "text/x-script.elisp"; break;
case ".elc": retval = "application/x-elc"; break;
case ".env": retval = "application/x-envoy"; break;
case ".eps": retval = "application/postscript"; break;
case ".es": retval = "application/x-esrehber"; break;
case ".etx": retval = "text/x-setext"; break;
case ".evy": retval = "application/envoy"; break;
case ".exe": retval = "application/octet-stream"; break;
case ".f": retval = "text/plain"; break;
case ".f77": retval = "text/x-fortran"; break;
case ".f90": retval = "text/plain"; break;
case ".fdf": retval = "application/vnd.fdf"; break;
case ".fif": retval = "image/fif"; break;
case ".fli": retval = "video/fli"; break;
case ".flo": retval = "image/florian"; break;
case ".flx": retval = "text/vnd.fmi.flexstor"; break;
case ".fmf": retval = "video/x-atomic3d-feature"; break;
case ".for": retval = "text/x-fortran"; break;
case ".fpx": retval = "image/vnd.fpx"; break;
case ".frl": retval = "application/freeloader"; break;
case ".funk": retval = "audio/make"; break;
case ".g": retval = "text/plain"; break;
case ".g3": retval = "image/g3fax"; break;
case ".gif": retval = "image/gif"; break;
case ".gl": retval = "video/gl"; break;
case ".gsd": retval = "audio/x-gsm"; break;
case ".gsm": retval = "audio/x-gsm"; break;
case ".gsp": retval = "application/x-gsp"; break;
case ".gss": retval = "application/x-gss"; break;
case ".gtar": retval = "application/x-gtar"; break;
case ".gz": retval = "application/x-gzip"; break;
case ".gzip": retval = "application/x-gzip"; break;
case ".h": retval = "text/plain"; break;
case ".hdf": retval = "application/x-hdf"; break;
case ".help": retval = "application/x-helpfile"; break;
case ".hgl": retval = "application/vnd.hp-hpgl"; break;
case ".hh": retval = "text/plain"; break;
case ".hlb": retval = "text/x-script"; break;
case ".hlp": retval = "application/hlp"; break;
case ".hpg": retval = "application/vnd.hp-hpgl"; break;
case ".hpgl": retval = "application/vnd.hp-hpgl"; break;
case ".hqx": retval = "application/binhex"; break;
case ".hta": retval = "application/hta"; break;
case ".htc": retval = "text/x-component"; break;
case ".htm": retval = "text/html"; break;
case ".html": retval = "text/html"; break;
case ".htmls": retval = "text/html"; break;
case ".htt": retval = "text/webviewhtml"; break;
case ".htx": retval = "text/html"; break;
case ".ice": retval = "x-conference/x-cooltalk"; break;
case ".ico": retval = "image/x-icon"; break;
case ".idc": retval = "text/plain"; break;
case ".ief": retval = "image/ief"; break;
case ".iefs": retval = "image/ief"; break;
case ".iges": retval = "application/iges"; break;
case ".igs": retval = "application/iges"; break;
case ".ima": retval = "application/x-ima"; break;
case ".imap": retval = "application/x-httpd-imap"; break;
case ".inf": retval = "application/inf"; break;
case ".ins": retval = "application/x-internett-signup"; break;
case ".ip": retval = "application/x-ip2"; break;
case ".isu": retval = "video/x-isvideo"; break;
case ".it": retval = "audio/it"; break;
case ".iv": retval = "application/x-inventor"; break;
case ".ivr": retval = "i-world/i-vrml"; break;
case ".ivy": retval = "application/x-livescreen"; break;
case ".jam": retval = "audio/x-jam"; break;
case ".jav": retval = "text/plain"; break;
case ".java": retval = "text/plain"; break;
case ".jcm": retval = "application/x-java-commerce"; break;
case ".jfif": retval = "image/jpeg"; break;
case ".jfif-tbnl": retval = "image/jpeg"; break;
case ".jpe": retval = "image/jpeg"; break;
case ".jpeg": retval = "image/jpeg"; break;
case ".jpg": retval = "image/jpeg"; break;
case ".jps": retval = "image/x-jps"; break;
case ".js": retval = "application/x-javascript"; break;
case ".jut": retval = "image/jutvision"; break;
case ".kar": retval = "audio/midi"; break;
case ".ksh": retval = "application/x-ksh"; break;
case ".la": retval = "audio/nspaudio"; break;
case ".lam": retval = "audio/x-liveaudio"; break;
case ".latex": retval = "application/x-latex"; break;
case ".lha": retval = "application/octet-stream"; break;
case ".lhx": retval = "application/octet-stream"; break;
case ".list": retval = "text/plain"; break;
case ".lma": retval = "audio/nspaudio"; break;
case ".log": retval = "text/plain"; break;
case ".lsp": retval = "application/x-lisp"; break;
case ".lst": retval = "text/plain"; break;
case ".lsx": retval = "text/x-la-asf"; break;
case ".ltx": retval = "application/x-latex"; break;
case ".lzh": retval = "application/octet-stream"; break;
case ".lzx": retval = "application/octet-stream"; break;
case ".m": retval = "text/plain"; break;
case ".m1v": retval = "video/mpeg"; break;
case ".m2a": retval = "audio/mpeg"; break;
case ".m2v": retval = "video/mpeg"; break;
case ".m3u": retval = "audio/x-mpequrl"; break;
case ".man": retval = "application/x-troff-man"; break;
case ".map": retval = "application/x-navimap"; break;
case ".mar": retval = "text/plain"; break;
case ".mbd": retval = "application/mbedlet"; break;
case ".mc$": retval = "application/x-magic-cap-package-1.0"; break;
case ".mcd": retval = "application/mcad"; break;
case ".mcf": retval = "text/mcf"; break;
case ".mcp": retval = "application/netmc"; break;
case ".me": retval = "application/x-troff-me"; break;
case ".mht": retval = "message/rfc822"; break;
case ".mhtml": retval = "message/rfc822"; break;
case ".mid": retval = "audio/midi"; break;
case ".midi": retval = "audio/midi"; break;
case ".mif": retval = "application/x-mif"; break;
case ".mime": retval = "message/rfc822"; break;
case ".mjf": retval = "audio/x-vnd.audioexplosion.mjuicemediafile"; break;
case ".mjpg": retval = "video/x-motion-jpeg"; break;
case ".mm": retval = "application/base64"; break;
case ".mme": retval = "application/base64"; break;
case ".mod": retval = "audio/mod"; break;
case ".moov": retval = "video/quicktime"; break;
case ".mov": retval = "video/quicktime"; break;
case ".movie": retval = "video/x-sgi-movie"; break;
case ".mp2": retval = "audio/mpeg"; break;
case ".mp3": retval = "audio/mpeg"; break;
case ".mpa": retval = "audio/mpeg"; break;
case ".mpc": retval = "application/x-project"; break;
case ".mpe": retval = "video/mpeg"; break;
case ".mpeg": retval = "video/mpeg"; break;
case ".mpg": retval = "video/mpeg"; break;
case ".mpga": retval = "audio/mpeg"; break;
case ".mpp": retval = "application/vnd.ms-project"; break;
case ".mpt": retval = "application/vnd.ms-project"; break;
case ".mpv": retval = "application/vnd.ms-project"; break;
case ".mpx": retval = "application/vnd.ms-project"; break;
case ".mrc": retval = "application/marc"; break;
case ".ms": retval = "application/x-troff-ms"; break;
case ".mv": retval = "video/x-sgi-movie"; break;
case ".my": retval = "audio/make"; break;
case ".mzz": retval = "application/x-vnd.audioexplosion.mzz"; break;
case ".nap": retval = "image/naplps"; break;
case ".naplps": retval = "image/naplps"; break;
case ".nc": retval = "application/x-netcdf"; break;
case ".ncm": retval = "application/vnd.nokia.configuration-message"; break;
case ".nif": retval = "image/x-niff"; break;
case ".niff": retval = "image/x-niff"; break;
case ".nix": retval = "application/x-mix-transfer"; break;
case ".nsc": retval = "application/x-conference"; break;
case ".nvd": retval = "application/x-navidoc"; break;
case ".o": retval = "application/octet-stream"; break;
case ".oda": retval = "application/oda"; break;
case ".ogg": retval = "audio/ogg"; break;
case ".omc": retval = "application/x-omc"; break;
case ".omcd": retval = "application/x-omcdatamaker"; break;
case ".omcr": retval = "application/x-omcregerator"; break;
case ".p": retval = "text/x-pascal"; break;
case ".p10": retval = "application/pkcs10"; break;
case ".p12": retval = "application/pkcs-12"; break;
case ".p7a": retval = "application/x-pkcs7-signature"; break;
case ".p7c": retval = "application/pkcs7-mime"; break;
case ".p7m": retval = "application/pkcs7-mime"; break;
case ".p7r": retval = "application/x-pkcs7-certreqresp"; break;
case ".p7s": retval = "application/pkcs7-signature"; break;
case ".part": retval = "application/pro_eng"; break;
case ".pas": retval = "text/pascal"; break;
case ".pbm": retval = "image/x-portable-bitmap"; break;
case ".pcl": retval = "application/vnd.hp-pcl"; break;
case ".pct": retval = "image/x-pict"; break;
case ".pcx": retval = "image/x-pcx"; break;
case ".pdb": retval = "chemical/x-pdb"; break;
case ".pdf": retval = "application/pdf"; break;
case ".pfunk": retval = "audio/make"; break;
case ".pgm": retval = "image/x-portable-greymap"; break;
case ".php": retval = "text/php"; break;
case ".pic": retval = "image/pict"; break;
case ".pict": retval = "image/pict"; break;
case ".pkg": retval = "application/x-newton-compatible-pkg"; break;
case ".pko": retval = "application/vnd.ms-pki.pko"; break;
case ".pl": retval = "text/plain"; break;
case ".plx": retval = "application/x-pixclscript"; break;
case ".pm": retval = "image/x-xpixmap"; break;
case ".pm4": retval = "application/x-pagemaker"; break;
case ".pm5": retval = "application/x-pagemaker"; break;
case ".png": retval = "image/png"; break;
case ".pnm": retval = "application/x-portable-anymap"; break;
case ".pot": retval = "application/vnd.ms-powerpoint"; break;
case ".pov": retval = "model/x-pov"; break;
case ".ppa": retval = "application/vnd.ms-powerpoint"; break;
case ".ppm": retval = "image/x-portable-pixmap"; break;
case ".pps": retval = "application/vnd.ms-powerpoint"; break;
case ".ppt": retval = "application/vnd.ms-powerpoint"; break;
case ".pptx": retval = "application/vnd.openxmlformats-officedocument.presentationml.presentation"; break;
case ".ppz": retval = "application/vnd.ms-powerpoint"; break;
case ".pre": retval = "application/x-freelance"; break;
case ".prt": retval = "application/pro_eng"; break;
case ".ps": retval = "application/postscript"; break;
case ".psd": retval = "image/vnd.adobe.photoshop"; break;
case ".pvu": retval = "paleovu/x-pv"; break;
case ".pwz": retval = "application/vnd.ms-powerpoint"; break;
case ".py": retval = "text/x-script.phyton"; break;
case ".pyc": retval = "applicaiton/x-bytecode.python"; break;
case ".qcp": retval = "audio/vnd.qcelp"; break;
case ".qd3": retval = "x-world/x-3dmf"; break;
case ".qd3d": retval = "x-world/x-3dmf"; break;
case ".qif": retval = "image/x-quicktime"; break;
case ".qt": retval = "video/quicktime"; break;
case ".qtc": retval = "video/x-qtc"; break;
case ".qti": retval = "image/x-quicktime"; break;
case ".qtif": retval = "image/x-quicktime"; break;
case ".ra": retval = "audio/x-pn-realaudio"; break;
case ".ram": retval = "audio/x-pn-realaudio"; break;
case ".ras": retval = "application/x-cmu-raster"; break;
case ".rast": retval = "image/cmu-raster"; break;
case ".rexx": retval = "text/x-script.rexx"; break;
case ".rf": retval = "image/vnd.rn-realflash"; break;
case ".rgb": retval = "image/x-rgb"; break;
case ".rm": retval = "application/vnd.rn-realmedia"; break;
case ".rmi": retval = "audio/mid"; break;
case ".rmm": retval = "audio/x-pn-realaudio"; break;
case ".rmp": retval = "audio/x-pn-realaudio"; break;
case ".rng": retval = "application/ringing-tones"; break;
case ".rnx": retval = "application/vnd.rn-realplayer"; break;
case ".roff": retval = "application/x-troff"; break;
case ".rp": retval = "image/vnd.rn-realpix"; break;
case ".rpm": retval = "audio/x-pn-realaudio-plugin"; break;
case ".rt": retval = "text/richtext"; break;
case ".rtf": retval = "text/richtext"; break;
case ".rtx": retval = "text/richtext"; break;
case ".rv": retval = "video/vnd.rn-realvideo"; break;
case ".s": retval = "text/x-asm"; break;
case ".s3m": retval = "audio/s3m"; break;
case ".saveme": retval = "application/octet-stream"; break;
case ".sbk": retval = "application/x-tbook"; break;
case ".scm": retval = "application/x-lotusscreencam"; break;
case ".sdml": retval = "text/plain"; break;
case ".sdp": retval = "application/sdp"; break;
case ".sdr": retval = "application/sounder"; break;
case ".sea": retval = "application/sea"; break;
case ".set": retval = "application/set"; break;
case ".sgm": retval = "text/sgml"; break;
case ".sgml": retval = "text/sgml"; break;
case ".sh": retval = "application/x-sh"; break;
case ".shar": retval = "application/x-shar"; break;
case ".shtml": retval = "text/html"; break;
case ".sid": retval = "audio/x-psid"; break;
case ".sit": retval = "application/x-sit"; break;
case ".skd": retval = "application/x-koan"; break;
case ".skm": retval = "application/x-koan"; break;
case ".skp": retval = "application/x-koan"; break;
case ".skt": retval = "application/x-koan"; break;
case ".sl": retval = "application/x-seelogo"; break;
case ".smi": retval = "application/smil"; break;
case ".smil": retval = "application/smil"; break;
case ".snd": retval = "audio/basic"; break;
case ".sol": retval = "application/solids"; break;
case ".spc": retval = "text/x-speech"; break;
case ".spl": retval = "application/futuresplash"; break;
case ".spr": retval = "application/x-sprite"; break;
case ".sprite": retval = "application/x-sprite"; break;
case ".src": retval = "application/x-wais-source"; break;
case ".ssi": retval = "text/x-server-parsed-html"; break;
case ".ssm": retval = "application/streamingmedia"; break;
case ".sst": retval = "application/vnd.ms-pki.certstore"; break;
case ".step": retval = "application/step"; break;
case ".stl": retval = "application/sla"; break;
case ".stp": retval = "application/step"; break;
case ".sv4cpio": retval = "application/x-sv4cpio"; break;
case ".sv4crc": retval = "application/x-sv4crc"; break;
case ".svf": retval = "image/vnd.dwg"; break;
case ".svr": retval = "application/x-world"; break;
case ".swf": retval = "application/x-shockwave-flash"; break;
case ".t": retval = "application/x-troff"; break;
case ".talk": retval = "text/x-speech"; break;
case ".tar": retval = "application/x-tar"; break;
case ".tbk": retval = "application/toolbook"; break;
case ".tcl": retval = "application/x-tcl"; break;
case ".tcsh": retval = "text/x-script.tcsh"; break;
case ".tex": retval = "application/x-tex"; break;
case ".texi": retval = "application/x-texinfo"; break;
case ".texinfo": retval = "application/x-texinfo"; break;
case ".text": retval = "text/plain"; break;
case ".tgz": retval = "application/x-compressed"; break;
case ".tif": retval = "image/tiff"; break;
case ".tiff": retval = "image/tiff"; break;
case ".tr": retval = "application/x-troff"; break;
case ".tsi": retval = "audio/tsp-audio"; break;
case ".tsp": retval = "application/dsptype"; break;
case ".tsv": retval = "text/tab-separated-values"; break;
case ".turbot": retval = "image/florian"; break;
case ".txt": retval = "text/plain"; break;
case ".uil": retval = "text/x-uil"; break;
case ".uni": retval = "text/uri-list"; break;
case ".unis": retval = "text/uri-list"; break;
case ".unv": retval = "application/i-deas"; break;
case ".uri": retval = "text/uri-list"; break;
case ".uris": retval = "text/uri-list"; break;
case ".url": retval = "text/url"; break;
case ".ustar": retval = "application/x-ustar"; break;
case ".uu": retval = "application/octet-stream"; break;
case ".uue": retval = "text/x-uuencode"; break;
case ".vcd": retval = "application/x-cdlink"; break;
case ".vcs": retval = "text/x-vcalendar"; break;
case ".vda": retval = "application/vda"; break;
case ".vdo": retval = "video/vdo"; break;
case ".vew": retval = "application/groupwise"; break;
case ".viv": retval = "video/vivo"; break;
case ".vivo": retval = "video/vivo"; break;
case ".vmd": retval = "application/vocaltec-media-desc"; break;
case ".vmf": retval = "application/vocaltec-media-file"; break;
case ".voc": retval = "audio/voc"; break;
case ".vos": retval = "video/vosaic"; break;
case ".vox": retval = "audio/voxware"; break;
case ".vqe": retval = "audio/x-twinvq-plugin"; break;
case ".vqf": retval = "audio/x-twinvq"; break;
case ".vql": retval = "audio/x-twinvq-plugin"; break;
case ".vrml": retval = "application/x-vrml"; break;
case ".vrt": retval = "x-world/x-vrt"; break;
case ".vsd": retval = "application/x-visio"; break;
case ".vst": retval = "application/x-visio"; break;
case ".vsw": retval = "application/x-visio"; break;
case ".w60": retval = "application/wordperfect6.0"; break;
case ".w61": retval = "application/wordperfect6.1"; break;
case ".w6w": retval = "application/msword"; break;
case ".wav": retval = "audio/wav"; break;
case ".wb1": retval = "application/x-qpro"; break;
case ".wbmp": retval = "image/vnd.wap.wbmp"; break;
case ".web": retval = "application/vnd.xara"; break;
case ".wiz": retval = "application/msword"; break;
case ".wk1": retval = "application/x-123"; break;
case ".wmf": retval = "windows/metafile"; break;
case ".wml": retval = "text/vnd.wap.wml"; break;
case ".wmlc": retval = "application/vnd.wap.wmlc"; break;
case ".wmls": retval = "text/vnd.wap.wmlscript"; break;
case ".wmlsc": retval = "application/vnd.wap.wmlscriptc"; break;
case ".word": retval = "application/msword"; break;
case ".wmv": retval = "video/x-ms-wmv"; break;
case ".wp": retval = "application/wordperfect"; break;
case ".wp5": retval = "application/wordperfect"; break;
case ".wp6": retval = "application/wordperfect"; break;
case ".wpd": retval = "application/wordperfect"; break;
case ".wq1": retval = "application/x-lotus"; break;
case ".wri": retval = "application/mswrite"; break;
case ".wrl": retval = "application/x-world"; break;
case ".wrz": retval = "x-world/x-vrml"; break;
case ".wsc": retval = "text/scriplet"; break;
case ".wsrc": retval = "application/x-wais-source"; break;
case ".wtk": retval = "application/x-wintalk"; break;
case ".xbm": retval = "image/x-xbitmap"; break;
case ".xdr": retval = "video/x-amt-demorun"; break;
case ".xgz": retval = "xgl/drawing"; break;
case ".xif": retval = "image/vnd.xiff"; break;
case ".xl": retval = "application/excel"; break;
case ".xla": retval = "application/vnd.ms-excel"; break;
case ".xlb": retval = "application/vnd.ms-excel"; break;
case ".xlc": retval = "application/vnd.ms-excel"; break;
case ".xld": retval = "application/vnd.ms-excel"; break;
case ".xlk": retval = "application/vnd.ms-excel"; break;
case ".xll": retval = "application/vnd.ms-excel"; break;
case ".xlm": retval = "application/vnd.ms-excel"; break;
case ".xls": retval = "application/vnd.ms-excel"; break;
case ".xlsx": retval = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; break;
case ".xlt": retval = "application/vnd.ms-excel"; break;
case ".xlv": retval = "application/vnd.ms-excel"; break;
case ".xlw": retval = "application/vnd.ms-excel"; break;
case ".xm": retval = "audio/xm"; break;
case ".xml": retval = "application/xml"; break;
case ".xmz": retval = "xgl/movie"; break;
case ".xpix": retval = "application/x-vnd.ls-xpix"; break;
case ".xpm": retval = "image/xpm"; break;
case ".x-png": retval = "image/png"; break;
case ".xsr": retval = "video/x-amt-showrun"; break;
case ".xwd": retval = "image/x-xwd"; break;
case ".xyz": retval = "chemical/x-pdb"; break;
case ".z": retval = "application/x-compressed"; break;
case ".zip": retval = "application/zip"; break;
case ".zoo": retval = "application/octet-stream"; break;
case ".zsh": retval = "text/x-script.zsh"; break;
default: retval = "application/octet-stream"; break;
}

return retval;
}

More .Net FtpWebRequest woes

This time it’s an issue with the SIZE command. As explained here,

Some servers require sending “TYPE I” before the SIZE command will work.

Note that setting FtpWebRequest.UseBinary to true (which it is by default) does not correct this. When getting the response, an exception will be thrown telling you the file is unavailable and you’ll get a 550 error with the message, “SIZE not allowed in ASCII mode”.

A discussion and Microsoft’s response to this issue is available here; it pretty much boils down to tough noogies, it’ll be fixed in a future version.

.Net FtpWebRequest and 503 (bad sequence of commands) errors

I’ve been working on some FTP code in C# with the .Net framework’s FTP classes and frustrated that I was occasionally getting 503 (bad sequence of commands) errors. Turns out these errors will pop up if the FtpWebRequest.KeepAlive property is set to true, which it is by default. Unfortunately, this doesn’t really address why this is occurring in the first place. I’m doing a lot of multithreaded stuff, so perhaps that’s the culprit (i.e. 2+ threads using the same connection, layering their calls on top of each other). However, I’ve found some forum posts (such as this one) indicating others are having the same issue doing seemingly serial, non-asynchronous stuff.

Suboptimal compression with .Net’s GZipStream

I played around a bit with one of the .Net framework’s compression classes (System.IO.Compression.GZipStream) recently and got some unexpected results. First, the module is a bit weird in how in takes in and outputs data (e.g. for decompression you read directly from the GZipStream, but for compression you read from a MemoryStream), but once you get past this you run into a more significant issue: the compression library is not optimal and, in certain cases, the size of the “compressed” data can be significantly larger than that of the uncompressed input. I did a few ad-hoc and very unscientific tests, but they were good enough to give an indication that there was a problem. GZipStream is probably still good enough when there’s highly compressible data, but for situations where you don’t have any idea of what’s being compressed it’s probably best to look for another solution.

There’s a thread on MSDN about this issue (System.IO.Compression not as good as compressed folder) and also a feedback entry on MS Connect.

Checking if a service is running in C#

Surprisingly easy. I’m doing some bluetooth stuff and needed a way to see if the bluetooth support service (BthServ) was running before attempting bluetooth related system queries and socket IO.

try
{
ServiceProcess.
ServiceController sc = new ServiceProcess.ServiceController("BthServ");
if (sc.Status != ServiceProcess.ServiceControllerStatus.Running)
{
// service not running
}
}
catch (Exception)
{
// service name not recognized
}

How to open the containing folder

Opening a window showing the contents of a folder and highlighting a specific file in the folder can be a pretty useful action, especially for applications that show or list files to the user, as it allows for the user to quickly get to a file and manipulate or open it via. the operating system’s shell. The most popular implementations of this features are, perhaps, in web browsers; it’s referred to by a couple of different phrases, “Open Folder” in IE7, “Show Containing Folder” in Safari, “Open Containing Folder” in Firefox.

Anyways, I wanted this feature for something I’m working on in Windows and it’s actually pretty simple to implement, but it took me a while to find information on it. There’s no Win32 function, instead, explorer has to be run with a command-line switch. Switches and accompanying examples can be found here.

So the command to open a containing folder would be:

explorer /select, <file_path>

Here’s a bit of C# code (it should be simple to do this in almost any language):

System.Diagnostics.Process p1 = new System.Diagnostics.Process();
p1.StartInfo.FileName =
"explorer";
p1.StartInfo.Arguments =
"/select, \"" + <file_path> + "\"";
p1.StartInfo.WorkingDirectory =
Environment.GetEnvironmentVariable("SystemRoot");
p1.StartInfo.UseShellExecute =
true;
p1.Start();

Of course, replace <file_path> with the file you want highlighted.

Based on the info here, as well as the page linked to above, it seems this should work on all versions of Windows since Win 95.