I know the answer (it's 42)

A blog on coding, .NET, .NET Compact Framework and life in general....

February, 2006

Posts
  • I know the answer (it's 42)

    What's in a name

    • 5 Comments

    The other day I went out to dinner to Fareast with my wife and daughter. On the way out I met a group of people who had come down from USA. They had their 8-month old daughter with them. In the casual chat that followed one of them asked my daughter's name and I answered Prokriti. I was kind of surprised by the question that followed. The gentleman asked me what the name means (BTW it means Nature in Bangla and Hindi)

    This brings up an interesting side to Indian names which that gentlemen seemed to know, most people's name in India have a meaning or some other significance like the name of some God/Goddess or some other mythological significance. AFAIK, this is not true in Western countries. I'll take some examples.

    Abhinaba (my name) => Unprecedented
    Somtapa (my wife) => One who worships the moon goddess.
    Hemant (friend) => Spring season in Sanskrit/hindi
    Mohor (sister) => Golden coin
    Pralay (friend) => Doom, cataclysm

    A lot of times the names are based on the names of some god or goddess like Shiva, Vishnu, Durga.

    Sometimes these names become kind of funny. For example long back I met someone with the name Nirdosh, which meant not-guilty. I couldn't figure out what lead his parents to name him such :)

  • I know the answer (it's 42)

    Virtual method calls from constructors

    • 10 Comments

    C++ and C# varies considerably in how virtual method calls from constructors work. I feel that the approach taken by C++ is significantly better. Let's consider the following code in C++.

    #include <iostream>
    using namespace std;
    class Base
    {
    public:
        Base()
        {
            Foo();
        }
        virtual void Foo()
        {
            cout << "Base::Foo" << endl;
        }
    };
    
    class Derived : Base
    {
    public:
        Derived()
        {
        }
        void  Foo()
        {
            cout << "Derived::Foo" << endl;
        }
    };
    Derived* der = new Derived();

    The output of the program is Base::Foo.

    Here the Base class constructor is calling the virtual method Foo. In C++  (as with most OO language) the Base class is created before the Derived class and hence the base class constructor is called first. So when the call to Foo is made in Base::Base(), Derived is not yet created and hence the call Foo() ends in Base::Foo and not its override in Derived::Foo.

    In C# the behavior is different and always the most derived override is called.

    class Base
    {
        public Base()
        {
            Foo();
        }
    
        public virtual void Foo()
        {
            Console.WriteLine("Base::Foo");
        }
    }
    
    class Derived : Base
    {
        string str = null;
        public Derived()
        {
            str = "Hello world";
        }
    
        public override void  Foo()
        {
            Console.WriteLine("Derived::Foo");
            //Console.WriteLine(str);
        }
    }
    
    class Program
    {
        static void Main(string[] args)
        {
            Derived der = new Derived();
        }
    }

    In this case the output is Derived::Foo. Even in C# the base class is created first and its constructor is called first. However calls to virtual methods always land on the most derived version which in this case is Derived::Foo().

    However there are issues with this. Even though Derived::Foo gets called, Derived class is still not initialized properly and its constructor is not yet called. In the above code the variable str is not initialized and if it is referred from Derived::Foo a null reference will occur. So I tend to believe that even though C++ implementation needs a bit more understanding of object creation (vtable build-up) it is safer.

    Due to all these subtleties its always recommended to not refer to virtual methods from ctors. If for example you are writing some code that will be used by others (as in Frameworks) then this may break the client developers if they derive from your class. They may never anticipate that calls to their overrides may hit un-initialized variables which they have explicitly initialized in the derived class's constructor.

  • I know the answer (it's 42)

    Code Generation in multiple languages

    • 8 Comments

    I'm currently working on a personal project that needs to spit out code after parsing some XML file. I had previously used the .NET frameworks CodeDom to do on the fly compilation and hence tried digging it up to see if I could use it for code generation. In a small time I was completely blown over by the feature set and what I could achieve in a relatively small time.

    I had initially expected to get little support from the framework and had thought I'd manipulate text to generate the C# code. I now figured out that I could use the CodeDom to build the code structure hierarchy and just pass on a language parameter and if that language is supported generate code using that language. Suddenly my application was not limited to C# but I could use VB.NET or VJ# for my output code as well. To demonstrate this I'd skip the XML parsing (serialization and logic) part. The following code generates a hello world program in any of the supported .NET language

    private void BtnGenerate_Click(object sender, EventArgs e)
    {

    TextCode.Text = GenerateCode("C#");
    TextCode.Text += GenerateCode("VJ#");
    TextCode.Text += GenerateCode("VB");
    }
    public string GenerateCode(string language)
    {
    // get CodeDom provider from the language name
    CodeDomProvider provider =
    CSharpCodeProvider.CreateProvider(language);
    // generate the code
    return GenerateCode(provider);
    }


    public string GenerateCode(CodeDomProvider provider)
    {
    // open string based in memory streams
    using(StringWriter writer = new StringWriter())
    using (IndentedTextWriter tw =
    new IndentedTextWriter(writer, " "))
    {
    // create top level namespace
    CodeNamespace myNamespace =
    new CodeNamespace("AbhinabaNameSpace");
    // create file level comment
    CodeComment comment = new CodeComment(
    string.Format("Generated on {0}",
    DateTime.Now.ToLocalTime().ToShortDateString()),
    false);
    CodeCommentStatement commentStatement =
    new CodeCommentStatement(comment);
    myNamespace.Comments.Add(commentStatement);
    // add using statements for the required namespaces
    myNamespace.Imports.Add(
    new CodeNamespaceImport("System"));
    // define the one and only class
    CodeTypeDeclaration mainClass =
    new CodeTypeDeclaration();
    mainClass.IsClass =
    true;
    mainClass.Name =
    "HelloWorldMainClass";
    mainClass.Attributes =
    MemberAttributes.Public;
    myNamespace.Types.Add(mainClass);
    //define the entry point which'd be
    //Main method in C#
    CodeEntryPointMethod mainMethod =
    new CodeEntryPointMethod();
    mainMethod.Comments.Add(
    new CodeCommentStatement("<summary>", true));
    mainMethod.Comments.Add(
    new CodeCommentStatement("Entry point", true));
    mainMethod.Comments.Add(
    new CodeCommentStatement("</summary>", true));
    mainClass.Members.Add(mainMethod);
    //define the string variable message
    CodeVariableDeclarationStatement strDecl =
    new CodeVariableDeclarationStatement(
    new CodeTypeReference(typeof(string)),
    "message");
    mainMethod.Statements.Add(strDecl);
    //create the message = "hello world" statement
    CodeAssignStatement ptxAssign =
    new CodeAssignStatement(
    new CodeVariableReferenceExpression("message"),
    new CodeSnippetExpression("\"hello world\""));
    mainMethod.Statements.Add(ptxAssign);
    //call console.writeline to print the statement
    CodeMethodInvokeExpression invokeConsoleWriteLine =
    new CodeMethodInvokeExpression(
    new CodeTypeReferenceExpression(typeof(Console)),

    "WriteLine",
    new CodeExpression[]
    {
    new CodeArgumentReferenceExpression(
    "message"),
    }
    );
    mainMethod.Statements.Add(invokeConsoleWriteLine);
    // code generation options
    CodeGeneratorOptions opt = new CodeGeneratorOptions();
    opt.BracingStyle = "C";
    opt.BlankLinesBetweenMembers = false;
    // generate the code and return it
    provider.GenerateCodeFromNamespace(myNamespace, tw, opt);
    return writer.ToString();
    }
    }

    If only more languages were on .NET I could build the list in http://www2.latech.edu/~acm/HelloWorld.shtml in about couple of hours :)

    I get the following output

    In C#
    =======
    // Generated on 2/27/2006
    namespace AbhinabaNameSpace
    {
        using System;
        
        public class HelloWorldMainClass
        {
            /// 
            /// Entry point
            /// 
            public static void Main()
            {
                string message;
                message = "hello world";
                System.Console.WriteLine(message);
            }
        }
    }
    
    VJ#
    =======
    // Generated on 2/27/2006
    package AbhinabaNameSpace;
    import System.*;
    
    public class HelloWorldMainClass
    {
        /** Entry point */
        public static void main(String[] args)
        {
            String message;
            message = "hello world";
            System.Console.WriteLine(message);
        }
    }
    
    
    
    VB
    =======
    Imports System
    
    'Generated on 2/27/2006
    Namespace AbhinabaNameSpace
        Public Class HelloWorldMainClass
            '''
            '''Entry point
            '''
            Public Shared Sub Main()
                Dim message As String
                message = "hello world"
                System.Console.WriteLine(message)
            End Sub
        End Class
    End Namespace
    
  • I know the answer (it's 42)

    unsafe C# code

    • 5 Comments

    In all the code I wrote for VSTF I never used unsafe C# code. However, recently I was writing a tool which needed some unsafe code (sizeof in particular).

    While writing the code I thought of some quick points to remember while using unsafe code.

    Do not use redundant unsafe context

    In C#2.0 you no longer need to use unsafe context while applying sizeof to predefined types. This means the following code compiles without any unsafe context.

    class MyClass
    {
    static public void Foo()
    {

    Console
    .WriteLine(sizeof(int));
    Console
    .WriteLine(sizeof(byte));
    }
    }

    Limit the scope of the unsafe context

    Locate the minimal scope of unsafe code and apply either the unsafe modifier or unsafe statement over that minimal scope only.

    The following is bad, because other methods in the class are also included in the unsafe context and unintentinally unsafe code may creep into them.

    unsafe class MyClass
    {
    static public void Foo()
    {

    Console
    .WriteLine(sizeof(MyStruct));
    }
    }

    The following is better because only required methods are marked as unsafe.

    class MyClass
    {
    unsafe static public void Foo()
    {

    Console.WriteLine(sizeof(MyStruct));
    }
    }

    The following is the best option if you have unsafe code only in limited places, as this gives the unsafe context only to the minimal scope (statement level).

    class MyClass
    {
    static public void Foo()
    {
    unsafe
    {
    Console.WriteLine(sizeof(MyStruct));

    }
    }
    }

    Be careful about subtle syntax difference

    Most commonly these unsafe features get used by C/C++ programmers moving into C#. The syntax looks deceptively similar to C/C++ but sometimes varies. The following statment is valid C/C++ and valid C# as well.

    int * a, b;

    However, in C/C++ it means that a is a pointer and b is not but in C# a and b are both pointers to ints. So in C# * should be written with type as in int* and not with the pointer name.

    Becareful about what pointers you return

    This is equally true for C/C++. You must ensure that you are not returning a pointer (as return value or ref/out arguments) that points to a local variable. Once the function returns the stack is popped and the local variables are gone. So the returned pointers become dangling pointers if they pointed to some local variables

    You can't point to everything

    Everything that resides in the manages heap can be moved around (relocated) by the garbage-collector and therefore it is not possible to have pointers to it directly. You can have pointers only to fixed variables. Fixed variables include stuff that is on the stack like local variables and value-type function-parameters. You can also take pointers to variables on the heap after pinning them with a fixed expression

    class MyClass
    {
    static int statNum = 50;
    unsafe static public void Bar(int paramNum)
    {
    int localNum;
    int* ap;
    ap = &localNum;
    //local variable
    ap = &paramNum; //value-type argument
    //pin so that the address don't change
    fixed(int* apnew = &statNum)
    {
    Console.WriteLine(*apnew);
    }
    }
    }

    Avoid unsafe code and pointers

    There was a reson for which pointers were excluded in core C#. Even though pointers make a language very powerfull they introduce complexity and pointer related bugs like dangling pointers, overrun, type-unsafety plague the software. C/C++ programmers have a habit of using unsafe context even when they are not required and this is a habit that may lead to trouble in the .NET world. Use unsafe code only when absolutely necessary....

  • I know the answer (it's 42)

    optional arguments in C#

    • 20 Comments

    <Note: Optional arguments are now available as of C# 2010 /> 

    One of the things I missed a lot when I moved to C# is optional arguments. In C++ optional arguments are used a lot. Code as below is a common sight.

    void foo(int reqdParam, int optParam = 0)

    {

    // ...

    }

     

    foo(5); // gets compiled as foo(5,0)

    foo(5, 10);

    The reason it is not included in C# is mainly due to versioning problem. Optional arguments are handled in most programming languages by inserting the default value of the optional argument at the call site. So for the above code foo(5) is compiled as foo(5, 0).

    The versioning issue comes to play if the call site and the method are in different assemblies. In the next version of the method the default value of optParam may change from 0 to 1 and 0 can become an unsupported value. However the calling code will still contain 0 and hence we may get a run-time issue. The way to get around is re-compiling all the assemblies that contains calls to the method and this simply does not scale.

    Another way of handling optional argument would be to automatically generate method overloads based on optional arguments. So the above code on compilation would yield something like

    void foo(int reqdParam)

    {

    foo(reqdParam, 0)

    }

    void foo(int reqdParam, int optParam)

    {

    // ...

    }

     

    foo(5); // calls the first overload

    foo(5, 10); // calls the actual function

    This is versioning safe. However this is not used by most languages including C#. I do not know why this is not used. This is versioning safe and at the same time gives all the benefits of optional arguments. Side effects would be code-bloat, inclusion of these methods in the call-stack.

  • I know the answer (it's 42)

    Scroll bars, elevators and the world of altered reality

    • 6 Comments

    In the initial years user interfaces derived heavily from real-life objects. Common examples include buttons, spin controls, dials, check-boxes and radio-buttons. Modern UI design relies on prior Computer exposure of general public and controls are now designed for the user-interfaces directly and not modeled on objects. Today we no-longer see the 3d button like controls in tool bars. There are exceptions like media players and clocks, but they have exact real-world couterparts.

    One of the things that worked somewhat opposite to the real-world is the scroll-bar. When we read from a piece of paper, we move the paper up to continue reading it. However on-screen we click on the down arrow below the scroll bar to make the document move up. Some software like Adobe Acrobat models there user-experience on the real-world. There you have the option of using the Hand Tool to grab the document and push it up, as you'd do with a piece of paper.

    Its funny to notice that most people are more comfortable with the scroll bar and not with this hand tool. Dominant software makes users conditioned to do things is a way so much so that they start feeling that this is indeed the right way to go.

    I have noticed a very similar thing with elevators. In developed countries its hard (or impossible) to find someone not accustomed to elevators. But in developing countries like India you sometimes do find people who are not very familiar with it. For them elevators are like cabs, they figure out they need to summon it and once inside need to tell it which direction to go. For them the usage pattern is very different. If they need to go down and the elevator is on some floor below them, they'll press the up button to call the elevator. When inside they'll press the down button. But to their astonishment it'll go to floors above them first.

  • I know the answer (it's 42)

    Abstract base class over interface

    • 10 Comments

    Currently I'm reading the book Framework Design Guidelines. This is one of the best books I have read in some time. Most books that cover design in general are one-sided and high-lights the author's beliefs and convictions. However, this book is very different. It gives suggestions about various framework design aspects and at the same time high-lights views/opinions of different people in the .NET team which doesn't necessarily conform to the guidelines. This makes the book a very interesting read.

    One of the suggestions is "Favor defining classes over interface". While this is highly debatable, I agree to this in general. In this section I read a comment from Brian Pepin that reminded me of some framework code I saw long time back which convinced me that Abstract Base Classes are sometimes much superior to interfaces in defining contracts.

    In that UI framework one of the requirements was that individual controls should support loading bitmaps that act as application skins with the following method prototypes....

    void LoadBitmap(string fileName);
    void LoadBitmap(string fileName, Color transparentCol);
    void LoadBitmap(string fileName, int width, int height);
    void LoadBitmap(string fileName, Color transparentCol,
    int width, int
    height);

    The last method is the actual implementation and all the other methods fill in default values and passes it to this method.

    In case this was defined in an interface as in

    public interface ILoadBitmap

    {
    void LoadBitmap(string fileName);
    void LoadBitmap(string fileName, Color transparentCol);
    void LoadBitmap(string fileName, int width, int height);
    void LoadBitmap(string fileName, Color transparentCol,
    int width, int height);
    }

    All classes that implemented the interface had to do method parameter validation for all the 4 methods and call the last method passing the default value for the parameters not specified. Not only this becomes tedious if some 20 types of controls supported skinning, it leads to programmer error in which a wrong default value is passed in some of the controls. This is where Abstract Base Class comes in. Using ABC you can code this as

    public abstract class SkinControl

    {
    public void LoadBitmap(string fileName)
    {
    Debug.Assert(!string.IsNullOrEmpty(fileName));
    LoadBitmap(fileName,
    Color.Magenta, -1, -1);
    }
    public void LoadBitmap(string fileName, Color transparentCol)
    {
    Debug.Assert(!string.IsNullOrEmpty(fileName));
    LoadBitmap(fileName, transparentCol, -1, -1);
    }
    public void LoadBitmap(string fileName, int width, int height)
    {
    Debug.Assert(!string.IsNullOrEmpty(fileName));
    Debug.Assert(width > 0 && height > 0);
    LoadBitmap(fileName,
    Color.Magenta, width, height);
    }
    public abstract void LoadBitmap(string fileName,
    Color transparentCol,
    int width, int height);
    }

    public
    class SkinnedButton : SkinControl

    {
    public override void LoadBitmap(string fileName,
    Color transparentCol,
    int width, int height)
    {
    // Actual implementation


    }
    }

    All the methods are implemented in the ABC and only the last method is made abstract. So for all classes that implements this abstract class the developer needs to implement the fourth overload of the method only. Most of the contract is directly coded into the ABC. This results in less code and less programming error.

  • I know the answer (it's 42)

    localized C#

    • 19 Comments
    C# and .NET supports Unicode and it’s super-cool that you can use variables and literals in your own language and get it to build and run. I never tried that out until I read Brad Adams post. I wrote the following program in C# using Hindi to name variables and namespaces.
    using System;

    using System.Collections.Generic;

    using System.Text;

    namespace मेराप्रोग्राम
    {
    class प्रोग्राम

    {
    static void Main(string[] arg)
    {
    for (int संख्या = 0; संख्या < 10; संख्या++)
    {
    Console.WriteLine("क्रम {0}", संख्या);
    }
    }
    }
    }

    Michael Kaplan's post prompted me to share this code out. IMO most developers are forced to learn English. The reason is evident from the code above. Even if all documentations are available in localized version, I still need to know what's the meaning of the term "using", "for" and "class".

    I always thought that I'd hack the Mono csharp compiler to create a language that'll be truly localized as in have localized keywords and support localized numbers as well. I looked into the mono-sources long back and remember seeing the file cs-tokenizer.cs which looked promising as it contained the list of keywords. Once VSTS is shipped I think I'll have some time to try that out.

  • I know the answer (it's 42)

    I just hit a century

    • 4 Comments

    I was reading Mike Stall's blog and he said that his last post was #200. This got me thinking and I went to check my blog-stat. My blog admin page currently states Total Posts: 100

    So this means I just hit a century. This is a cricket term and I intentionally used it tell some people that just as you do not understand cricket we do not understand Super Bowl (American Football) jargon either :)

    I initially started this blog to rant about Team System, but it looks like I am ranting more about C#/.NET these days. In future I intend to keep it this way.

    I also hope that I do not act like Tendulkar and get out soon after my century. (This is another cricketing thing for folks who talks too much about Super Bowl in their blogs :)

  • I know the answer (it's 42)

    C#: Writing extendable applications using on-the-fly compilation

    • 10 Comments

    Sometime back I had posted about writing applications that can load plugins using late binding. Users can drop assemblies in a specific folders which is scanned by an host application at startup. Using reflection the host can locate classes that implement a specific interface and instantiate those classes as plugins. The drawback is that the host processes plugin assemblies and you need to store/maintain the corresponding sources elsewhere.

    This can be extended using on the fly compilation. In this technique the user drops source files in a specific folder and the host-application either at startup or on user request compiles the sources in-memory and loads the generated assembly. The sources can be in any of the .NET languages like C#, VB.NET or J#.  The whole of this can be trivially accomplished using the Microsoft.CSharp and the System.CodeDom.Compiler namespaces from System.dll.

    We can call these sources as scripts as they are available as sources. However, in the truest sense they are not scripts because they are not interpreted but are compiled and executed. They are more of plugins where the step of compilation is done by the host application.

    There are several security issues to be considered before using this technique and so you might want to read the drawbacks section at the end of this post before trying this out.

    The Common Contract

    The first and one of the most important things to decide is the Document Object Model or the DOM that the host-application exposes. The DOM is used by the script to manipulate the host-application. Similarly it's also important to decide the interface that the script exposes so that the host application can locate the script class in the script-source and instantiate the class. The DOM and the script interface together form the SW contract that both parties use to communicate with each other.

    It's best to define the DOM and the script interface in a common extension dll and make both the host application and all scripts refer to it. The DOM is also defined in terms of an interface which the host application implements. For our purpose let's consider the simple DOM/script-interface combination.

    namespace ScriptableApplication.Extensibility
    {
    public delegate void ClickEvent(int x, int y);

    public interface IHost

    {

    string Title { get; set; }

    Color BackgroundColor { get; set; }

    event ClickEvent Click;

    }

    public interface IScript

    {

    string Name {get;}

    string Description { get;}

    void Initialize(IHost host);

    void Close();

    }

    }

    Here the host exposes a simple DOM using which the scripts can modify the host-applications title text and background color. It also exposes an event which is fired each time user clicks on the host-form. Scripts can subscribe to the event to get click notification along with the coordinates of the click.

    Each script needs to have at least one class that implements the IScript interface. The host application compiles the script on the fly and using reflection looks for any class that implements this interface and instantiates that class. It then calls the Initialize method passing it the IHost pointer which the script can use to manipulate the host DOM.

    On the Fly Compilation

    This is what makes the whole technique work. .NET framework exposes all the compilers and associated framework in a very well designed namespace. This can be used to locate any compiler registered with a given file extension and use it to compile the sources.

    private CompilerResults LoadScript(string filepath)
    {
    string language = CSharpCodeProvider.GetLanguageFromExtension(
    Path.GetExtension(filepath));
    CodeDomProvider codeDomProvider =
    CSharpCodeProvider.CreateProvider(language);
    CompilerParameters compilerParams = new CompilerParameters();
    compilerParams.GenerateExecutable =
    false;
    compilerParams.GenerateInMemory =
    true;
    compilerParams.IncludeDebugInformation =
    false;

    string
    extAssembly = Path.Combine(
    Path.GetDirectoryName(Application.ExecutablePath),
    "Extensibility.dll");
    compilerParams.ReferencedAssemblies.Add(extAssembly);
    compilerParams.ReferencedAssemblies.Add(
    "System.dll");
    compilerParams.ReferencedAssemblies.Add(
    "System.Drawing.dll");
    compilerParams.ReferencedAssemblies.Add(
    "System.Windows.Forms.dll");

    return codeDomProvider.CompileAssemblyFromFile(compilerParams,
    filepath);
    }

    In the first part we use the .NET framework to locate the relevant compiler based on the extension of the script file. In case of unsupported language System.Configuration.ConfigurationErrorsException is thrown.

    After we get the code-dom provider we create the compiler parameters. The GenerateInMemory flag is set to indicate the assembly is not generated on disk but in-memory.

    Since the script needs to refer to the extensibility dll and some bare minimal .NET framework dlls, they are added to the ReferencedAssemblies collection. After that the compilation is done and the result of the compilation is returned as a CompilerResults object.

    In case compilation fails the failures are available and are enumerated as follows

    CompilerResults result = LoadScript(filePath);
    if (result.Errors.HasErrors)
    {
    StringBuilder errors = new StringBuilder();
    string filename = Path.GetFileName(filePath);
    foreach (CompilerError err in result.Errors)
    {
    errors.Append(
    string.Format("\r\n{0}({1},{2}): {3}: {4}",
    filename, err.Line, err.Column,
    err.ErrorNumber, err.ErrorText));
    }
    string str = "Error loading script\r\n" + errors.ToString();
    throw new ApplicationException(str);
    }

    This gives detailed failure messages along with rom/column numbers of the failure.

    Loading the plugins

    If there are no compilation errors then the compiled in-memory assembly is available in result.CompiledAssembly. The host uses reflection to search through all the types in the assembly that implements IScript interface and loads that type and calls IScript methods.

    GetPlugins(result.CompiledAssembly);

    private
    void GetPlugins(Assembly assembly)
    {
    foreach (Type type in assembly.GetTypes())
    {
    if (!type.IsClass || type.IsNotPublic) continue;
    Type[] interfaces = type.GetInterfaces();
    if (((IList<Type>)interfaces).Contains(typeof(IScript)))
    {
    IScript iScript = (IScript)Activator.CreateInstance(type);
    iScript.Initialize(m_host);
    // add the script details to a collection

    ScriptDetails.Add(
    string.Format("{0} ({1})\r\n",
    iScript.Name, iScript.Description));
    }
    }
    }

    With this we are done initializing the plugins

    Implementing the scripts

    Implementing the scripts is simple and can be done in any .NET language. The following example is a script in C#.

    using System;
    using ScriptableApplication.Extensibility;
    using System.Drawing;
    public class Script : IScript
    {
    int i = 0;
    IHost host =
    null;
    public string Name {get {return "CoolScript";}}
    public string Description { get {return "Coolest script";}}
    public void Initialize(IHost host)
    {
    this.host = host;
    host.Click +=
    delegate(int x, int y)
    {
    host.Title =
    string.Format("Clicked on {0}, {1}",
    x, y);
    Random autoRand = new Random();

    host.BackgroundColor =
    Color.FromArgb(autoRand.Next(0, 255),
    autoRand.Next(0, 255),
    autoRand.Next(0, 255));
    };

    }

    public void Close()
    {
    }
    }

    The script stores the IHost reference and subscribes to the IHost.Click event. In the event handler it sets the host dialogs title to the position of the click and changes the background-color to some random generated color.

    Similarly scripts can be written in VB.NET as follows

    Imports Microsoft.VisualBasic
    Imports System
    Imports
    System.Drawing
    Imports ScriptableApplication.Extensibility


    Public
    Class Class1
    Implements IScript

    Public
    Sub Initialize(ByVal host As IHost)
    Implements IScript.Initialize
    host.Title =
    "VB Script loaded"
    End Sub
     
    Public Sub Close() Implements IScript.Close
    End Sub
     
    Public ReadOnly Property Description() As String
    Implements IScript.Description
    Get
    Description = "I'm a nice VB script"
    End Get
    End Property
     
    Public ReadOnly Property Name() As String
    Implements IScript.Name
    Get
    Name = "VB Script"
    End Get
    End Property
    End
    Class

    Sample project

    You can download the complete sample from here. It contains the following

    Extensibility project: This contains only one source file Interfaces.cs which contains definition for the IScript and IHost interfaces. This project generates the Extensibility.dll.

    ScriptableApplication project: This contains ScriptHandler.cs which has the complete implementation of on the fly compilation and loading of the dlls. MainForm.cs which implements the host application.

    Scripts: Contains two sample scripts script.cs and script.vb

    Drawbacks

    There are two huge drawbacks to this technique, both of which related to security. If any user with lesser privilege has access to the plugins folder or can direct the host-application to pick up a script from any folder then the user can execute any code he wants using the credentials of the host application. In my case I used this to create motion detection algorithm plugins. This was a personal use test code and I ensured that only I and other admins of the box had write permission to the plugins folder, and so it is kind-of safe for use. However, if you want to use this in a program that's distributed outside you need to plug this security-flaw.

    I had initially assumed that I can apply assembly level security restrictions on the generated assembly to disallow file and network access using something like [assembly: FileIOPermission(SecurityAction.RequestRefuse, Unrestricted = true)] and I'll be done. I am not an expert on security related issues and so I asked around on what is the best option in securing this scenario. Shawn Farkas suggested that the best option would be to use sand-boxed AppDomains. However since the plugin will be in an AppDomain different from the AppDomain in which the host application exists, there'll be performance cost due to cross appdomain calls that needs marshalling.

    The other issue is error conditions in the script. If there is an unhandled exception in the script it'll bring the whole application down.

  • I know the answer (it's 42)

    Mysterious thing's I have eaten

    • 14 Comments

    Steve Yi has a interesting post about Mysterious things he has eaten. Since I am from India we are used to a lot of food that may be considered as Mysterious. I couldn't figure out why Kimchee made into his list. It's served in all oriental restaurant here and is very main stream.

    Anyways I thought I'd post the mysterious things I ate

    1. Goat brain: This has to be the most mysterious and the most obnoxious thing I've had. Its actually called Brain-Masala, in which the Goat brain is light-fried and served by sprinkling a lot of spices (called Masala) on it. This is not for the faint-hearted and I have sweared never to even think about it again (but then I keep remembering it :(0) )
    2. Sutki-Mach: This is much like the Dried Squid Steve writes about, but its dried sea-fish (Bombay-duck). It is so dry it looks like the bark of a tree.
    3. Hilsha Chips: This again is similar to the shrimp-chips, but is tastier and smells less. These are sold in packets and you need to fry them yourself before eating. Hilsha or Elish is a very popular fish found in the Ganga-delta region in Bangladesh and also in some parts of China.
    4. Deer-meat: The deer is buried underground for 3-4 days and then dug out, roasted in log-fire and served hot. I ate it long back in a forest.
    5. Murg-Masallam: The last one is not that mysterious, but its very-very tasty. The inside of a chicken (Murg) is scooped out and cleaned. Then its stuffed with Rice (as in Biriyani) boiled eggs and cooked over charcoal fire. You've got to eat it to believe how tasty it becomes.

    And no we do not eat snakes and bull-eyes as depicted in the Indiana Jones movie :-)

Page 1 of 1 (11 items)