Archive for April, 2008

Write files in Java using BufferedWriter class

In Java, you can write data out to flat files using the BufferedWriter class. This class writes text out to a character output stream and buffers characters in order to provide an efficient means of writing single characters, arrays and strings.

This example also uses the FileWriter class inside of the BufferedWriter constructor. The FileWriter class is sort of a helper, or a convenient class enabling writing of character files.

I have a class that will return me a ResultSet from a Query against the NorthWind database Customers table. I define my BufferedWriter, loop through the ResultSet and write out the data to a flat delimited file.

try {
ResultSet rs = conn.GetResultSet(cn,”Select * from Customers”);

BufferedWriter writer = new BufferedWriter(new FileWriter(”c:/writerTest.txt”));

while(rs.next()){
String outLine=rs.getString(1)+”,”+rs.getString(2);
writer.write(outLine);
writer.newLine();
System.out.println(rs.getString(1) + ” ” + rs.getString(2));
}

rs.close();
cn.close();
System.out.println(”completed!”);

}
catch(Exception ex) {
//write out something here
}

If the File that you define in your FileWriter constructor does not exist, it will be created. Notice I use the writer.newLine(). This is so that the file prints with a carriage return/line-feed option and not continous accross one line.

Advertisements

April 28, 2008 at 7:26 am Leave a comment

MySQL JDBC Driver. Connect to MySQL from Java

Although the majority of my programming efforts evolve around C# & ASP.NET using C#, I find myself doing more stuff with Java. As with every new language that I work with, there are specific things which are common across all languages, such as reading flat files and parsing delimited strings, reading and writing XML files and of course, connecting to a database that I tend to focus on.

The other day, I found myself needing to connect to a MySQL Database, so I downloaded the JDBC Driver (jar file) that would enable me to connect a small java app and read some data. I downloaded it from the java web site, you can do a search for “download jdbc drivers” and you should find the url.

Next, I created a new project in Eclipse and added a .java file. Be sure to add the .jar file for the jdbc driver to the build path of your Eclipse project or you will get an error when you try use the DriverManager and try to connect to the database.

Here is the code that I used:

Add the following import statement:
import java.sql.*;

Add the following module level variables. 

   static Connection conn;
   static Statement stmt;
   static ResultSet rset;

try {
   Class.forName(”com.mysql.jdbc.Driver”);
   conn = DriverManager.getConnection(
   “jdbc:mysql://localhost:3306/
   yourdatabase”, “loginid”, “loginpw”);

   stmt=conn.createStatement();
   rset = stmt.executeQuery(”SELECT *
        FROM ssfsigma.csaccount”);

   while(rset.next()) {
     System.out.println(rset[1].getString() );
   }
}
catch( Exception ex ) {
   System.out.println(ex.getMessage());
   return;

}

Using the DriverManager object, I call the getConnection() method. The Statement is like the SqlCommand object, so I call CreateStatement() on the Connection object. Once I have my Statement, I create a ResultSet by using the executeQuery() method. After this, I can read each record in the ResultSet using the .next() method.

Notice that the connection string contains localhost:3306. This is the port that is defaulted in the install of MySQL.

April 28, 2008 at 7:25 am Leave a comment

How to collapse and expand rows of a datagrid using C#, ASP.NET, and Javascript.

The following article will describe the source code, which will allow programmers to create a HGrid. It will allow master/slave or master/child data to be shown. It also includes the features to collapse and expand data on the client side using JavaScript. The original code was done in Visual Studio 2003 using framework 1.1. This is the second version of this grid.

What are the controls needed?

In order to create a HGrid on your own, only a datagrid, and a hidden textbox are needed. In the example I have included the following are the components:

1.    DataGrid (ID: DataGrid1)

The datagrid will hold the data for the master/slave or master/child data. We will also include the feature to expand/collapse (show/hide) on the grid itself. In the example I use, I will be connecting to the NorthWind database of a SQL Database.

2. TextBox (ID: txtExpandedDivs, Width = “0px” or in a div which has style.display: ’none’)

The width is set to 0px so that the users cannot see it, but it exists on the page as a hidden text field. I chose to do it this way, so users can change the width and view the contents of the textbox

3. Button (ID: ButtonSample)

This button is outside of the grid. I created this button, but most likely when users create a page, the page will consist of many controls which will call the page to reload. We have to make sure the contents of the grid are the same, once the page is refreshed.

4. Labels (ID: LabelPostBack)

This label will show the contents of the hidden textbox (txtExpandedDivs) once the (ButtonSample) is clicked.

5. Labels (ID: LabelTitle)

This label is just show the database we are connecting to. e.g.. NorthWind

6. Labels (ID: LabelWhatHappens)

This label is a static label which always shows the message: “What are we storing in the hidden textbox field (txtExpandedDivs Textbox Control)?”

7. Table (ID: Table1)

This table has all the above controls in it.

Details of the DataGrid

Here is the html of the datagrid below. It has paging (10 per page), sorting, and autogeneratedcolumns = false. The columns we have are:

  1. HyperLinkColumn: “+”
  2. BoundColumn: “OrderID”, “CustomerID”, “EmployeeID”, “ShipName”, “ShipAddress”, “ShipCity”, “ShipRegion”, “ShipPostCode”, “ShipCountry”.


<asp:datagrid id=”DataGrid1″ runat=”server” ForeColor=”Black” AllowSorting=”True” AllowPaging=”True” GridLines=”Vertical” CellPadding=”3″ BackColor=”White” BorderWidth=”1px” BorderStyle=”Solid” BorderColor=”#999999″ Width=”100%” AutoGenerateColumns=”
False“>

<SelectedItemStyle Font-Bold=”True” HorizontalAlign=”Left” ForeColor=”White”

VerticalAlign=”Top” BackColor=”#000099″>

</SelectedItemStyle>

<EditItemStyle HorizontalAlign=”Left” VerticalAlign=”Top”></EditItemStyle>

<AlternatingItemStyle HorizontalAlign=”Left” ackColor=”#CCCCCC”></AlternatingItemStyle>

<ItemStyle Font-Size=”8pt” Font-Names=”Tahoma” HorizontalAlign=”Left”

VerticalAlign=”Top”>

</ItemStyle>

<HeaderStyle Font-Bold=”True” ForeColor=”White” BackColor=”Black”></HeaderStyle>

<FooterStyle BackColor=”#CCCCCC”></FooterStyle>

<Columns>

<asp:HyperLinkColumn Text=”+”></asp:HyperLinkColumn>

<asp:BoundColumn Visible=”False” DataField=”OrderID” ReadOnly=”True”

HeaderText=”OrderID”>

</asp:BoundColumn>

<asp:BoundColumn Visible=”False” DataField=”CustomerID

HeaderText=”CustomerID”>

</asp:BoundColumn>

<asp:BoundColumn Visible=”False” DataField=”EmployeeID

HeaderText=”EmployeeID”>

</asp:BoundColumn>

<asp:BoundColumn DataField=”ShipName” SortExpression=”ShipName

HeaderText=”Name”>

</asp:BoundColumn>

<asp:BoundColumn DataField=”ShipAddress” SortExpression=”ShipAddress

HeaderText=”Address”>

</asp:BoundColumn>

<asp:BoundColumn DataField=”ShipCity” SortExpression=”ShipCity

HeaderText=”City”>

</asp:BoundColumn>

<asp:BoundColumn DataField=”ShipRegion” SortExpression=”ShipRegion

HeaderText=”Region”>

</asp:BoundColumn>

<asp:BoundColumn DataField=”ShipPostalCode” SortExpression=”ShipPostalCode

HeaderText=”Postal”>

</asp:BoundColumn>

<asp:BoundColumn DataField=”ShipCountry” SortExpression=”ShipCountry

HeaderText=”Country”>

</asp:BoundColumn>

</Columns>

<PagerStyle HorizontalAlign=”Center” ForeColor=”Black” BackColor=”#999999″

Mode=”NumericPages”>

</PagerStyle>

</asp:datagrid>

Language used for this code is: ASP.NET, C#. There are many tools to convert to VB.NET if needed. The source code is very descriptive and can easily be traced.

Code:

private string connectionstring = “server=SERVERNAME;database=Northwind;uid=USERID;password=PASSWORD;”;

private void Page_Load(object sender, System.EventArgs e)
{

//Clear the contents of the Label
this.LabelPostBack.Text = “”;

if ( !Page.IsPostBack )
{

BindData(); //Bind Master Details
}
else
{

for ( int i = 0; i < this.DataGrid1.Items.Count; i++ )
{
//After Postback ID’s get lost. Javascript will not //work without it, so we must set them back.
this.DataGrid1.Items[i].Cells[0].ID = “CellInfo” + i.ToString();
}

//If it is a postback that is not from the grid, we have to
//expand the rows the user had expanded before. We have to
//check first who called this postback by checking the
//Event Target. The reason we check this, is because we
//don’t need to expand if it is changing the page of the
//datagrid, or sorting, etc…

if ( Request[“__EVENTTARGET”] != null)
{
string strEventTarget = Request[“__EVENTTARGET”].ToString().ToLower();

//datagrid1 is the name of the grid. If you modify
//the grid name, make sure to modify this if
//statement.

if ( strEventTarget.IndexOf(”datagrid1″) == -1)
{

if (!Page.IsStartupScriptRegistered(”ShowDataJS”))
{
Page.RegisterStartupScript( “ShowDataJS”, “<script>ShowExpandedDivInfo(’” + this.txtExpandedDivs.ClientID + “‘,’” +
this.DataGrid1.ClientID + “‘);</script>”);
}
}
}
}
}

private void ButtonSample_Click(object sender, System.EventArgs e)
{

LabelPostBack.ForeColor = System.Drawing.Color.DarkRed;
if ( txtExpandedDivs.Text.Length == 0 )
{
LabelPostBack.Text = “A Postback has occurred. txtExpandedDivs has no content!”;
}
else
{
LabelPostBack.Text = “A Postback has occurred. txtExpandedDivs has contents: <BR/><B>” +
this.txtExpandedDivs.Text + “</B>”;
}
}
#region Database Methods

private void BindData()
{

//======Query For Master Rows=======
string QueryString = “SELECT OrderID, CustomerID, EmployeeID,
ShipName, ShipAddress, ShipCity, ShipRegion,
ShipPostalCode, ShipCountry FROM Orders”;

if ( ViewState[“sortby”] != null )
{
QueryString = QueryString + ” order by ” + ViewState[“sortby”].ToString();
}

//==============================

System.Data.SqlClient.SqlConnection conn = new
System.Data.SqlClient.SqlConnection();

try
{
conn.ConnectionString = connectionstring;
if ( conn.State == System.Data.ConnectionState.Closed )
{
conn.Open();
}

System.Data.SqlClient.SqlDataAdapter adapter = new
System.Data.SqlClient.SqlDataAdapter( QueryString, conn);

DataSet ds = new DataSet();
adapter.Fill( ds );
DataGrid1.DataSource = ds;
DataGrid1.DataBind();
}
catch( Exception ex1 )
{
Response.Write( “An error has occurred: ” );
Response.Write( ex1.Message.ToString() );
Response.End();
}
finally
{
if ( conn.State == System.Data.ConnectionState.Open )
{
conn.Close();
}
}
}

private DataSet RunQuery(string QueryString)
{
System.Data.SqlClient.SqlConnection conn = new
System.Data.SqlClient.SqlConnection();

try
{
conn.ConnectionString = connectionstring;
if ( conn.State == System.Data.ConnectionState.Closed )
{
conn.Open();
}

System.Data.SqlClient.SqlDataAdapter adapter = new
System.Data.SqlClient.SqlDataAdapter( QueryString, conn);

DataSet ds = new DataSet();
adapter.Fill( ds );
return ds;
}
catch(Exception ex1)
{
Response.Write(”An Error has occurred.<BR />”);
Response.Write(ex1.Message.ToString());
Response.End();

//This line below will never execute.
return null;
}
finally
{
if ( conn.State == System.Data.ConnectionState.Open )
{
conn.Close();
}
}
}

#endregion

#region Datagrid Methods

private void DataGrid1_ItemDataBound(object sender, System.Web.UI.WebControls.DataGridItemEventArgs e)
{
//If your page size is 10, only 10 sub queries will be done.
if ( e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem )
{

string DetailsQuery = “SELECT C.CompanyName, OD.UnitPrice, ” +
“OD.Quantity, OD.Discount, E.FirstName, ” +
“E.LastName “FROM [Order Details] as OD, ” +
“[Customers] as C, [Orders] as O, ” +
“[Employees] as E ” + ” where OD.OrderID = ” +
“O.OrderID and O.CustomerID = ” +
“C.CustomerID and O.EmployeeID = E.EmployeeID and ” +
“O.OrderID = ‘” + e.Item.Cells[1].Text + “‘ and ” +
“C.CustomerID = ‘” + e.Item.Cells[2].Text + “‘ and ” +
“E.EmployeeID = ‘” + e.Item.Cells[3].Text + “‘”;

//Here I am grabbing the additional data and putting it
//into mini datagrids…
//If you wish to just use labels, or other controls, just
//bind the data as you
//wish, and render to html as I did.

DataSet ds = this.RunQuery(DetailsQuery);
DataGrid NewDg = new DataGrid();
NewDg.AutoGenerateColumns = true;
NewDg.Width = Unit.Percentage(100.00);
NewDg.DataSource = ds;
NewDg.DataBind();

SetProps(NewDg);

System.IO.StringWriter sw = new System.IO.StringWriter();
System.Web.UI.HtmlTextWriter htw = new System.Web.UI.HtmlTextWriter(sw);
NewDg.RenderControl( htw );

string DivStart = “<DIV id=’uniquename” +
e.Item.ItemIndex.ToString() +“‘ style=’DISPLAY: none;’>”;

string DivBody = sw.ToString();
string DivEnd = “</DIV>”;
string FullDIV = DivStart + DivBody + DivEnd;

int LastCellPosition = e.Item.Cells.Count – 1;
int NewCellPosition = e.Item.Cells.Count – 2;

e.Item.Cells[0].ID = “CellInfo” + e.Item.ItemIndex.ToString();

if (e.Item.ItemType == ListItemType.Item)
{
e.Item.Cells[LastCellPosition].Text = e.Item.Cells[LastCellPosition].Text +
“</td><tr><td bgcolor=’f5f5f5′></td><td colspan=’” +
NewCellPosition + “‘>” + FullDIV;
}
else
{
e.Item.Cells[LastCellPosition].Text = e.Item.Cells[LastCellPosition].Text +
“</td><tr><td bgcolor=’d3d3d3′></td><td colspan=’” +
NewCellPosition +”‘>” + FullDIV;
}

e.Item.Cells[0].Attributes[“onclick”] = “HideShowPanel(’uniquename” +
e.Item.ItemIndex.ToString() + “‘); ChangePlusMinusText(’” +
e.Item.Cells[0].ClientID + “‘); SetExpandedDIVInfo(’” +
e.Item.Cells[0].ClientID + “‘,’” + this.txtExpandedDivs.ClientID +
“‘, ‘uniquename” + e.Item.ItemIndex.ToString() + “‘);”;

e.Item.Cells[0].Attributes[“onmouseover”] = “this.style.cursor=’pointer’”;

e.Item.Cells[0].Attributes[“onmouseout”] = “this.style.cursor=’pointer’”;
}
}

private void DataGrid1_PageIndexChanged(object source, System.Web.UI.WebControls.DataGridPageChangedEventArgs e)
{
//clean up expanded records.
this.txtExpandedDivs.Text = “”;
DataGrid1.CurrentPageIndex = e.NewPageIndex;
BindData();
}

private void DataGrid1_SortCommand(object source, System.Web.UI.WebControls.DataGridSortCommandEventArgs e)
{
this.txtExpandedDivs.Text = “”;
string sortby = “[” + e.SortExpression + “]“;

if ( ViewState[“sortby”] == null )
{
sortby = sortby + ” ASC”;
ViewState[“sortby”] = sortby;
BindData();
}
else
{
if ( ViewState[“sortby”].ToString() == sortby + ” ASC”)
{
sortby = sortby + ” DESC”;
ViewState[“sortby”] = sortby;
BindData();
}
else if ( ViewState[“sortby”].ToString() == sortby + ” DESC”)
{
sortby = sortby + ” ASC”;
ViewState[“sortby”] = sortby;
BindData();
}
else
{
sortby = sortby + ” ASC”;
ViewState[“sortby”] = sortby;
BindData();
}
}
}

public void SetProps(System.Web.UI.WebControls.DataGrid DG)
{
/***************************************************************/
DG.Font.Size = 8;
DG.Font.Bold = false;
DG.Font.Name = “tahoma”;
/*****************Professional*****************/
//Border Props
DG.GridLines = GridLines.Both;
DG.CellPadding = 3;
DG.CellSpacing = 0;
DG.BorderColor = System.Drawing.Color.FromName(”#CCCCCC”);
DG.BorderWidth = System.Web.UI.WebControls.Unit.Pixel(1);

//Header Props
DG.HeaderStyle.BackColor = System.Drawing.Color.SteelBlue;
DG.HeaderStyle.ForeColor = System.Drawing.Color.White;
DG.HeaderStyle.Font.Bold = true;
DG.HeaderStyle.Font.Size = 8;
DG.HeaderStyle.Font.Name = “tahoma”;

DG.ItemStyle.BackColor = System.Drawing.Color.LightSteelBlue;
}
#endregion

Using the code with your database

In order to use the above code, just modify three things, and your all set:

  1. In the BindData() Method, insert your master query to your database.
  2. In the DataGrid Item_DataBound Method, modify the subquery to your database.
  3. If you modified the grid name, change it in the code as well. Just find and replace the old datagrid name: “datagrid1” to your new datagrid id.
  4. Compile, and Run!!!

April 28, 2008 at 7:24 am Leave a comment

Web Browser/Content in a C# Application

One of the most powerful development tools I’ve come across is using a dynamic
HTML type user interface for my C# applications. Not for the entire application
(like Microsoft Money), but frequently rich mixed content needs to be delivered
to the user and an embedded web browser is powerful.

Embedding just a web browser into an app is okay, but to use it as a responsive
user interface to your C# application is where the real power lies.

Note: Don’t get overwhelmed by the number of steps here. Each step is built upon
the previous but made so you can stop anywere and use what you’ve got up to that point.

Step 1: Get Internet Explorer Into Your App

  1. Create a new Windows Form
  2. Add the SHDocVw Web Browser COM Custom Control to your “Windows Forms”
    1. Right Click on the Toolbox
    2. Choose “Customize Toolbox…”
    3. Select and Add “Microsoft Web Browser”
  3. Draw the new control onto your form (Global icon)

These steps are necessary as the OCX control requires state information that
VS.NET automatically handles and includes in the projects resource file.
Step 2: Using the Web Browser

Since the Web Browser object is compatible with IE 3 to IE 6 and is based on
COM, it is a bit more complicated to use than a .NET component. Here is some
code on how to navigate.
Note: I will call my axWebBrowser control on a form “webMain”.


private void Navigate(string url)
{
    object o = System.Reflection.Missing.Value;
    webMain.Navigate(url, ref o, ref o, ref o, ref o);
}

The System.Reflection.Missing.Value object provides a null reference for an
optional/missing parameter. Much like in VB you can make passing some parameters
optional. Ex: Function MyFunc(url as String, Optional OtherInfo as String)

Handling the Web Browsers events requires knowing what to look for. Here is an
example of the status text change event:


using AxSHDocVw;

webMain.StatusTextChange += new DWebBrowserEvents2_StatusTextChangeEventHandler(webMain_StatusTextChange);

private void webMain_StatusTextChange(object sender, DWebBrowserEvents2_StatusTextChangeEvent e)
{
    Console.WriteLine(”webMain Status Text: ” + e.text);
}

This is all that is need just to use the browser to navigate to a web site.

Step 3: Access the IE Document Object Module (DOM)

Knowledge of Internet Explorer’s Document Object Model (IE DOM) from here
on is very useful.

Now my favorite part is in creating DHTML (Dynamic HTML) at run time and feeding
this to the browser control to make my own custom UI and display rich dynamic
content. We need access to the Microsoft HTML object library then know which
properties to line up.

  1. Right Click on References in the Solutions View
  2. Choose “Add Reference…”
  3. Go to the COM Tab
  4. Select and add “Microsoft HTML Object Library”

Note: There are a lot of items avalible in the mshtml library. Use the
references below to get more info on them.

Now let’s get the body of the web document.


using mshtml;

private HTMLDocument document
{get {return (HTMLDocument) webMain.Document;}}

private HTMLBody body
{get {return (HTMLBody) document.body;}}

Note: The web browser is a generic content container and by default is
not initialized to an HTML container so you must first load some HTML content
before attempting to access the document or body properties. The easiest way to
do this is:


private void Form1_Load(object sender, System.EventArgs e)
{
    // Goto a blank HTML page
    Navigate(”about:blank”);

    // Wait for the document to load
    while (body == null) Application.DoEvents();
     Step 4: Trapping IE DOM Events

Okay so now we have a Web Browser control showing our custom content.  How do we
interact with the content we’re showing to the use?  We need to trap
the HTML events.


using System.Runtime.InteropServices;

private void Form1_Load(object sender, System.EventArgs e)
{
    // … Other Previous Code Here

    // Set the handler for several DHTML events
    document.onclick = this;
    document.onmouseover = this;
    document.onmouseout = this;
}

// The default COM Interop method [DispId(0)]
public void DefaultMethod()
{
    HTMLWindow2 win = (HTMLWindow2) document.parentWindow;   Step 5: Putting it All Together - Make a Wrapper Custom Control

Okay, we now have all the tools we need to make everything work together.
I highly recommend making your own web browser custom control wrapper to make
working with the browser easier.  Here is the basic wrapper that I made and use
on everything.  This is great for spiffy message boxes, rich content on your
forms, etc.  Be sure to have the correct references.

Note: You will have to remove/delete the Web Browser control off the custom
control, put it back on manually, and rename it to webMain in order for VS.NET to
include the correct OCX state and licensing.

When put on a form, this custom control can appear and act much like a regular
label.  It defaults to the basic color and font of other controls.  Have fun!


using System;
using mshtml;
using System.Windows.Forms;
using System.ComponentModel;
using System.Runtime.InteropServices;

namespace CoadTools
{
    #region Delegates
    public delegate void WebBrowserElementEventHandler(object sender, mshtml.IHTMLEventObj e);
    #endregion

    /// &ltsummary>
    /// Noah Coad’s IE Web Browser Custom Control Wrapper
    /// </summary>
    public class WebBrowser : System.Windows.Forms.UserControl
    {
        #region Control Components
        private System.Windows.Forms.Panel pnlWeb;
        private AxSHDocVw.AxWebBrowser webMain;

        /// &ltsummary> Required designer variable. </summary>
        private System.ComponentModel.Container components = null;
        #endregion

        #region Enumerators
        public enum ieScrollBars {None, Always, Auto};
        #endregion

        #region Event Handler Declarations
        public event WebBrowserElementEventHandler WebBrowserElementEvent;
        #endregion

        #region Constructor(s)
        public WebBrowser()
        {
            InitializeComponent();

            // Go to the blank page, initializes the WebBrowser control to handle HTML documents.
            Navigate(”about:blank”, true);

            // Wait for the control to initialize to HTML and load the blank page.
            while (body == null) {Application.DoEvents();}

            // Set default properties for the control to appear like a generic label control.
            pnlWeb.BorderStyle = BorderStyle.None;
            //ScrollBars = ScrollBars.none;
            this.Text = “”;
            this.HTML = “”;
            body.style.font = “8.25pt Microsoft Sans Serif, 10pt Verdana”;
            body.style.margin = “0″;
            body.style.borderStyle = “none”;
            body.style.background = “buttonface”;
            ScrollBars = ieScrollBars.None;
        }

        #endregion

        #region Component Designer generated code
        /// &ltsummary> 
        /// Clean up any resources being used.
        /// </summary>
        protected override void Dispose( bool disposing )
        {
            if (disposing) if (components != null) components.Dispose();
            base.Dispose(disposing);
        }

        /// &ltsummary> 
        /// Required method for Designer support - do not modify 
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            System.Resources.ResourceManager resources = new System.Resources.ResourceManager(typeof(WebBrowser));
            this.pnlWeb = new System.Windows.Forms.Panel();
            this.webMain = new AxSHDocVw.AxWebBrowser();
            this.pnlWeb.SuspendLayout();
            ((System.ComponentModel.ISupportInitialize)(this.webMain)).BeginInit();
            this.SuspendLayout();
            // 
            // pnlWeb
            // 
            this.pnlWeb.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
            this.pnlWeb.Controls.AddRange(new System.Windows.Forms.Control[] {
                                                                                                                                                 this.webMain});
            this.pnlWeb.Dock = System.Windows.Forms.DockStyle.Fill;
            this.pnlWeb.Name = “pnlWeb”;
            this.pnlWeb.Size = new System.Drawing.Size(150, 150);
            this.pnlWeb.TabIndex = 1;
            // 
            // webMain
            // 
            this.webMain.ContainingControl = this;
            this.webMain.Dock = System.Windows.Forms.DockStyle.Fill;
            this.webMain.Enabled = true;
            this.webMain.OcxState = ((System.Windows.Forms.AxHost.State)(resources.GetObject(”webMain.OcxState”)));
            this.webMain.Size = new System.Drawing.Size(146, 146);
            this.webMain.TabIndex = 0;
            // 
            // WebBrowser
            // 
            this.Controls.AddRange(new System.Windows.Forms.Control[] {
                                                                                                                                    this.pnlWeb});
            this.Name = “WebBrowser”;
            this.pnlWeb.ResumeLayout(false);
            ((System.ComponentModel.ISupportInitialize)(this.webMain)).EndInit();
            this.ResumeLayout(false);

        }
        #endregion

        #region Public Control Properties
        // Sets the scroll bars of body of the document.
        /// &ltsummary>
        /// Special Internet Explorer BODY.Scroll Property
        /// </summary>
        [DefaultValue(ieScrollBars.None)]
        [Description("Internet Explorer's BODY.Scroll Property")]
        public ieScrollBars ScrollBars
        {
            get
            {
                if (body.scroll.Equals(”yes”)) return ieScrollBars.Always;
                if (body.scroll.Equals(”auto”)) return ieScrollBars.Auto;
                return ieScrollBars.None;
            }
            set
            {
                if (value == ieScrollBars.Auto) body.scroll = “auto”;
                if (value == ieScrollBars.None) body.scroll = “no”;
                if (value == ieScrollBars.Always) body.scroll = “yes”;
            }
        }

        [DefaultValue(BorderStyle.None)]
        public BorderStyle BorderStyle
        {
            get {return pnlWeb.BorderStyle;}
            set {pnlWeb.BorderStyle = value;}
        }

        #endregion

        #region Public HTML Properties

        [Browsable(false)]  // Do not show in the properties box
        public HTMLDocument document
        { get {return (HTMLDocument) webMain.Document;} }

        [Browsable(false)]  // Do not show in the properties box
        public HTMLBody body
        { get {return (HTMLBody) document.body;} }

        // Document Body’s innerText
        [DefaultValue("")] // Let the properties box know the default value
        [Browsable(true)]  // Do show in the properties box
        [Description("Internet Explorer's BODY.innerText Property")]
        public override string Text
        {
            get {return body.innerText;}
            set {body.innerText = value;}
        }

        // Document Body’s innerHTML
        [DefaultValue("")]
        [Description("Internet Explorer's BODY.innerHTML Property")]
        public string HTML
        {
            get {return body.innerHTML;}
            set {body.innerHTML = value;}
        }

        #endregion

        #region COM Event Handler for WebBrowser HTML Elements
        // COM Event Handler for HTML Element Events
        [DispId(0)]
        public void DefaultMethod()
        {
            // Call the custom Web Browser HTML event 
            WebBrowserElementEvent(this, document.parentWindow.@event);
        }
        #endregion

        #region Public Methods
        /// &ltsummary>
        /// Navigates to a web page, defaults to waiting for the page to load before continuing.
        /// </summary>
        /// &ltparam name=”url”>The URL to be redirected to</param>
        public void Navigate(string url)
        { Navigate(url, true); }

        /// &ltsummary>
        /// Navigates to a web page
        /// </summary>
        /// &ltparam name=”url”>The URL to be redirected to</param>
        /// &ltparam name=”wait”>Wait for the page to load before continuing</param>
        public void Navigate(string url, bool wait)
        {
            // Creates the null missing value object
            object o = System.Reflection.Missing.Value;

            // Resets the browser to an empty container, cleaning the slate
            if (wait) webMain.Navigate(null, ref o, ref o, ref o, ref o);

            // Wait until the browser is empty
            if (wait) while (document != null) {Application.DoEvents();}

            // Go to the new URL
            webMain.Navigate(url, ref o, ref o, ref o, ref o);

            if (wait) while (document.body == null) {Application.DoEvents();}
            //if (wait) while (webMain.Busy) {Application.DoEvents();}
        }

        #endregion
    }
}

Step 6: Using the Custom Web Browser Control
Here is a simple form and way to use the control above. Enjoy!


using System;
using mshtml;
using CoadTools;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace WebBrowserTutorial
{
    /// &ltsummary> Test Container for CoadTools.WebBrowser </summary>
    public class frmWebTest : System.Windows.Forms.Form
    {
        private CoadTools.WebBrowser webMain;
        private System.ComponentModel.Container components = null;

        public frmWebTest()
        { InitializeComponent(); }

        protected override void Dispose( bool disposing )
        {
            if (disposing) if (components != null) components.Dispose();
            base.Dispose(disposing);
        }

        #region Windows Form Designer generated code
        /// &ltsummary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.webMain = new CoadTools.WebBrowser();
            this.SuspendLayout();
            // 
            // webMain
            // 
            this.webMain.Dock = System.Windows.Forms.DockStyle.Fill;
            this.webMain.HTML = “webBrowser1″;
            this.webMain.Name = “webMain”;
            this.webMain.Size = new System.Drawing.Size(234, 102);
            this.webMain.TabIndex = 0;
            // 
            // frmWebTest
            // 
            this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
            this.ClientSize = new System.Drawing.Size(234, 102);
            this.Controls.AddRange(new System.Windows.Forms.Control[] {
                                                                                                                                    this.webMain});
            this.Name = “frmWebTest”;
            this.Text = “Web Browser Test”;
            this.Load += new System.EventHandler(this.frmWebTest_Load);
            this.ResumeLayout(false);

        }
        #endregion

        /// &ltsummary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        { Application.Run(new frmWebTest()); }

        private void frmWebTest_Load(object sender, System.EventArgs e)
        {
            webMain.WebBrowserElementEvent += new WebBrowserElementEventHandler(webMain_HTMLEvent);
            webMain.HTML = “&ltbr>&ltbr>&ltcenter>&ltspan style=’font: bold 10pt verdana; color: darkgreen;’>Hello World</span></center>”;
            webMain.document.onclick = webMain;
        }

        private void webMain_HTMLEvent(object sender, mshtml.IHTMLEventObj e)
        {
            Console.WriteLine(”HTML Object: ” + e.srcElement + “, Type: ” + e.type);
        }
    }
}

This concludes the test form for experimenting with the above Web Browser control.

Console.WriteLine(”Object: ” + win.@event.srcElement + “, Type: ” + win.@event.type);

}

// Now you have full access to the body of a blank HTML page.

body.innerText = “Hello World”;

}

April 28, 2008 at 7:22 am Leave a comment

Windows Server 2003 IIS and Scripting interview questions

  1. What is presentation layer responsible for in the OSI model? The presentation layer establishes the data format prior to passing it along to the network application’s interface. TCP/IP networks perform this task at the application layer.
  2. Does Windows Server 2003 support IPv6? Yes, run ipv6.exe from command line to disable it.
  3. Can Windows Server 2003 function as a bridge? Yes, and it’s a new feature for the 2003 product. You can combine several networks and devices connected via several adapters by enabling IP routing.
  4. What’s the difference between the basic disk and dynamic disk? The basic type contains partitions, extended partitions, logical drivers, and an assortment of static volumes; the dynamic type does not use partitions but dynamically manages volumes and provides advanced storage options
  5. What’s a media pool? It is any compilation of disks or tapes with the same administrative properties.
  6. How do you install recovery console? C:\i386\win32 /cmdcons, assuming that your Win server installation is on drive C.
  7. What’s new in Terminal Services for Windows 2003 Server? Supports audio transmissions as well, although prepare for heavy network load.
  8. What scripts ship with IIS 6.0? iisweb.vsb to create, delete, start, stop, and list Web sites, iisftp.vsb to create, delete, start, stop, and list FTP sites, iisdir.vsb to create, delete, start, stop, and display virtual directories, iisftpdr.vsb to create, delete, start, stop, and display virtual directories under an FTP root, iiscnfg.vbs to export and import IIS configuration to an XML file.
  9. What’s the name of the user who connects to the Web site anonymously? IUSR_computername
  10. What secure authentication and encryption mechanisms are supported by IIS 6.0? Basic authentication, Digest authentication, Advanced digest authentication, Certificate-based Web transactions that use PKCS #7/PKCS #10, Fortezza, SSL, Server-Gated Cryptography, Transport Layer Security
  11. What’s the relation between SSL and TLS? Transport Layer Security (TLS) extends SSL by providing cryptographic authentication.
  12. What’s the role of http.sys in IIS? It is the point of contact for all incoming HTTP requests. It listens for requests and queues them until they are all processed, no more queues are available, or the Web server is shut down.
  13. Where’s ASP cache located on IIS 6.0? On disk, as opposed to memory, as it used to be in IIS 5.
  14. What is socket pooling? Non-blocking socket usage, introduced in IIS 6.0. More than one application can use a given socket.
  15. Describe the process of clustering with Windows 2003 Server when a new node is added. As a node goes online, it searches for other nodes to join by polling the designated internal network. In this way, all nodes are notified of the new node’s existence. If other nodes cannot be found on a preexisting cluster, the new node takes control of the quorum resources residing on the shared disk that contains state and configuration data.
  16. What applications are not capable of performing in Windows 2003 Server clusters? The ones written exclusively for NetBEUI and IPX.
  17. What’s a heartbeat? Communication processes between the nodes designed to ensure node’s health.
  18. What’s a threshold in clustered environment? The number of times a restart is attempted, when the node fails.
  19. You need to change and admin password on a clustered Windows box, but that requires rebooting the cluster, doesn’t it? No, it doesn’t. In 2003 environment you can do that via cluster.exe utility which does not require rebooting the entire cluster.
  20. For the document of size 1 MB, what size would you expect the index to be with Indexing Service? 150-300 KB, 15-30% is a reasonable expectation.
  21. Doesn’t the Indexing Service introduce a security flaw when allowing access to the index? No, because users can only view the indices of documents and folders that they have permissions for.
  22. What’s the typical size of the index? Less then 100K documents – up to 128 MB. More than that – 256+ MB.
  23. Which characters should be enclosed in quotes when searching the index? &, @, $, #, ^, ( ), and |.
  24. How would you search for C++? Just enter C++, since + is not a special character (and neither is C).
  25. What about Barnes&Noble? Should be searched for as Barnes’&’Noble.
  26. Are the searches case-sensitive? No.
  27. What’s the order of precedence of Boolean operators in Microsoft Windows 2003 Server Indexing Service? NOT, AND, NEAR, OR.
  28. What’s a vector space query? A multiple-word query where the weight can be assigned to each of the search words. For example, if you want to fight information on ‘black hole’, but would prefer to give more weight to the word hole, you can enter black[1] hole[20] into the search window.
  29. What’s a response queue? It’s the message queue that holds response messages sent from the receiving application to the sender.
  30. What’s MQPing used for? Testing Microsoft Message Queue services between the nodes on a network.
  31. Which add-on package for Windows 2003 Server would you use to monitor the installed software and license compliance? SMS (System Management Server).
  32. Which service do you use to set up various alerts? MOM (Microsoft Operations Manager).
  33. What languages does Windows Scripting Host support? VB, VBScript, JScript.

April 28, 2008 at 7:21 am Leave a comment

Threading c-sharp

using System;
using System.Threading;

public class Alpha
{

   // This method that will be called when the thread is started
   public void Beta()
   {
      while (true)
      {
         Console.WriteLine("Alpha.Beta is running in its own thread.");
      }
   }
};

public class Simple
{
   public static int Main()
   {
      Console.WriteLine("Thread Start/Stop/Join Sample");

      Alpha oAlpha = new Alpha();

      // Create the thread object, passing in the Alpha.Beta method
      // via a ThreadStart delegate. This does not start the thread.
      Thread oThread = new Thread(new ThreadStart(oAlpha.Beta));

      // Start the thread
      oThread.Start();

      // Spin for a while waiting for the started thread to become
      // alive:
      while (!oThread.IsAlive);

      // Put the Main thread to sleep for 1 millisecond to allow oThread
      // to do some work:
      Thread.Sleep(1);

      // Request that oThread be stopped
      oThread.Abort();

      // Wait until oThread finishes. Join also has overloads
      // that take a millisecond interval or a TimeSpan object.
      oThread.Join();

      Console.WriteLine();
      Console.WriteLine("Alpha.Beta has finished");

      try
      {
         Console.WriteLine("Try to restart the Alpha.Beta thread");
         oThread.Start();
      }
      catch (ThreadStateException)
      {
         Console.Write("ThreadStateException trying to restart Alpha.Beta. ");
         Console.WriteLine("Expected since aborted threads cannot be restarted.");
      }
      return 0;
   }
 }
 -----------------------------------------
using System;
using System.Threading;

public class MonitorSample
{
   public static void Main(String[] args)
   {
      int result = 0;   // Result initialized to say there is no error
      Cell cell = new Cell( );

      CellProd prod = new CellProd(cell, 20);  // Use cell for storage,
                                               // produce 20 items
      CellCons cons = new CellCons(cell, 20);  // Use cell for storage,
                                               // consume 20 items

      Thread producer = new Thread(new ThreadStart(prod.ThreadRun));
      Thread consumer = new Thread(new ThreadStart(cons.ThreadRun));
      // Threads producer and consumer have been created,
      // but not started at this point.

      try
      {
         producer.Start( );
         consumer.Start( );

         producer.Join( );   // Join both threads with no timeout
                             // Run both until done.
         consumer.Join( );
      // threads producer and consumer have finished at this point.
      }
      catch (ThreadStateException e)
      {
         Console.WriteLine(e);  // Display text of exception
         result = 1;            // Result says there was an error
      }
      catch (ThreadInterruptedException e)
      {
         Console.WriteLine(e);  // This exception means that the thread
                                // was interrupted during a Wait
         result = 1;            // Result says there was an error
      }
      // Even though Main returns void, this provides a return code to
      // the parent process.
      Environment.ExitCode = result;
   }
}

public class CellProd
{
   Cell cell;         // Field to hold cell object to be used
   int quantity = 1;  // Field for how many items to produce in cell

   public CellProd(Cell box, int request)
   {
      cell = box;          // Pass in what cell object to be used
      quantity = request;  // Pass in how many items to produce in cell
   }
   public void ThreadRun( )
   {
      for(int looper=1; looper<=quantity; looper++)
         cell.WriteToCell(looper);  // “producing”
   }
}

public class CellCons
{
   Cell cell;         // Field to hold cell object to be used
   int quantity = 1;  // Field for how many items to consume from cell

   public CellCons(Cell box, int request)
   {
      cell = box;          // Pass in what cell object to be used
      quantity = request;  // Pass in how many items to consume from cell
   }
   public void ThreadRun( )
   {
      int valReturned;
      for(int looper=1; looper<=quantity; looper++)
      // Consume the result by placing it in valReturned.
         valReturned=cell.ReadFromCell( );
   }
}

public class Cell
{
   int cellContents;         // Cell contents
   bool readerFlag = false;  // State flag
   public int ReadFromCell( )
   {
      lock(this)   // Enter synchronization block
      {
         if (!readerFlag)
         {            // Wait until Cell.WriteToCell is done producing
            try
            {
               // Waits for the Monitor.Pulse in WriteToCell
               Monitor.Wait(this);
            }
            catch (SynchronizationLockException e)
            {
               Console.WriteLine(e);
            }
            catch (ThreadInterruptedException e)
            {
               Console.WriteLine(e);
            }
         }
         Console.WriteLine(”Consume: {0}”,cellContents);
         readerFlag = false;    // Reset the state flag to say consuming
                                // is done.
         Monitor.Pulse(this);   // Pulse tells Cell.WriteToCell that
                                // Cell.ReadFromCell is done.
      }   // Exit synchronization block
      return cellContents;
   }

   public void WriteToCell(int n)
   {
      lock(this)  // Enter synchronization block
      {
         if (readerFlag)
         {      // Wait until Cell.ReadFromCell is done consuming.
            try
            {
               Monitor.Wait(this);   // Wait for the Monitor.Pulse in
                                     // ReadFromCell
            }
            catch (SynchronizationLockException e)
            {
               Console.WriteLine(e);
            }
            catch (ThreadInterruptedException e)
            {
               Console.WriteLine(e);
            }
         }
         cellContents = n;
         Console.WriteLine(”Produce: {0}”,cellContents);
         readerFlag = true;    // Reset the state flag to say producing
                               // is done
         Monitor.Pulse(this);  // Pulse tells Cell.ReadFromCell that
                               // Cell.WriteToCell is done.
      }   // Exit synchronization block
   }
}
---------------------------------------
using System;
using System.Collections;
using System.Threading;

// Useful way to store info that can be passed as a state on a work item
public class SomeState
{
   public int Cookie;
   public SomeState(int iCookie)
   {
      Cookie = iCookie;
   }
}

public class Alpha
{
   public Hashtable HashCount;
   public ManualResetEvent eventX;
   public static int iCount = 0;
   public static int iMaxCount = 0;
   public Alpha(int MaxCount)
   {
      HashCount = new Hashtable(MaxCount);
      iMaxCount = MaxCount;
   }

   // Beta is the method that will be called when the work item is
   // serviced on the thread pool.
   // That means this method will be called when the thread pool has
   // an available thread for the work item.
   public void Beta(Object state)
   {
      // Write out the hashcode and cookie for the current thread
      Console.WriteLine(" {0} {1} :", Thread.CurrentThread.GetHashCode(),
         ((SomeState)state).Cookie);
      // The lock keyword allows thread-safe modification
      // of variables accessible across multiple threads.
      Console.WriteLine(
         "HashCount.Count=={0}, Thread.CurrentThread.GetHashCode()=={1}",
         HashCount.Count,
         Thread.CurrentThread.GetHashCode());
      lock (HashCount)
      {
         if (!HashCount.ContainsKey(Thread.CurrentThread.GetHashCode()))
            HashCount.Add (Thread.CurrentThread.GetHashCode(), 0);
         HashCount[Thread.CurrentThread.GetHashCode()] =
            ((int)HashCount[Thread.CurrentThread.GetHashCode()])+1;
      }

      // Do some busy work.
      // Note: Depending on the speed of your machine, if you
      // increase this number, the dispersement of the thread
      // loads should be wider.
      int iX  = 2000;
      Thread.Sleep(iX);
      // The Interlocked.Increment method allows thread-safe modification
      // of variables accessible across multiple threads.
      Interlocked.Increment(ref iCount);
      if (iCount == iMaxCount)
      {
         Console.WriteLine();
         Console.WriteLine(”Setting eventX “);
         eventX.Set();
      }
   }
}

public class SimplePool
{
   public static int Main(string[] args)
   {
      Console.WriteLine(”Thread Pool Sample:”);
      bool W2K = false;
      int MaxCount = 10;  // Allow a total of 10 threads in the pool
      // Mark the event as unsignaled.
      ManualResetEvent eventX = new ManualResetEvent(false);
      Console.WriteLine(”Queuing {0} items to Thread Pool”, MaxCount);
      Alpha oAlpha = new Alpha(MaxCount);  // Create the work items.
      // Make sure the work items have a reference to the signaling event.
      oAlpha.eventX = eventX;
      Console.WriteLine(”Queue to Thread Pool 0″);
      try
      {
         // Queue the work items, which has the added effect of checking
         // which OS is running.
         ThreadPool.QueueUserWorkItem(new WaitCallback(oAlpha.Beta),
            new SomeState(0));
         W2K = true;
      }
      catch (NotSupportedException)
      {
         Console.WriteLine(”These API’s may fail when called on a non-Windows 2000 system.”);
         W2K = false;
      }
      if (W2K)  // If running on an OS which supports the ThreadPool methods.
      {
         for (int iItem=1;iItem < MaxCount;iItem++)
         {
            // Queue the work items:
            Console.WriteLine(”Queue to Thread Pool {0}”, iItem);
            ThreadPool.QueueUserWorkItem(new WaitCallback(oAlpha.Beta),new SomeState(iItem));
         }
         Console.WriteLine(”Waiting for Thread Pool to drain”);
         // The call to exventX.WaitOne sets the event to wait until
         // eventX.Set() occurs.
         // (See oAlpha.Beta).
         // Wait until event is fired, meaning eventX.Set() was called:
         eventX.WaitOne(Timeout.Infinite,true);
         // The WaitOne won’t return until the event has been signaled.
         Console.WriteLine(”Thread Pool has been drained (Event fired)”);
         Console.WriteLine();
         Console.WriteLine(”Load across threads”);
         foreach(object o in oAlpha.HashCount.Keys)
            Console.WriteLine(”{0} {1}”, o, oAlpha.HashCount[o]);
      }
      return 0;
   }
}
---------------------------------
using System;
using System.Threading;

public class MutexSample
{
   static Mutex gM1;
   static Mutex gM2;
   const int ITERS = 100;
   static AutoResetEvent Event1 = new AutoResetEvent(false);
   static AutoResetEvent Event2 = new AutoResetEvent(false);
   static AutoResetEvent Event3 = new AutoResetEvent(false);
   static AutoResetEvent Event4 = new AutoResetEvent(false);

   public static void Main(String[] args)
   {
      Console.WriteLine(”Mutex Sample …”);
      // Create Mutex initialOwned, with name of “MyMutex”.
      gM1 = new Mutex(true,”MyMutex”);
      // Create Mutex initialOwned, with no name.
      gM2 = new Mutex(true);
      Console.WriteLine(” - Main Owns gM1 and gM2″);

      AutoResetEvent[] evs = new AutoResetEvent[4];
      evs[0] = Event1;    // Event for t1
      evs[1] = Event2;    // Event for t2
      evs[2] = Event3;    // Event for t3
      evs[3] = Event4;    // Event for t4

      MutexSample tm = new MutexSample( );
      Thread t1 = new Thread(new ThreadStart(tm.t1Start));
      Thread t2 = new Thread(new ThreadStart(tm.t2Start));
      Thread t3 = new Thread(new ThreadStart(tm.t3Start));
      Thread t4 = new Thread(new ThreadStart(tm.t4Start));
      t1.Start( );   // Does Mutex.WaitAll(Mutex[] of gM1 and gM2)
      t2.Start( );   // Does Mutex.WaitOne(Mutex gM1)
      t3.Start( );   // Does Mutex.WaitAny(Mutex[] of gM1 and gM2)
      t4.Start( );   // Does Mutex.WaitOne(Mutex gM2)

      Thread.Sleep(2000);
      Console.WriteLine(” - Main releases gM1″);
      gM1.ReleaseMutex( );  // t2 and t3 will end and signal

      Thread.Sleep(1000);
      Console.WriteLine(” - Main releases gM2″);
      gM2.ReleaseMutex( );  // t1 and t4 will end and signal

      // Waiting until all four threads signal that they are done.
      WaitHandle.WaitAll(evs);
      Console.WriteLine(”… Mutex Sample”);
   }

   public void t1Start( )
   {
      Console.WriteLine(”t1Start started,  Mutex.WaitAll(Mutex[])”);
      Mutex[] gMs = new Mutex[2];
      gMs[0] = gM1;  // Create and load an array of Mutex for WaitAll call
      gMs[1] = gM2;
      Mutex.WaitAll(gMs);  // Waits until both gM1 and gM2 are released
      Thread.Sleep(2000);
      Console.WriteLine(”t1Start finished, Mutex.WaitAll(Mutex[]) satisfied”);
      Event1.Set( );      // AutoResetEvent.Set() flagging method is done
   }

   public void t2Start( )
   {
      Console.WriteLine(”t2Start started,  gM1.WaitOne( )”);
      gM1.WaitOne( );    // Waits until Mutex gM1 is released
      Console.WriteLine(”t2Start finished, gM1.WaitOne( ) satisfied”);
      Event2.Set( );     // AutoResetEvent.Set() flagging method is done
   }

   public void t3Start( )
   {
      Console.WriteLine(”t3Start started,  Mutex.WaitAny(Mutex[])”);
      Mutex[] gMs = new Mutex[2];
      gMs[0] = gM1;  // Create and load an array of Mutex for WaitAny call
      gMs[1] = gM2;
      Mutex.WaitAny(gMs);  // Waits until either Mutex is released
      Console.WriteLine(”t3Start finished, Mutex.WaitAny(Mutex[])”);
      Event3.Set( );       // AutoResetEvent.Set() flagging method is done
   }

   public void t4Start( )
   {
      Console.WriteLine(”t4Start started,  gM2.WaitOne( )”);
      gM2.WaitOne( );   // Waits until Mutex gM2 is released
      Console.WriteLine(”t4Start finished, gM2.WaitOne( )”);
      Event4.Set( );    // AutoResetEvent.Set() flagging method is done
   }
}

April 28, 2008 at 7:19 am Leave a comment

Reverse Engineering Page Layout

Have you ever seen a Web page that uses a really amazing layout? With just a few simple tricks you can learn how that layout was created. In the process you can grow your Web design skills dramatically.

Tables Are the Key

HTML tables are the key to Web page design. Since HTML doesn’t reliably support absolute positioning, Web Designers have long used tables to control page layout. Dividing your Web page into a series of table cells gives you some degree of control over where text and graphics will appear.

Sophisticated page layouts require very complex tables. Designers use tables with cells that span multiple rows and columns, or even nest tables inside one another to create the desired effect. The result can be a confusing mass of HTML code.

While page layouts can be a challenge to decipher, a few simple tricks can help you understand the underlying table structure. Start by viewing the Web page’s HTML source code.

Go to the Source

You can easily view the HTML source code used to create any Web page. In fact, it’s impossible for a Web Designer to hide their HTML code so that others can’t read it.

To view a page’s source code using Internet Explorer, go to the View menu and select Source. A new window will pop up containing the page’s source code, as shown below.

The graphic below shows a snippet of the the HTML source code for the start of the body section for the KMAC web site (http://www.kmaconline.com), a relatively simple Web page that we will use as an example.

Source of beginning of body section

As you can see, the HTML code for even a simple layout can be complicated. Trying to understand the Web page by viewing the source code alone can be an exercise in futility. Surely there must be a better way!

Cracking the Secret Code

Fortunately there is a better approach: reverse engineering. While this may sound hard, the basic steps are simple.

  1. Save a copy of the page to your local computer
  2. Change the page’s HTML code to show you the underlying tables
  3. View the page in your browser

Let’s try it.

Saving the Page

To save a local copy of the Web page using Internet Explorer, go to the File menu and select Save As. A dialog box will appear asking where you’d like to save the Web page.

Notice that this dialog box has a field labeled Save as type. This lets you chose exactly how the page will be saved. By default, the field should be set to Web Page complete, which is what we want. This option tells Internet Explorer to save the Web page itself and also download a copy of all the graphics it uses. This ensures that we will see all of the page’s graphics when we view the local copy. Otherwise our local copy would be filled with broken images.

Viewing the Page

Once you’ve saved the page, you will need to load your local copy into your browser (Internet Explorer doesn’t do this automatically when you save the page!).

To load the local copy, follow these steps:

  1. Under the File menu, chose Open. A dialog box will appear.
  2. Click the Browse button in this dialog box.
  3. Another dialog box will appear that allows you to navigate the files on your local computer’s file system.
  4. Find the local copy of your Web page and select it.
  5. Click Open, and then Ok to load the page.

If you’ve done everything correctly, you should see the Web page in your browser, and the browser’s address field should say something like “C:\temp\Adventure Summer Camp for All Ages – Kent Mountain Adventure Center”.

Change the Code

Now that we have a copy of the page on our computer, we can edit the HTML source code and view any changes we will make.

To edit the source code, again go to the View menu and select Source. A window will again appear showing you the HTML code. This window is actually a copy of Notepad, the Windows text editor.

You can change the HTML code using Notepad and then select File – Save to save your changes. When you refresh the Web page in your browser, the changes will appear.

Turn on Those Tables

Now we’re finally ready to view the tables used to control layout. Find the first TABLE tag used on the page, and set the width of its borders.

For example, line 14 of the source code for the Kent Mountain page looks like this:

<TABLE border=0 cellPadding=0
cellSpacing=0 width=620>

Notice that the table’s BORDER attribute is set to zero. Change this to set the border width to something we can see like a 4, as shown below.

<TABLE border=4 cellPadding=0
cellSpacing=0 width=620>

Now save the changed code and refresh your browser window to load the changes.

This clearly shows the main table used in the page’s layout. Notice that we can see three distinct columns: a left column containing the page navigation, a right column containing the page’s main text, and a narrow middle column used for padding.

Let’s go further into the code. Notice that line 22 of the page shows another table that looks like this:

<TABLE border=0 cellPadding=0
cellSpacing=0 width="100%">

By likewise setting this table’s BORDER attribute, we can see where it appears. Or, if you prefer, you can also use the table’s BGCOLOR attribute to color the table. BGCOLOR shades all of the table’s cells in the color of your choice. For complex layouts it is sometimes easier to understand tables using both BGCOLOR and BORDER.

That’s what we’ll do in this example, as shown below.

<TABLE  BGCOLOR=orange border=4
cellPadding=0 cellSpacing=0 width="100%">

Again save the HTML source code and refresh your browser window to view the changes. The page should now appear as below.

This shows that the right column of our main table includes a second, nested table. This second table likewise includes three distinct columns.

This same approach works with images too. If we aren’t sure which parts of the page are created using graphics, and which parts are created with pure HTML, we can set the BORDER attribute for each image to see.

Look and Learn

There’s more to this layout that what we’ve seen here, and this is a relatively simple Web page. Analyzing pages with a complex layout can take quite some time. Don’t expect to understand the page’s structure immediately; it often takes several tries and a little experimentation to understand what’s really going on. As a rule of thumb, expect to spend 2-4 hours reverse engineering a page layout.

That may seem like a long time, but it’s worth the trouble. Once you understand a page layout, it’s easy to use something similar in your own page designs.

Copy, But Don’t Plagiarize

All of this raises an important question: are we stealing someone else’s work? The answer depends on how much someone’s page layout you plan to copy.

If you are debugging pages to learn new HTML tricks, then you’re probably safe. Professional Web Designers routinely debug pages in this way to build their skills.

On the other hand, if you reuse an existing page layout by simply changing its text and graphics, then you’re on shaky ethical ground.

Let your conscience be your guide, and ask yourself how much of your own Web pages you’re willing to let other people mimic.

Life as a Web Designer

And don’t forget that this same technique can be used to track down HTML errors on your own pages or in pages that you inherited from someone else.

If you plan a career in Web Design, then you can expect to spend a lot of time debugging pages in this way, both to understand them and to track down errors. You’ll find yourself reverse engineering lots of pages to track down errors that break your page. Any tools and tricks that help are worth the time investment to learn.

Don’t forget that using Keynote NetMechanic’s HTML Toolbox is also a great way to debug Web pages. HTML Toolbox includes HTML Check & Repair, a great tool that finds coding errors on your Web page and can fix them with just one click. It can dramatically reduce the time you spend debugging Web pages.

April 28, 2008 at 7:18 am Leave a comment

Older Posts


April 2008
M T W T F S S
    Jun »
 123456
78910111213
14151617181920
21222324252627
282930