Blogger :
Geekswithblogs.net
All posts :
All posts by Geekswithblogs.net
Category :
BizTalk 2004
Blogged date : 2007 Nov 09
When BizTalk compiles a project that contains a schema it generates a wrapper class for each schema. Take for example the typical Biztalk Project below. It contains a PropertySchema + 4 other schemas.

Compiling this project and opening it up with .NET Reflector, we'll get the following. The important stuff to note from this are
- A class was generated for each schema (including the Property schema)
- The generated classes inherit from "Microsoft.XLANGs.BaseTypes.SchemaBase"
- (See Figure 2) SchemaBase has a property called "XmlContent" which is overriden by the generated class. This property contains the raw schema string!

Figure 1. Reflector output

Figure 2. Properties Overriden by the Generated Class
So to get the raw schema, all we need to do is open up the dll in .NET Reflector and do some copy-paste magic. :) But what if you have a huge schema project? Extracting them all will be very painful (at least for me). So being the kind of programmer that hates repetitive work, and aside from the fact that I'm currently learning and loving F#, I hacked up this code to do everything automatically. Here's the tool in action. It creates the XSD files in the same folder where the tool was ran.

The tool can be downloaded here. (p.s. easy-share.com deletes the file if it has not been downloaded for within 30 days. Just drop me an email if you want me to send the file directly)
and here's the code (How it works will be topic in a future post )
#light
module BtXsd
open System
open System.Windows.Forms
open System.ComponentModel
open BtsXsdExtractorUI
open System.IO
open System.Reflection
open System.Text
open Microsoft.FSharp.Reflection
open Microsoft.FSharp.Core
open Microsoft.XLANGs.BaseTypes
let schemaPropertyName = "XmlContent"
let btsSchemas file =
if (not (String.IsNullOrEmpty(file))) then
let btsAssembly = Assembly.LoadFile(file)
let types = btsAssembly.GetTypes()
let schemabaseType = typeof
let btsSchemaTypes = types |> Array.filter (fun x -> schemabaseType.IsAssignableFrom(x))
btsSchemaTypes
else
[||]
let rec generateFileName rootDir name =
let ext = ".xsd"
let temp = Path.Combine(rootDir, name + ext)
if File.Exists(temp) then
let newName = name +"_("+ int_to_string (Directory.GetFiles(rootDir, name + "*", SearchOption.TopDirectoryOnly).Length) + ")"
generateFileName rootDir newName
else
temp
type Form1 =
inherit Form as base
val mutable components: System.ComponentModel.Container
override this.Dispose(disposing) =
if (disposing && (match this.components with null -> false | _ -> true)) then
this.components.Dispose()
base.Dispose(disposing)
val mutable tbDllFile: System.Windows.Forms.TextBox
val mutable btnBrowse: Button
val mutable btnExtract: Button
val mutable label1: Label
val mutable bgwExtract: BackgroundWorker
val mutable progressBar1: ProgressBar
val mutable openFileDialog1: OpenFileDialog
member this.InitializeComponent() =
this.tbDllFile <- new System.Windows.Forms.TextBox();
this.btnBrowse <- new System.Windows.Forms.Button();
this.btnExtract <- new System.Windows.Forms.Button();
this.label1 <- new System.Windows.Forms.Label();
this.bgwExtract <- new System.ComponentModel.BackgroundWorker();
this.progressBar1 <- new System.Windows.Forms.ProgressBar();
this.openFileDialog1 <- new System.Windows.Forms.OpenFileDialog();
this.SuspendLayout();
//
// tbDllFile
//
this.tbDllFile.Location <- new System.Drawing.Point(13, 33);
this.tbDllFile.Name <- "tbDllFile";
this.tbDllFile.Size <- new System.Drawing.Size(336, 20);
this.tbDllFile.TabIndex <- 0;
this.tbDllFile.Text <- "Erik:\\VS 2005 Projects\\FSharp\\FSoapBits\\ValidationSchemas.dll";
//
// btnBrowse
//
this.btnBrowse.Location <- new System.Drawing.Point(355, 30);
this.btnBrowse.Name <- "btnBrowse";
this.btnBrowse.Size <- new System.Drawing.Size(34, 23);
this.btnBrowse.TabIndex <- 1;
this.btnBrowse.Text <- "...";
this.btnBrowse.UseVisualStyleBackColor <- true;
this.btnBrowse.Click.Add(fun _ ->
if (DialogResult.OK == this.openFileDialog1.ShowDialog()) then
this.tbDllFile.Text <- this.openFileDialog1.FileName
else
this.tbDllFile.Text <- " ")
//
// btnExtract
//
this.btnExtract.Location <- new System.Drawing.Point(314, 64);
this.btnExtract.Name <- "btnExtract";
this.btnExtract.Size <- new System.Drawing.Size(75, 23);
this.btnExtract.TabIndex <- 2;
this.btnExtract.Text <- "Extract";
this.btnExtract.UseVisualStyleBackColor <- true;
this.btnExtract.Click.Add(fun e ->
//let max = ref 0
let justTheFileName = Path.GetFileName(this.tbDllFile.Text);
if File.Exists(this.tbDllFile.Text) then
let temp = btsSchemas this.tbDllFile.Text
(*if not (temp.Length % 2 = 0) then
max := temp.Length + 1
else
max := temp.Length*)
this.progressBar1.Maximum <- temp.Length
this.progressBar1.Minimum <- 0
this.progressBar1.Step <- 1
this.progressBar1.Value <- 0
this.progressBar1.Refresh()
if temp.Length > 0 then
temp |> Array.iter (fun typ ->
let instance = Activator.CreateInstance(typ) :?> SchemaBase
let xsd = instance.XmlContent
let curAssm = Assembly.GetExecutingAssembly()
let curDir = Path.GetDirectoryName(curAssm.Location)
//let curDir = Directory.GetCurrentDirectory()
let fullFileName = generateFileName curDir typ.Name
//Path.Combine(curDir, typ.Name + ".xsd")
using(new StreamWriter(fullFileName, false, Encoding.Unicode)) (fun sw -> sw.Write(xsd))
this.progressBar1.Increment(1)
)
else
MessageBox.Show(justTheFileName + " does not contain BizTalk schemas") |> ignore
else
MessageBox.Show(justTheFileName + " file does not exist") |> ignore
)
//
// label1
//
this.label1.AutoSize <- true
this.label1.Location <- new System.Drawing.Point(10, 9)
this.label1.Name <- "label1"
this.label1.Size <- new System.Drawing.Size(85, 13);
this.label1.TabIndex <- 3;
this.label1.Text <- "Biztalk Assembly";
//
// progressBar1
//
this.progressBar1.Location <- new System.Drawing.Point(12, 64);
this.progressBar1.Name <- "progressBar1";
this.progressBar1.Size <- new System.Drawing.Size(296, 23);
this.progressBar1.TabIndex <- 4;
//
// openFileDialog1
//
this.openFileDialog1.FileName <- "openFileDialog1";
this.openFileDialog1.Filter <- "Dll files|*.dll"
//
// BtsXsdExtractorForm
//
this.AutoScaleDimensions <- new System.Drawing.SizeF(6.0F, 13.0F);
this.AutoScaleMode <- System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize <- new System.Drawing.Size(401, 113);
this.Controls.Add(this.progressBar1);
this.Controls.Add(this.label1);
this.Controls.Add(this.btnExtract);
this.Controls.Add(this.btnBrowse);
this.Controls.Add(this.tbDllFile);
this.Name <- "BtsXsdExtractorForm";
this.Text <- "BizTalk Assembly Schema Extractor";
this.ResumeLayout(false);
this.PerformLayout();
new () as this =
{
tbDllFile = null
btnBrowse = null
btnExtract = null
label1 = null
bgwExtract = null
progressBar1 = null
openFileDialog1 = null
components = null
}
then
this.InitializeComponent()
let main() =
Application.EnableVisualStyles() |> ignore
//Application.SetCompatibleTextRenderingDefault(false) |> ignore
let form1 = new Form1()
Application.Run(form1)// |> ignore
[]
do main ()
