Click here to Skip to main content
Click here to Skip to main content

DragonSharq Web Browser: Safe Browsing / Source Viewing

, 22 Jul 2014 CPOL
Rate this:
Please Sign up or sign in to vote.
Point DragonSharq at a web site to view its source as text, list response headers and view formatted HTML.

Introduction 

The DragonSharq web browser allows you to safely visit any URL because it retrieves and displays all data as character data. That means you do not have to worry about hidden scripts, active content or executables running malicious code. This allows you to investigate web sites and URLs you might not have otherwise been able to look at.   

Article Revision 4 : Details 

(06/06/2013)

Please note that if you've read this article before you can skip to the Current Updates section where I discuss the latest additions I've made to DragonSharq.   This latest upate (v1.4.0.0) now allows viewing of the Formatted Content in the main window via splitter. This means no more pop-up dialog for viewing formatted HTML. The bottom splitter opens automatically when you attempt to view. It looks like the following -  

 

Previous update 3 included the ability to add the User-Agent header to mimic any browser you desire. 

Many More Reasons To Use DragonSharq   

But, if you are a developer or tester there are many more reasons you may find DragonSharq helpful. Here is a list of just a few of the ideas that come to mind.  

Why Would You Use DragonSharq?

Here's a quick list of why you might want this functionality: 

  1. Great for viewing unknown pages safely. DragonSharq only downloads the bytes of the target URL and only displays them as ASCII.
  2. Incorporates my WebBrowserMenu control (see my other article for more : http://www.codeproject.com/Articles/382389/Web-Browser-Context-Menu-Ctrl-Load-Shortcut-From-Y) so you can load any page in any of web browser installed on your machine simply by right-clicking and choosing the browser from the list.
  3. Great for learning JavaScript. Point it at a .JS file and examine the code.
  4. Great for learning CSS. Point at .CSS file and examine the code.
  5. Great for decoding Tiny URLs. You can get a quick look at what site is actually retrieved before viewing in your browser.
  6. Examining the response headers gives you more information about the site and web page. Ever wondered what web server software is running at a particular site?  Now you can see it in a convenient drop down list.
  7. DargonSharq doesn't clutter up your hard drive because it does not save any files on your hard drive. There is no cache. The display in the multi-line text viewer is only displaying the bytes that come over the stream. None of it is saved.
  8. DragonSharq pulls back the data stream on a separate (background) thread so you can stop the retrieval at any time (via the Stop button).  

DragonSharq Limitations

Writing articles for CodeProject has made me keenly aware of many readers' bitter opinions so I want to list the numerous limitations of DragonSharq up front. This is a learning tool, not necessarily meant for the novice user. Here's the list of things DragonSharq could do better. Many of them I will be addressing in future versions.

  1. Fix ugly flicker as it updates the source (main multi-line text box).
  2. Scrolling the main multi-line text box does not work while the page is being retrieved.
  3. Needs a better way to load sub-content. ie Display links as clickable. Choose a link within the content and load it. 
  4. Allow user to search content for terms. 
  5. [ + ] Needs a better way to view the actual content so a user can more easily read content and determine what the site is about. Update: v1.2.0.0 Added HTMLRenderer for viewing. 
  6. [ + } Needs a less lame way to load an image from a URL found in the content. (More later in the article) 
  7. There are no navigation controls (back, forward, etc).
  8. Needs more error handling 
  9. Clean up the quick prototype code / separate into proper layers (classes)
  10. Can be slow on large sites (computerworld.com, yahoo.com, etc.)
  11. Add a way to save the source file (or portions) as a text file -- if user chooses to. 
  12. Sometimes when the URL is invalid it takes a while to fail. Allow user to set the timeout for failure.
  13. Requesting a URL which points to a binary or encoded document retrieves the bytes and looks strange. For example, if you point at an URL which resolves to a PDF, the program will display the ASCII bytes of the PDF.   

Lynx Web Browser? 

For all of you who are going to compare DragonSharq to the Lynx Web Browser here are a few notes.

The Lynx web browser definitely does some things better than DragonSharq, but they are really two different tools. Also, Lynx is difficult to get and build -- for me anyway. Also, I find it cryptic to use. Yes, I understand it is a text-based tool. Also, Lynx is really something different. It is a text-based browser. DragonSharq is more about viewing the actual HTML / Script / CSS behind the page.  

Background  

I have a filtering software installed on my child's PC. The filtering software provides a daily list of URLs that were visited. It will often contain URLs that are related to advertisements which are further down on pages that my child never sees. Those URLs can look extremely cryptic and I wondered what was at a the other end of a URL but I didn't want to browse an unsafe site. All I wanted was a preview of what is at the other end of the link. That desire to see the source HTML of any link is what drove the creation of this project.
Using the code 

The amount of code in the project is very small which makes it good for learning. The most interesting part of the code is the GetWebSource() method which retrieves the bytes from the URL.  

private void GetWebSource()
{
    string strUri = urlComboBox.Text;
        
    if (strUri.Length == 0) 
        return; 
 
    // Call helper method to insure that the URL
    // is valid -- check it starts with http:// or https://
    strUri = CheckForUrlPrefix(strUri);
    
    urlComboBox.Text = strUri;
        
    bool isAdded = visitedUrls.TryAdd(strUri.ToUpper(),strUri);
    // If the url hasn't already been added to the drop list
    // navigation add it so user can select it again later
    if (isAdded)
    {
        urlComboBox.Items.Add(strUri);
    }
        
    System.Net.WebRequest webreq; 
    System.Net.WebResponse webres; 
    try 
    {
        // The WebRequest.Create method is a factory : you send
        // in a URL and it creates a webreq obj.
        webreq = System.Net.WebRequest.Create(strUri); 
        // call the GetResponse() method to get the bytes
        // that the server is sending for the resource
        webres = webreq.GetResponse(); 
    } 
    catch (Exception exc) 
    {
        // If we get any error, just throw
        // the error message into the main content area. 
        htmlViewText.Text = exc.Message;
        return; 
    } 
    // Generate a stream object we can get the bytes from
    Stream stream = webres.GetResponseStream();
    
    // This allows us to read the stream one line at a time.
    // There are probably better ways, but this is just easy.
    StreamReader strrdr = new StreamReader(stream); 
    string strLine; 
    int line = 1; 
    
    // check to see if we're at the end
    // of the stream or if someone hit the Stop button
    while (((strLine = strrdr.ReadLine()) != null) && 
                   (!webSourceWorker.CancellationPending))
    {
        // read a line and append a NewLine for multi-line text output.
        htmlViewText.Text += string.Format("{0}{1}", strLine,Environment.NewLine);
        // increment the line counter
        ++line;
        // only update every 100 lines 
        if ((line %100) == 0)
        {
            // this method is a Windows Control method
            // that will allow the control to redraw itself.
            htmlViewText.Update();
        }
    }
    // if the user hit the Stop Button I just want to make
    // sure the control was updated one last time.
    htmlViewText.Update();
    
    // Get the Headers off of the web response object.  
    foreach (string key in webres.Headers.Keys)
    {
        // iterate through the header keys and
        // get their values and add them to the drop list.
        responseHeadersDropList.Items.Add(string.Format("{0} = {1}",
            key,webres.Headers[key]));
    }
    // this is an odd line we have to add so the first item in the drop list is displayed
    // but only do it if the drop list contains at least one item
    if (responseHeadersDropList.Items.Count > 0)
    {
        responseHeadersDropList.SelectedIndex = 0;
    }
    }
}

Background ThreadWorker: Code Indirection 

The code can be a bit confusing to examine if you've never seen code that uses the BackgroundThread Worker.

To allow the UI to update continually I quickly dragged and dropped a BackgroundThreadWorker object onto my WinForm. There may be better ways to do this, but this is the easiest. 

Hook Up the Delegate  

Once you add the BackgroundThreadWorker to your form you have to switch over to events and add the DoWork event which hooks up a delegate which is a method that will run when you call  

YourBackgroundThreadWorker.RunWorkerAsync();

RunWorkerAsync() calls the delegate method, which in the case of the DragonSharq code is the GetWebResource() method. 

Debug Details

This threading also brings up an interesting point about debugging threads. I've provided some additional helpful details under the Points of Interest section below, so be sure to check them if you are attempting to run debug versions of the source.   

Image Viewer: The Lame Way 

There's one more thing I wanted to provide: A way to  view images from URLs found in the source. I gen'd up a quick way by adding a button which opens another window.

WinForm and PicutreBox Opens A Stream 

I've added a PictureBox to the form, and I load a StreamReader from the URL you paste in the nav textbox at the top. This way you can copy a URL paste it in there and take a look at the image to try to determine what the source code is displaying. 

It all looks something like the following image. Note, the data behind the image stream is not saved. It is direct loaded by the PictureBox.  

ThirdParty : My WebContextMenu Control

Using the Exe 

Please keep in mind if you are using the utility -- if you download the Exe -- there is an additional DLL required (I've added it to the exe download). You'll see it in the EXE zip file and it is named :  WebBrowserMenu.dll

That control makes it easy to allow users to load a link in the browser of their choice. Please see my other code project article for more info:  http://www.codeproject.com/Articles/382389/Web-Browser-Context-Menu-Ctrl-Load-Shortcut-From-Y

Building the Source

If you choose to build the source, you'll note that I've added a directory under the project named \ThirdParty. The WebBrowserMenu.dll is found in there and the project should reference it properly when building.

More Third Party: Viewing Formatted Content 

One of the things I wanted to provide was a way to select some of the content and attempt to view it as formatted content. I found a great Open Source library on codeplex ( http://htmlrenderer.codeplex.com/ ) which parses HTML and displays it as formatted.  

To view formatted content all you need to do is select some content in the main multi-line text control and then right-click to get the context menu. When it appears, choose the View Formatted Content menu item.

It'll look like the following:

After you click the View Formatted Content menu item, a new window should pop up with your content.

 

However, I emphasize, should because it may fail. I'll show you what happens when it fails and why it may fail in just a moment, but first let's take a look at the simple code (because of the great HtmlRenderer library) that it took to do this work.

HTMLRenderer Code Is Simple To Use

First, I just dropped in the HTMLRenderer.dll as a reference. You will now see that is a part of the project as I've added it into the \ThirdParty directory. 

Next, I added the new Windows Form (ViewContentForm) and altered the constructor a bit. First, I'll show you the code then I'll explain what it does. 

After adding the form, since we've already added the reference to the HTMLRenderer assembly, we now have a couple of new items on the toolbar which we can drag and drop onto the form.

When you're in Design Mode in your IDE (Integrated Dev. Environment) you should see a few items in the toolbox related to the HTMLRenderer.

I dragged and dropped the HTMLPanel onto my View Content form and then I docked it so it stretched all the way across the form. Now lets take a look at the code. 

public partial class ViewContentForm : Form
{
    private string HTMLContent;
    private MainForm mainForm;
    public ViewContentForm(string htmlContent, MainForm mainForm )
    {
        this.HTMLContent = htmlContent;
        this.mainForm = mainForm;
        InitializeComponent();
    }
    
    void ViewContentFormLoad(object sender, EventArgs e)
    {
        try
        {
           mainHtmlPanel.Text = string.Format(
             "<html><body>{0}</body></html>",HTMLContent);
        }
        catch
        {
            try 
            {
                mainHtmlPanel.Text = HTMLContent;                    
            }
            catch
            {
                mainForm.DisplayError();
                this.Close();
            }
        }
   }

View Content Form Constructor

When the form is constructed I pass in a string which contains the HTMLContent that I want formatted.

I also pass in a reference to my main form. I'll explain this in a moment.  

Simply Do Two Things

Next, when the form loads I simply try two things: 

  1. Use string.Format to wrap the HTMLContent between HTML and BODY tags.
  2. Set the HTMLRenderer Panel's Text property to the HTMLContent.  

Once you do that the HTMLRenderer takes over and parses the string and attempts to create formatted HTML.

Amazing and powerful. Please check out the project at CodePlex.

Parsing / Formatting HTML May Fail and Possibly Often  

Finally, I told you that the HTML Parse / Format of the content may fail. That's because the user will often be picking only parts of the HTML. That means the HTML may not be well-formed because tags could be broken up in many ways.

What I Do For Failure

You may also notice that I try to get the HTMLRenderer to parse the string wrapped with HTML and BODY tags and then without the wrapper. That's in case someone chooses the entire document.

If it does fail I simply call  mainForm.DisplayError();

That method is on the MainForm and is why I pass a reference to that form in the constructor. The DisplayError() method looks like the following:

public void DisplayError()
{
    this.Text = "DragonSharq - !!! Could not parse HTML!!! Try again.";
    messageTimer.Start();
}  

It simply changes the text at the top of the main form so the user knows an error has occurred. After that it starts a timer, which will change the title text of the Main Form back after it fires. 

It looks like the following: 

Many Reasons the HTML Parsing May Fail 

Please keep in mind there are many reasons the HTML parsing may fail.

  • It may fail because the user selects non-viewable source like JavaScript.
  • It may fail because of missing styles 
  • It may fail because of mal-formed HTML 
  • It may fail because the HTMLRenderer doesn't support the HTML

Keep in mind this is a utility for advanced users and you won't mind so much when it fails. Smile | <img src= " />  

Note: Included open source license for HTMLRenderer

Since I'm using the HTMLRenderer, I've included the CodePlex BSD license in my code. You can see it at the CodePlex link provided and also in the DragonSharq application. 

Points of Interest  

For this project I used SharpDevelop version 4.3, an open source Visual Studio replacement. At work I use Visual Studio Enterprise edition and it has all the features available.

You can learn more about SharpDevelop  here: http://www.icsharpcode.net/opensource/sd/ 

Thread Debugging Limitation 

At one point I needed to debug the code for the GetWebSource() method. Since that method runs on the backgroundworker thread there are a couple of things you have to do. You have to create an #if and check if DEBUG is defined. If it is then you run the non-threaded code so you can step through it.

SharpDevelop Limitation

However, I found out that SharpDevelop would never break on the line like my Enterprise Edition of Visual Studio. It just skipped over it.  

Visual Studio Express Limitation

I also have Visual Studio 2010 Express on my machine so I tried it also but the debugger doesn't stop in that version either. Obviously, debugging threads like that requires the professional / enterprise edition of Visual Studio. Interesting.

Solving This Problem Without Full Visual Studio

To solve this problem you will see an extra line in the code which is commented out, which looks like:

GetWebSource();

Since the debugger will never break inside the code called by RunWorkerAsync(), if you want to debug that code you'll have to comment out the line:

webSourceWorker.RunWorkerAsync();

and then uncomment the GetWebSource() method -- which is the real target that is ran by the thread.  

Current Updates 

View Formatted Content 

Now when you select the View Formatted Content menu item instead of a pop-up dialog a hidden splitter will appear and the lower portion of the main window will display the formatted content.

It looks like this:

Setting Up the Main Form : SplitterContainer 

The code switch from the previous version was quite easy. Now instead of creating the new form I just had to add do the following:

  1. add a SplitterContainer to the main window
  2. drop the original multi-line TextBox onto the top portion of the SplitterContainer
  3. drop the HtmlPanel (from the CodePlex project) onto the bottom portion of the SplitterContainer  

The most difficult part was designer layout because it really doesn't work very well in the Sharp Develop Studio. I also use Visual Studio Enterprise and it isn't much better. SplitterContainers and Panels have always been difficult in Microsoft's tools. Anyway the code looks like the following:

void HtmlTextViewContentMenuItemClick(object sender, EventArgs e)
{
   if (htmlViewText.SelectedText.Length > 0)  // make sure some text is selected
   {
    try
    {
        mainHtmlPanel.Text = string.Format(
          "<html><body>{0}</body></html>",htmlViewText.SelectedText);
        mainHtmlPanel.Width = mainSplitContainer.Panel2.ClientSize.Width;
        mainHtmlPanel.Height = mainSplitContainer.Panel2.ClientSize.Height;
        mainSplitContainer.Panel2Collapsed = false;
    }
    catch
    {
             try 
        {
        mainHtmlPanel.Text = htmlViewText.SelectedText;
        mainHtmlPanel.Width = mainSplitContainer.Panel2.ClientSize.Width;
        mainHtmlPanel.Height = mainSplitContainer.Panel2.ClientSize.Height;
        mainSplitContainer.Panel2Collapsed = false;
           }
        catch
        {
            DisplayError();
            if (!AlwaysShowMenuItem.Checked)
            {
                mainSplitContainer.Panel2Collapsed = true;
            }
        }
       }
    }
    else // no text was selected so give an error msg.
    {
           MessageBox.Show(this,
             "Please select some text you'd like to view as HTML.", "DragonSharq");
    }
}

This change makes it much easier to use the app and examine code. I hope to keep enhancing the project for fun. Hope you find it useful.

HTML Parse Errors

There is another section within this document, but please note that if the HTML is unparsable (for many reasons as noted in the other section) then the app. will just leave the bottom portion hidden. Since there is nothing to show, there is no reason to display that portion. 

Additional Menu Item: HTML View Always Show 

If you choose the menu item it will place a check on the menu item and then the bottom portion will stay visible for you. 

User-Agent Header Info  

With the previous version (v1.2.0.0) some sites may returned a message stating that the browser wasn't supported. For example, Facebook.com returned a message that looked like the following: 

Facebook warning

Browser User-Agent Header  

To resolve this issue we need to set the User-Agent header on our WebRequest

However, I learned that to set that value I actually needed to use the System.Net.HttpWebRequest versus the System.Net.WebRequest I was using in version 1.2.0.0. Both of these objects have to be built by falling a factory method so the change is small. The code now looks like the following.

webreq = (System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(strUri);
if (UserAgentDropList.SelectedIndex > 0)
{
    webreq.UserAgent  = ((UserAgentPair)UserAgentDropList.SelectedItem).value.ToString();
}
webres = webreq.GetResponse(); 

I will explain more about what is happening inside the if statement, but first let's focus on the first line of code in the example. In the previous version I called the Create() method on the WebRequest object, but that object didn't provide a UserAgent property or a way to set the UserAgent header, so I altered it so I am now creating the  

There is a lot going on in the line inside the if statement, but most of it is just overhead so I can bind a name/value pair to the droplist. I will explain more about that, but first I need to explain a little more about what the UserAgent header is and what it does. 

What Is User-Agent Header 

It is basically just an agreed upon standard way of identifying client software that runs over HTTP. There are a number of strings which identify each browser (and other agents that run). Each of the Big 5 (MS Internet Explorer, Mozilla FireFox, Google Chrome, Apple Safari and OS Opera) have defined their own string values which they each set on their header before a request is made.

Mimic Each Browser

If you'd like to mimic a browser then all you have to do is set the User-Agent header to the same value the browser uses and any server you contact will believe your application is that browser. That is what we want to do so we can learn more about how servers respond to DragonSharq. 

Added A Resource File 

Since there are numerous strings which define each browser and browser version I've decided to create a global resource so I only have to add these strings to my application one time in one location for easy maintenance. If you look in the Properties directory of the source you will find two new files named UserAgent.resx and UserAgent.Designer.resx. Those two files represent an application resource of strings.  

If you view this file in Visual Studio or Sharp Develop Studio you will see the following:

Iterate Through Resource File For All User-Agents 

I've added a few User-Agent strings already and I've added the code to iterate through all of them and add their Key (Name) to a DropDownList on the DragonSharq main page so you can now easily choose one and emulate the appropriate browser. The DropDownList can be seen in the following screen shot: 

 

Internet Explorer Windows 7

In the example, the user has chosen Internet Explorer  running under Windows 7 (NT61). 

Now that we've mimicked (emulated) a valid browser, the request to Facebook.com succeeds and we get something that looks like the following, when we "Select All" and choose the "View Formatted Content"  menu item. Now that the Facebook server is convinced we are a valid browser it returns more data to us.

Setting the Values In the DropDownList 

The code to get the values in the DropDownList is interesting because it is quite a challenge to iterate through the string resources. After the form is done initializing I call a method I wrote called LoadAllUserAgents() The code looks like the following: 

public void LoadAllUserAgents()
{
   allUserAgents.Clear();
   allUserAgents.Add(new UserAgentPair(string.Empty,string.Empty));
   System.Resources.ResourceSet rs = 
     DragonSharq.Properties.UserAgent.ResourceManager.GetResourceSet(
     System.Globalization.CultureInfo.CurrentCulture, true, true);
    
   foreach (DictionaryEntry entry in rs)
   {
    allUserAgents.Add(new UserAgentPair(entry.Key.ToString(), entry.Value.ToString()));
   }
    
   UserAgentDropList.DisplayMember = "key";
   UserAgentDropList.ValueMember = "value";
   UserAgentDropList.DataSource = allUserAgents;
}  

Basically this code has to get a reference to the Resource, using the ResourceManager object which has a method named  GetResourceSet(). The ResourceSet is basically an Dictionary (key / value pair), which for WinForm binding sake I have to turn into a simple class I call UserAgentPair.

The UserAgentPair is the item that is bound to the DropDownList and later returned in the if statement I mentioned earlier which looks like:

webreq.UserAgent  = ((UserAgentPair)UserAgentDropList.SelectedItem).value.ToString();

That is why I have to cast item returned from the DropDownList as a UserAgentPair and then get its value (which is the User-Agent header string. I take that value and set it to the webrequest's UserAgent property so that when we make the request DragonSharq can fully emulate the chosen browser.  

Try Them Out

You can try out the UserAgents I've added (I even have one which mimics an iPad). You can also add more if you get the source and add them to the UserAgent.resx file.  I hope you have fun and learn a lot. 

Bug Fixes and Enhancements  

I've also fixed some bugs and made some small enhancements in this edition which are listed under the History section below

---- End of Current Updates  section --- 

How I Really Used DragonSharq When Google Chrome Warned Me 

Today, 05/21/2013, I attempted to read an article in Inc. Magazine on their web site. I clicked the link in Google Chrome and received the following message:

I've never seen that message before, but I wanted to read the article safely so I opened up DragonSharq and went to the page.

I found the part of the article I wanted to read, highlighted it and clicked the View Formatted Content

Then I was able to read the article in a reasonably formatted version. Kind of cool.

 

Google Safe Browsing 

I'll show you one more thing that I learned. There is a google sight that provides more information about why Inc. Magazine's sight was blocked. Here's a snapshot of what Google Safe Browsing tells us about the site.

I guess that site has had so many infections that Google Chrome now warns you. Interesting, yes? 

History

v 1.0.0.0

I made this idea up and generated the code quickly for release today on 05/19/2013.  

v 1.2.0.0 

Updated the application to include a View Formatted Content on 05/21/2013: v1.2.0.0 of DragonSharq 

v 1.3.0.0 

Updated to include the ability to send a User-Agent header to the web site so you can mimic any browser.

Also fixed bugs and made enhancements as follow:

  1. Fixed bug with Copy context menu item on html view -- It didn't do anything / didn't work: had no code in the method. 
  2. Fixed bug with Select All context menu item. Sometimes it failed. Fixed it by setting focus to the htmlViewText first then calling SelectAll() method.
  3. Enhancement: previously if you chose the "View formatted content" before selecting any text a blank window would appear. Now a message box appears asking you to select some text.
  4. Enhancement: Added "Paste & Go" option to HTML View context menu so when the user selects a URL s/he can right-click, choose "Paste & Go" and DragonSharq will navigate to that URL. Cuts down some copy/paste movements the user has to make. 

v1.4.0.0 - released 06/06/2013

  1. Enhancement: Now when the user chooses to View Formatted Content, a hidden splitter window appears at the bottom of the main window so you can see both views at the same time. 
  2. Enhancement: Added menu item which allows the user to always show the hidden splitter window (View Formatted Content area). 

v1.5.0.0 - released 07/22/2014

  1. Enhancement: Made change to code in constructor which should help the web pages load faster in text box -- still not fast.
  2. Enhancement: Now using an icon which is from openclipart.org -- see help about... after running program for more info
  3. Enhancement: Now uses version 1.2.0.0 of the WebBrowserMenu control.

License

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

Share

About the Author

newton.saber
Architect
United States United States
My newest book is Learn Python, Think Python (amazon link opens in new window/tab)
 
My previous book is Object-Oriented JavaScript (See it at Amazon.com)
 
My book, Learn JavaScript - amazon.com link is available at Amazon.
 
My upcoming book, Learn AngularJS - Think AngularJS, will be releasing later in 2014.
 
You can learn more about me and my other books, at, NewtonSaber.com
Follow on   Twitter

Comments and Discussions

 
QuestionInvalid cross thread operations. PinmemberDave Cross18-Jun-13 1:26 
AnswerRe: Invalid cross thread operations. Pinmembernewton.saber19-Jun-13 3:27 
GeneralRe: Invalid cross thread operations. PinmemberTomijan23-Jul-14 8:18 
GeneralRe: Invalid cross thread operations. Pinmembernewton.saber23-Jul-14 8:24 
GeneralRe: Invalid cross thread operations. PinmemberTomijan23-Jul-14 10:39 
GeneralMy vote of 5 PinmemberMihai MOGA13-Jun-13 21:55 
GeneralRe: My vote of 5 Pinmembernewton.saber14-Jun-13 10:12 
GeneralMy vote of 5 PinmemberLoRdPMN23-May-13 6:45 
GeneralRe: My vote of 5 Pinmembernewton.saber23-May-13 8:48 
GeneralMy vote of 5 Pinmemberfredatcodeproject22-May-13 2:09 
GeneralRe: My vote of 5 Pinmembernewton.saber22-May-13 3:21 
QuestionUseful utility PinprofessionalPrasad Khandekar20-May-13 5:08 
AnswerRe: Useful utility Pinmembernewton.saber20-May-13 7:42 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.141220.1 | Last Updated 22 Jul 2014
Article Copyright 2014 by newton.saber
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid