Click here to Skip to main content
15,885,743 members
Articles / Programming Languages / XML

Converting .NET Assemblies to Silverlight Assemblies

Rate me:
Please Sign up or sign in to vote.
4.92/5 (15 votes)
3 Mar 2009CPOL5 min read 151.3K   1.4K   69  
Share your .NET assemblies with Silverlight.
using System;
using System.Diagnostics;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml;
using System.Collections.Generic;

namespace SLAsm
{
    class Program
    {
        

        public static string ILDisassembler { get; set; }
        public static string ILAssembler { get; set; }
        /// <summary>
        /// Validate the IL Assembler .Disassembler Paths
        /// </summary>
        static bool validatePaths()
        {
            return !string.IsNullOrEmpty(ILDisassembler)
                && System.IO.File.Exists(ILDisassembler)
                && !string.IsNullOrEmpty(ILAssembler)
                && System.IO.File.Exists(ILAssembler);
        }
        /// <summary>
        /// Load the settings from the SLAsm.Settings.xml file
        /// </summary>
        /// <returns></returns>
        static ExternAssembly[] LoadSettings()
        {
            try
            {
                string sPath = System.IO.Path.ChangeExtension(
                    typeof(ExternAssembly).Assembly.Location, ".Settings.xml");
                if (!System.IO.File.Exists(sPath))
                {
                    Console.WriteLine(string.Format("Error: Could not locate Settings File ('{0}')", sPath));
                    return new ExternAssembly[] { };
                }
                XmlDocument xDoc = new XmlDocument();
                xDoc.Load(sPath);
                
                string LocalPath = System.IO.Path.GetDirectoryName(sPath);
                
                //Updated to allow %path% token be replaced by the local path
                ILDisassembler = xDoc.DocumentElement.GetAttribute("ILDisassembler").Replace("%path%",LocalPath);
                
                //Updated to load ilasm from the .Net instalation dir
                ILAssembler = System.IO.Path.Combine(System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory(), "ilasm.exe");
                if(!System.IO.File.Exists(ILAssembler))
                    ILAssembler = xDoc.DocumentElement.GetAttribute("ILAssembler").Replace("%path%", LocalPath);
                XmlNamespaceManager nsMgr = new XmlNamespaceManager(xDoc.NameTable);
                nsMgr.AddNamespace("ns", ExternAssembly.NamespaceUrn);
                List<ExternAssembly> assemblies = new List<ExternAssembly>();
                foreach (XmlElement xExtern in xDoc.DocumentElement.SelectNodes("ns:ExternAssembly[@Name]",nsMgr))
                {
                    ExternAssembly asm = ExternAssembly.FromXml(xExtern);
                    if (!asm.IsEmpty)
                        assemblies.Add(asm);
                }
                return assemblies.ToArray();

            }
            catch (Exception ex)
            {
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine(string.Format("Unexpected Error!\n{0}", ex.Message));
            }
            return new ExternAssembly[] { };
        }
        

        static int Main(string[] args)
        {
            if (args == null || args.Length == 0 || args[0].Equals("/?") || args[0].Equals("-?"))
            {
                Console.WriteLine("Usage: SLAsm.exe <AssemblyPath.dll> [/Key=<StrongNameKeyPath.snk>] [/Output=<TargetPath.dll>]");
                return 0;
            }

            

            //Load Settings
            ExternAssembly[] Assemblies = LoadSettings();

            if (Assemblies.Length == 0)
            {
                Console.WriteLine("Could not load Assembly Settings");
                return -2;
            }
            //Validate External Paths
            if (!validatePaths())
            {
                Console.ForegroundColor = ConsoleColor.Red;
                string sError ="Invalid paths set for IL Assembler / Disassembler\nPlease modify the SLAsm.Settings.xml file";
                Console.Error.WriteLine(sError);
                
                return -1;
            }

            string Path = null, Output = null, KeyFile = null;
            foreach (string arg in args)
            {
                string[] spl = arg.Split('=');
                if (spl.Length > 1)
                {
                    switch (spl[0].Trim().ToLower())
                    {
                        case "/key":
                            KeyFile = spl[1].Trim();
                            break;
                        case "/output":
                            Output = spl[1].Trim();
                            break;
                    }
                }
                else
                {
                    Path = spl[0].Trim();
                }
            }
            if (string.IsNullOrEmpty(Output))
                Output = System.IO.Path.ChangeExtension(Path, ".SL.dll");
            
            if (!System.IO.File.Exists(Path))
            {
                Console.ForegroundColor = ConsoleColor.Red;
                Console.Error.WriteLine("Error: Invalid Input assembly");

                return -3;
            }

            

            //Start Disassembler
            Process p = new Process();
            Console.WriteLine(string.Format("Disassembling '{0}'", Path));
            p.StartInfo = new ProcessStartInfo(ILDisassembler,string.Format("{0}.dll /out:{0}.il /text /nobar",System.IO.Path.GetFileNameWithoutExtension( Path)));
            p.StartInfo.RedirectStandardOutput = true;
            p.StartInfo.UseShellExecute = false;
            p.StartInfo.WorkingDirectory = System.IO.Path.GetDirectoryName(Path);
            p.Start();
            p.WaitForExit();
            if (p.ExitCode != 0)
            {
                StringBuilder sB = new StringBuilder(p.StandardOutput.ReadToEnd());
                if (sB.Length > 0)
                {
                    Console.WriteLine("Result from ILDAsm was:");
                    Console.WriteLine(sB.ToString());
                }
            }



            string ILFile = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(Path), System.IO.Path.GetFileNameWithoutExtension(Path) + ".il");
            if (System.IO.File.Exists(ILFile))
            {
                //Load IL Code
                string IL = System.IO.File.ReadAllText(ILFile);
                Console.WriteLine("Fixing Assembly references...");

                //Iterate All Problematic Assembly references and fix their version
                foreach (ExternAssembly item in Assemblies)
                    IL = item.FixAssembly(IL);
                
                //Check for a Strong name Key and remove if exists
                Regex publicKey = new Regex(".publickey\\s=\\s\\([^\\)]*\\)", RegexOptions.Compiled);
                Match pkey = publicKey.Match(IL);
                if (pkey != null && pkey.Length != 0)
                {
                    Console.WriteLine("Removing Strong name Key...");
                    StringBuilder sBIL = new StringBuilder(IL.Length - pkey.Length);
                    sBIL.Append(IL.Substring(0, pkey.Index));
                    sBIL.Append(IL.Substring(pkey.Index + pkey.Length));
                    IL = sBIL.ToString();
                }

                //Output the modified IL Code
                System.IO.File.WriteAllText(ILFile, IL);

                //Start The IL Assembler Process
                string sParams = "{0}.il /dll /out:\"{1}\"";
                string resFile = System.IO.Path.ChangeExtension(Path, ".res");
                if (System.IO.File.Exists(resFile))
                    sParams = "{0}.il /dll /resource:{0}.res /out:\"{1}\"";
                if (!string.IsNullOrEmpty(KeyFile))
                    sParams += string.Format(" /key=\"{0}\"", args[1]);
                sParams = "/Quiet /Optiomize " + sParams;

                if (!System.IO.Directory.Exists(System.IO.Path.GetDirectoryName(Output)))
                    System.IO.Directory.CreateDirectory(System.IO.Path.GetDirectoryName(Output));
                Console.WriteLine("Re-Assembling File...");
                p = new Process();
                p.StartInfo = new ProcessStartInfo(ILAssembler, string.Format(sParams, System.IO.Path.GetFileNameWithoutExtension(Path),Output));
                p.StartInfo.UseShellExecute = false;
                p.StartInfo.WorkingDirectory = System.IO.Path.GetDirectoryName(Path);

                p.Start();
                if (!p.HasExited)
                    p.WaitForExit();
                if (p.ExitCode != 0)                    
                        Console.WriteLine("ILAsm Faild!");
                else
                    Console.WriteLine(string.Format("Silverlight Compatible Assembly created in: '{0}'", Output));
                System.IO.File.Delete(ILFile);
                if (System.IO.File.Exists(resFile))
                    System.IO.File.Delete(resFile);
                return 0;
            }
            else
            {
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine("Could not find IL code for assembly");
                return -1;
            }
        }

       

        
       

    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) VCM Software
Israel Israel
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions