“Unindent” String Extension

I was a little bored and felt like porting mynyml’s unindent gem to C# as an extension method on String:

 

 

And here’s mynyml’s original Ruby code:

 

Code Katas

http://blog.objectmentor.com/articles/2010/04/14/c-tdd-videos-you-asked-for-them
http://www.iamnotmyself.com/2009/10/23/TDDKataCalculatorDemonstration.aspx
http://osherove.com/tdd-kata-1/
http://katas.softwarecraftsmanship.org/
http://rickardnilsson.net/post/2010/07/21/Prime-Factors-Kata.aspx

Delicious.

ASP.NET Development Server v2.0: Faster, Better, Stronger

So here’s the thing – we all hate having to tie our Visual Studio solutions to an IIS web site when the ASP.NET Development Server will do just fine.  Sure, it’s best to test our web apps on a live, flesh and blood IIS server – but for small scale projects, why bother?  You and I are happy to use it 99% of the time…

… but some times we can’t!

That’s right – ASP.NET Development Server refuses remote connections.  What’s an iPhone web app developer to do?  Use IIS so I can establish remote connections from my iPhone?

Hell no!

Ladies and gentlemen, I present to you: ILDASM

Ohhhh yeah!  It’s time to bring out the big guns.  We’re gonna have us a little hackin’ action.  If the dev server doesn’t want to play nice, we’ll make it!

Step 1: Let’s grab the dev server executable.  You can find out where it’s located by debugging a ASP.NET web project, opening the Task Manager and clicking the “Open File Location” on the WebDev.WebServer.EXE.  Copy that file to c:\temp, where we’ll do a little patch work later on.  In my case, it’s in the following folder:  C:\Program Files (x86)\Common Files\microsoft shared\DevServer\10.0

Step 2: It’s time to perform open heart surgery.  Grab Reflector, and let’s get to work.  Drag and drop the executable onto Reflector and take a look around.  You’ll notice that there’s nothing of real interest here – it delegates most of the heavy lifting to the WebDev.WebHost40 assembly.  Let’s figure out where that is like so:

Now that we know where it is, let’s copy that to c:\temp:

xcopy C:\Windows\Microsoft.Net\assembly\GAC_32\WebDev.WebHost40\v4.0_10.0.0.0__b03f5f7f11d50a3a\WebDev.WebHost40.dll c:\temp

Step 3: Back to Reflector!  Let’s take a look around for a sec…  Did you notice the Request class?  Let’s take a look there.  Ah!  Request.Process() looks rather suspicious:

[AspNetHostingPermission(SecurityAction.Assert, Level=AspNetHostingPermissionLevel.Medium)]
public void Process()
{
    if (this.TryParseRequest())
    {
        if (((this._verb == "POST") && (this._contentLength > 0)) && (this._preloadedContentLength < this._contentLength))
        {
            this._connection.Write100Continue();
        }
        if (!this._host.RequireAuthentication || this.TryNtlmAuthenticate())
        {
            if (this._isClientScriptPath)
            {
                this._connection.WriteEntireResponseFromFile(this._host.PhysicalClientScriptPath + this._path.Substring(this._host.NormalizedClientScriptPath.Length), false);
            }
            else if (this.IsRequestForRestrictedDirectory())
            {
                this._connection.WriteErrorAndClose(0x193);
            }
            else if (!this.ProcessDefaultDocumentRequest())
            {
                this.PrepareResponse();
                HttpRuntime.ProcessRequest(this);
            }
        }
    }
}

Hmmm… that call to TryParseRequest()… let’s take a look:

private bool TryParseRequest()
{
    this.Reset();
    this.ReadAllHeaders();
    if (!this._connection.IsLocal)
    {
        this._connection.WriteErrorAndClose(0x193);
        return false;
    }
    if (((this._headerBytes == null) || (this._endHeadersOffset < 0)) || ((this._headerByteStrings == null) || (this._headerByteStrings.Count == 0)))
    {
        this._connection.WriteErrorAndClose(400);
        return false;
    }
    this.ParseRequestLine();
    if (this.IsBadPath())
    {
        this._connection.WriteErrorAndClose(400);
        return false;
    }
    if (!this._host.IsVirtualPathInApp(this._path, out this._isClientScriptPath))
    {
        this._connection.WriteErrorAndClose(0x194);
        return false;
    }
    this.ParseHeaders();
    this.ParsePostedContent();
    return true;
}

Busted! If the connection is not local, return a 403 and close the connection – WriteErrorAndClose(0×193). Let’s put this on our naughty list – we’ll get back to it later on.

Step 4: Hunt down the Loopbacks!  Here’s Server.Start():

public void Start()
{
    try
    {
        this._socket = this.CreateSocketBindAndListen(AddressFamily.InterNetwork, IPAddress.Loopback, this._port);
    }
    catch (Exception exception)
    {
        SocketException exception2 = exception as SocketException;
        if ((exception2 != null) && (exception2.SocketErrorCode == SocketError.AddressAlreadyInUse))
        {
            throw exception;
        }
        this._socket = this.CreateSocketBindAndListen(AddressFamily.InterNetworkV6, IPAddress.IPv6Loopback, this._port);
    }
    if (this._socket != null)
    {
        ThreadPool.QueueUserWorkItem(this._onStart);
    }
}

Those Loopbacks gotta go.

Step 5: It’s surgery time.  Use ILDASM to dump WebDev.WebServer.EXE and WebDev.WebHost40.dll to c:\temp\server\WebDev.WebServer.IL and c:\temp\host\WebDev.WebHost40.IL, respectively.  When prompted, tick each checkbox on the output options.

Let’s start with the host.  Open up WebDev.WebHost40.IL, preferably with a real text editor.  Let’s first find those Loopbacks – locate the Server.Start() method:

  .method /*0600009B*/ public hidebysig instance void
          Start() cil managed
  // SIG: 20 00 01
  {

Now, replace Loopback and IPV6Loopback with Any and IPV6Any, respectively. In other words, this:

IL_0003:  /* 7E   | (0A)0000A4       */ ldsfld     class [System/*23000003*/]System.Net.IPAddress/*01000015*/ [System/*23000003*/]System.Net.IPAddress/*01000015*/::Loopback /* 0A0000A4 */

becomes:

IL_0003:  /* 7E   | (0A)0000A4       */ ldsfld     class [System/*23000003*/]System.Net.IPAddress/*01000015*/ [System/*23000003*/]System.Net.IPAddress/*01000015*/::Any /* 0A0000A4 */

Great! Now it’ll accept connections – but it will still respond with a 403 and drop the connection – no bueno!  Let’s fix it.

Here’s the offending code:

    if (!this._connection.IsLocal)
    {
        this._connection.WriteErrorAndClose(0x193);
        return false;
    }

That translates to the following IL (from the TryParseRequest() method):

                                         // if (this._connection.IsLocal) goto IL_002b
    IL_000c:  /* 02   |                  */ ldarg.0
    IL_000d:  /* 7B   | (04)00004E       */ ldfld      class Microsoft.VisualStudio.WebHost.Connection/*02000004*/ Microsoft.VisualStudio.WebHost.Request/*0200000B*/::_connection /* 0400004E */
    IL_0012:  /* 6F   | (06)000015       */ callvirt   instance bool Microsoft.VisualStudio.WebHost.Connection/*02000004*/::get_IsLocal() /* 06000015 */
    IL_0017:  /* 2D   | 12               */ brtrue.s   IL_002b

                                         // this._connection.WriteErrorAndClose(403); return;
    IL_0019:  /* 02   |                  */ ldarg.0
    IL_001a:  /* 7B   | (04)00004E       */ ldfld      class Microsoft.VisualStudio.WebHost.Connection/*02000004*/ Microsoft.VisualStudio.WebHost.Request/*0200000B*/::_connection /* 0400004E */
    IL_001f:  /* 20   | 93010000         */ ldc.i4     0x193
    IL_0024:  /* 6F   | (06)000023       */ callvirt   instance void Microsoft.VisualStudio.WebHost.Connection/*02000004*/::WriteErrorAndClose(int32) /* 06000023 */
    IL_0029:  /* 16   |                  */ ldc.i4.0
    IL_002a:  /* 2A   |                  */ ret

    // blah blah blah . . .

Pretty simple, right? If the connection is local, branch – go to IL_002b and continue processing. There’s several ways you can fix this – my suggestion is that you just replace the “this._connection.WriteErrorAndClose(403)” code with NOPs. Here’s what you end up with:

    IL_0019:   nop
    IL_001a:   nop
    IL_001b:   nop
    IL_001c:   nop
    IL_001d:   nop
    IL_001e:   nop
    IL_001f:   nop
    IL_0020:   nop
    IL_0021:   nop
    IL_0022:   nop
    IL_0023:   nop
    IL_0024:   nop
    IL_0025:   nop
    IL_0026:   nop
    IL_0027:   nop
    IL_0028:   nop
    IL_0029:   nop
    IL_002a:   nop

Yay! One last little change:

.assembly /*20000001*/ WebDev.WebHost40
{
  // blah blah blah
  .ver 10:0:0:0 // Let's bump this up to .ver 10:1:0:0
}

Now, create a strong name key using Sn.exe. After you have your snk, compile the IL using:

ilasm /dll /resource=webdev.webhost40.res /key=c:\temp\mykey.snk webdev.webhost40.il

Install the assembly into the GAC:

gacutil /i c:\temp\webdev.webhost.dll

One assembly down, one more to go; we still need to update the web server’s reference to the new WebDev.WebHost40.  Open up WebDev.WebServer40.IL and change this:

.assembly extern /*23000005*/ WebDev.WebHost40
{
  .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A )
  .ver 10:0:0:0
}

to

.assembly extern /*23000005*/ WebDev.WebHost40
{
  .publickeytoken = (00 00 00 00 00 00 00 00 ) // put _YOUR_ public key here!!!
  .ver 10:1:0:0
}

Now it’s time to compile using ilasm: ilasm /exe /resource=WebDev.WebServer40.res /key=c:\temp\mykey.snk WebDev.WebServer40.il

Give it a test:

c:\temp\server\WebDev.WebServer40.exe /port:1234 /path:c:\path\to\website /vpath:website [/ntlm]

You’re golden, Ponyboy! Create a backup folder in your DevServer\10.0 folder, then feel free to replace the original executable with your patched version.

Enumerating Resources in Silverlight

Thanks go to Alex Gosh for the following code snippet – I wouldn’t have figured this out without his blog post:

The ResourceInspector class provides an easy way to inspect the Resources within your Silverlight assemblies. The inspect method returns an IDictionary where each key/value pair consists of the resource name and the appropriate uri. If you combine this with Jason Cooke’s WebXapFileLoader and XapInspector, you’ll be able to enumerate all “Content” and “Resource” files at runtime.

Implications for the DLR

The nice thing about this discovery is that I’ll be able to create a custom Platform Adaption Layer with additional features. The current BrowserPAL is limited to providing a Stream instance when given a known “Content” file name – it does not support “Resource” files from arbitrary assemblies, and you can’t enumerate the files within the virtual file system. As a result, the following IronRuby code will throw a “NotImplementedException”:

Dir.glob ‘.’

However, it’s possible to implement a custom PAL (using the code snippet above) that would allow DLR languages to enumerate the files contained within the XAP and assemblies. I’ll try to whip up a proof of concept soon and post it here.

Cheers,
-Charles

How to Configure IronRuby in Silverlight

In this post I’ll show you some tips when working with IronRuby in Silverlight. While you can use almost identical code whether you’re working on the desktop or within the browser, you’ll have to make a few tweaks if you want to do any file operations from Ruby (ex: File.open ‘some_image.png’, require ‘foo’, etc). Make sure that you set the “Build Action” to “Content” for each script and/or resource in your project.

The Platform Adaption Layer (PAL)

The DLR provides an abstraction over platform functionality using PlatformAdaptionLayers (PALs). In order to read from your XAP’s contents you’ll need to use the BrowserScriptHost, which delegates to the BrowserPAL class. Here’s a snippet I like to use to configure my my Ruby ScriptRuntime to use the BrowserScriptHost:

private ScriptRuntimeSetup GetSetup()
{
    // Standard options
    var typeName = typeof (RubyContext).AssemblyQualifiedName;
    var displayName = "IronRuby";
    var names = new List<string> {"IronRuby", "Ruby", "rb"};
    var exts = new List<string> { ".rb" };

    var setup = new ScriptRuntimeSetup();
    setup.HostType = typeof(BrowserScriptHost);
    setup.LanguageSetups.Add(new LanguageSetup(typeName, displayName, names, exts));
    return setup;
}

// ...

var setup = GetSetup();
var runtime = IronRuby.Ruby.CreateRuntime(setup);
var engine = runtime.GetEngine("rb");
var context = (RubyContext)HostingHelpers.GetLanguageContext(engine);

Add a REPL to the Page

Another indispensible trick is to add a REPL to the page:

// Insert REPL into DOM
HtmlElement replDiv;
var repl = Repl.Create(engine, engine.CreateScope(), out replDiv);
HtmlPage.Document.Body.AppendChild(replDiv);
repl.Start();

context.StandardOutput = repl.OutputBuffer;
context.StandardErrorOutput = repl.OutputBuffer;

Using the Scala Plugin in IntelliJ IDEA

Getting Started

First, check out jetbrain’s documentation on the Scala plugin. Read through “Setting up the Environment” to figure out how to install the plugin. Next, create a project using steps 1 and 2 from “Hello World with Scala in 7 Steps”. Now, go through the rest of the steps and make sure everything is working. If you get the example working, congrats! You can stop reading this post and start hacking. If things didn’t turn out so peachy, keep reading.

When Things Go Wrong…

Now, there’s a possibility that you’ll see the following error in your “Run” window:

java.lang.ClassNotFoundException

If so, you’ll need to “refresh” the project settings. Follow these steps:

  1. Right click your project in the source tree and left click “Module Settings”
  2. Under “Project Settings”, left click “Modules”
  3. Expand your project tree and left click “Scala”
  4. Under “Project Settings”, left click “Facets”
  5. Expand the “Scala” node and left click “Scala (<project_name_here>)”
  6. Click “Apply”, followed by “OK”

That should fix the project. The reason you might need to do this is because the Scala compiler and library settings are not set properly. Touching these settings once will cause these settings to be properly configured.

Setting an SSH Key’s Password

This was a royal pain in the ass to figure out, so hopefully this’ll save you or someone else some time. What follows is pretty much copied verbatim from the following site:
http://www.noah.org/wiki/SSH_public_keys

Note to Windows/msysgit users: the following commands will work without a hitch if you run them from the “GIT Bash”. Otherwise, you’ll need to ensure that openssl is on your PATH. I’m assuming here that your key is located at %userprofile%/.ssh/id_rsa.

Unencrypt your existing key

If your existing key is encrypted (read: has a password), you’ll need to remove the encryption first (this will obviously overwrite the existing key file):
openssl rsa -in ~/.ssh/id_rsa -out ~/.ssh/id_rsa

Encrypt your existing key

Once you’ve unencrypted your key, you’ll need to re-encrypt it (this will obviously overwrite the existing key file):
openssl rsa -des3 -in ~/.ssh/id_rsa -out ~/.ssh/id_rsa

When you run the above command, you’ll be prompted for your new password.

Tags:

Why Crystal Reports Sucks

Trying to change the Datasource for your report? Too bad- you can’t…
http://forums.sdn.sap.com/thread.jspa?threadID=1501902&start=0&tstart=0

… unless you manually set the “Overriden Qualified Table Name” property under “Set Datasource Location”.

Thanks Crystal Reports for blowing several hours of my life away.

COM Magic in C#

I’m no COM wizard, but I did learn something interesting today. C# allows you to “new up” a COM interface from a PIA as if it were a class. This caught me by surprise today when I was playing around with COM & IronRuby – I couldn’t instantiate COM objects like I could in C#!

Out of curiosity, I disassembled (using Reflector ) a snippet of C# code where I was instantiating an Outlook Applicaition; here’s what I found:

// This...
var app = new Microsoft.Office.Interop.Outlook.Application();

// ... is compiled like this:
var app =((Microsoft.Office.Interop.Outlook.Application)
  Activator.CreateInstance(Type.GetTypeFromCLSID(new Guid("0006F03A-0000-0000-C000-000000000046")), args));

Isn’t that fascinating! How is the C# compiler finding the correct CLSID for the Outlook.Application interface?

I’m not really sure… but here’s my stab at pulling this off:

// Get the PIA assemby name, using the GUID of the typlib.
// Alternatively, we can skip this if we already know the assembly name.
string asmName;
string asmCodeBase;
var conv = new System.Runtime.InteropServices.TypeLibConverter();
conv.GetPrimaryInteropAssembly(new Guid("00062FFF-0000-0000-C000-000000000046"), 9, 3, 0, out asmName, out asmCodeBase);

// Load the PIA, and get the interface type
var assembly = System.Reflection.Assembly.Load(asmName);
var type = assembly.GetType("Microsoft.Office.Interop.Outlook.Application");

// Get the coclass
var coClassAttr = (System.Runtime.InteropServices.CoClassAttribute)
    type.GetCustomAttributes(typeof(System.Runtime.InteropServices.CoClassAttribute), false)[0];
var coClass = coClassAttr.CoClass;

// Get the CLSID
var clsid = coClass.GUID;

You can also do pretty much the same thing in IronRuby (although you really should use WIN32OLE):

# The typlib details
ol_guid  = System::Guid.new("00062FFF-0000-0000-C000-000000000046".to_clr_string)
ol_major = 9
ol_minor = 3
ol_lcid  = 0

# Get the PIA's assembly name
conv = System::Runtime::InteropServices::TypeLibConverter.new
result, asm_name, asm_code_base = conv.GetPrimaryInteropAssembly(ol_guid, ol_major, ol_minor, ol_lcid)

# Load the assembly
require asm_name

include Microsoft::Office::Interop

def create_com_object(com_module)
  coClass = com_module.to_clr_type.get_custom_attributes(
    System::Runtime::InteropServices::CoClassAttribute.to_clr_type, false)[0].CoClass

  System::Activator.CreateInstance(coClass)
end

app = create_com_object(Outlook::Application)

As I mentioned above, using WIN32OLE is a much better idea:

require 'win32ole'

app = WIN32OLE.new('Outlook.Application')

Visual Studio Extensibility

Look like I’m going to be busy figuring out how to extend Visual Studio 2010… just for the fun of it. I know the Spark View Engine’s VS2010 integration needs some work… perhaps I’ll start there.

Links