Geeks With Blogs
Buhay Programmer Dont byte more than you can chew

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 ()

Posted on Friday, November 9, 2007 1:22 PM | Back to top


Comments on this post: Extracting Raw Schemas from BizTalk 2004 and 2006 Assemblies

# re: Extracting Raw Schemas from BizTalk 2004 and 2006 Assemblies
Requesting Gravatar...
Hi,

the download link doesn't work anymore. Pls. fix.

thx
Roland
Left by Roland on Jun 16, 2009 3:22 AM

Your comment:
 (will show your gravatar)


Copyright © Erik Araojo | Powered by: GeeksWithBlogs.net