Archives

Archives / 2011 / April
  • Passing managed objects to unmanaged methods as method argument

    It is well documented how to expose a .net class as a COM object through the COM callable wrapper. However, it is not well documented how to pass a .net object to a COM method in an argument and have the COM method treat the .net object as COM. It turns out all we need to do is to add the [ComVisible(true)] to the classes that we need to pass to COM method; runtime would recognize that we are passing the object to COM and generate the COM callable wrapper automatically.

    However, there are some impedance mismatches between COM and .NET. For example, .NET supports method overloading while COM does not. COM objects often uses optional arguments so that the client can pass variable number of arguments to the server. I used the following pattern to expose the Assert object to unmanaged VBScript engine in my VBScriptTest project in ASP Classic Compiler:

            [ComVisible(false)]
            public void AreEqual(object expected, object actual)
            {
                Assert.AreEqual(expected, actual);
            }
            [ComVisible(false)]
            public void AreEqual(object expected, object actual, string message)
            {
                Assert.AreEqual(expected, actual, message);
            }
            [ComVisible(true)]
            public void AreEqual(object expected, object actual, [Optional]object message)
            {
                if (message == null || message == System.Type.Missing)
                    AreEqual(expected, actual);
                else
                    AreEqual(expected, actual, message.ToString());
            }
    

    Note that I marked the first two overloaded methods with [ComVisible(false)] so that they are only visible to other .net objects. Next, I created a COM callable method with an optional parameter. The optional parameter must have the object type; runtime will supply the System.Type.Missing object if a parameter is not supplied by the called. So in the body of the method, I just need to check whether the parameter equals to System.Type.Missing to determine whether the parameter is passed.

  • /Platform:AnyCPU, /Platform:x64, /Platform:x86, what do they mean

    When we build a .net solution, we often see the Platform choice in the configuration manager:

    image

    Besides AnyCPU, other choices are x86 ,x64, and Itanium. What do they mean? According to MSDN, “Anycpu” compiles the assembly to run on any platform while the other 3 choices compiles the assembly for 32 bit, 64 bit x64 and 64bit Itanium respectively.

    On a 64-bit Windows operating system:

    • Assemblies compiled with /platform:x86 will execute on the 32 bit CLR running under WOW64.

    • Executables compiled with the /platform:anycpu will execute on the 64 bit CLR.

    • DLLs compiled with the /platform:anycpu will execute on the same CLR as the process into which it is being loaded.

    If a .net application uses any 32 bit ActiveX component, it will not be able to load the component in-process. We have two choices:

    1. Host the 32 bit component in an external process, such as COM+ Server Application, or
    2. Run the .NET application as a 32 bit application.

    The VBScriptTest project in ASP Classic Compiler contains an unmanaged test. It hosts the msscript.ocx so that I can compare my .net implementation of VBScript against the original VBScript engine from Microsoft. In order to use the 32 bit msscript.ocx, I need to run my unit test in a 32 bit process. NUnit has a 32 bit version of the test runner call NUnit-x86.exe. To use the 32 bit runner, I registered new shell extension as shown below so that I can use the “Run 32 bit NUnit” context menu to invoke the 32 bit NUnit test:

    image

    Lastly, how to run ASP.NET in 32 bit? It turned out that this is controlled by the Application Pool. If I set the “Enabled 32 bit Application” to true in the Advance Property Setting of the application pool, the ASP.NET application will run in 32 bit.

    image

  • Build a very green Windows Server

    My old server consumes about 80W. Given my top tier electricity cost of $0.24/KWh, it costs me about $14 in electricity each month, and generates considerable noise and heat. Recently, I set out to build a greener server. I bought an Intel Atom Dual-Core D525MW Fan-less Motherboard for $80 and a Apex MI-100 mITX case for $40. I also I bough an Kingston 64GB SSD for $75 after rebate. I used 2 x 2GB DDR3 SODIMM RAM and a Toshiba 250GB notebook drive scratched from my recent laptop upgrade. So my total out-of-pocket expense is just under $200 before tax. If I include the cost of retired parts, the hardware cost is about $300. I cloned my Windows 2003 Server OS from my old server into my new server. Although Intel does not supports server OS from desktop boards, I was actually able to install all the necessary drivers from the Intel CD despite the setup program reported installation failure on 3 out of 4 drivers. The new server is barely audible; it is quieter than a outlet timer. Like any machine powered by an SSD drive, it boots up in seconds.

    2011 MVP Summit 016 (600x800)

    So how much power does it consume? My Kill-A-Watt meter tells me that in consumes just under 30 watt at idle. To put that in perspective, my previous Dish Network Receiver and my current Time Warner HD Receiver each consumes about 20 watt at idle. It is quite adequate as my server.

    2011 MVP Summit 017 (480x640)AtomD525

  • ASP Classic Compiler: the unit testing framework is released

    In my previous post, I stressed the importance to have a unit testing framework to move forward with this project. I was facing the decision whether to use NUnit or MSTest. After some thoughts, I came to the conclusion that the choice of unit testing framework is not critical, at least for now. For a language project, unit testing usually falls into two categories: the testing of a parser and the testing of generated code. For parser testing, most of work lies in comparing AST generated by the parser with the expected AST. Paul Vick has an excellent framework in his VBParser work. For testing of the generated code, it is best to have a unit testing framework that is self-contained in the target language so that is can most accurately test the semantics of the language. For example, Javascript has the QUnit framework and ASP Classic has the ASPUnit framework.

    So I went ahead to release my own unit testing framework for VBScript. I created an interface called IAssert that has the following methods:

            void AreEqual(object expected, object actual);

            void AreEqual(object expected, object actual, string message);

            void AreNotEqual(object notExpected, object actual);

            void AreNotEqual(object notExpected, object actual, string message);

            void Fail();

            void Fail(string message);

            void IsFalse(bool condition);

            void IsFalse(bool condition, string message);

            void IsTrue(bool condition);

            void IsTrue(bool condition, string message);

    These are minimum set of method often found in most of unit testing frameworks. We can always add more when needed. Note that I did not have IsEmpty or IsNothing methods. That is because I believe we should use the language built-in method to best reflect the language semantics. For example, instead of having an IsEmpty method in the testing framework, we should use IsTrue(IsEmpty(myVar)) where we are using the VBScript built-in function.

    In environments that we have control over the host, the host will supply an Assert object that can route the testing results to one of the existing unit testing framework, such as NUnit, so that we can reuse the test runners and report functionalities. In the environments that we do not have control of the host, we can supply an Assert class in VBScript itself, much like what ASPUnit does.

    If you look at my VBScriptTest project, you will notice that it uses NUnit framework. It has a single NUnit test case that walks the entire hierarchy under the VBScripts folder. When we need to write a new test case, we just simply add a .vbs file under the VBScripts folder. The following is an example VBScript unit test case:

    dim a
    Assert.IsTrue(IsEmpty(a), "Unassigned variable must be empty")

    Because I have use a single NUnit test case to run all the VBScripts, the message parameter is an important parameter to distinguish the test case in the situation of failed test case.

  • ASP Classic Compiler: the next step

    I opened the source code for my ASP Classic Compiler 2 days ago. As this project was started as a research project, proof of concepts has been a major goal. I have cut corners whenever possible to bring out features fast. Going forward, there are many things that need to be tighten up. The following are my top priorities:

    1. Unit testing: You eager downloaders may have noticed the my project is notoriously missing unit tests. I intentionally took out my unit tests when I upload because my previous unit tests were not well organized. I want to give us chance of a fresh start. Since we will have refactoring and re-architecture of the code generator, unit testing is going to carry this project. Like many open source projects, NUnit or MSTest is a decision to make. I have created this thread in my forum to solicit ideas. I don’t quite need StackOverflow style discussions as there are already plenty. But if you look at recent high profile switches in either directions, you would know this is not an easy decision.
    2. Making it easier for people diagnose problems. A debugger is not going to happen easily, as I have already tried twice. But with source code, it is still possible for people to diagnose problems. This will help reducing the frustration level and getting bug reported and fixed.
    3. VBScript 5.0 support. This is my real top goal since many people requested it, but I could not get there without 1 and 2. I want to take over the memory management since I have already pushed DLR to the limit. Controlling the memory management will open up the possibility for debugging. Details is going to be a blog by itself.
    4. Performance improvement when calling CLR static methods. The TypeModel used in VBScript.NET does not take advantage of call-site caching and is hence very slow. Fortunately, this can be corrected fairly easily.
    5. Optimize for multiple string concatenations. This has been a habit in many ASP projects. I can discover this in code analysis and generate the code behind the scene using StringBuilder. This is a pretty fun research project and it is not too hard.
    6. Type checking in many places can still be optimized for callsite-caching.
    7. Rewrite of the parser. Currently, my VBScript parser is modified from Paul Vick’s VBParser which was written in VB.NET. I have some concern on VB.NET’s timely availability in new platforms (remember Windows Phone 7?). However, since my code generator is tightly coupled to the abstract syntax tree (AST) in the parser project, this is going to be a messy work.