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

The Code Project Forum Analyzer : Find out how much of a life you don't have!

By , 26 Mar 2011
 

Figure 01 - The app in action, analyzing Lounge posts

Figure 02 - Charting the exported CSV data in Excel

Introduction

This is an unofficial Code Project application that can analyze forums over a range of posts to retrieve posting statistics for individual members. Like my other Code Project applications (and that of others like John and Luc), this app uses HTML scraping and parsing to extract the required information. So any change to the site layout/CSS can potentially break the functioning of this application. There's no workaround for that until the time that Code Project provides an official web-service that will expose this data.

Using the app

I've got a hardcoded list of forums that are shown in a combo-box. I chose the more important forums and also the ones with a decent amount of posts. You can also choose the number of posts you want to fetch and analyze. The app currently supports fetching 1,000 posts, 5,000 posts, or 10,000 posts. Anything more than 10,000 is not safe as you will then start seeing the effects of the heavy-loaded Code Project database servers, which means time outs and lost pages. This won't break the app but the app will be forced to skip pages which results in reduced statistical accuracy. Even with 10,000 posts you can still hit this on forums like Bugs/Suggestions or C++/CLI because some of the older pages have posts with malformed HTML which breaks the HTML parser. There is a status log at the bottom of the UI which will list such parsing errors and at the end of the analysis will also tell you how many posts were skipped.

Figure 03 - Forums with malformed HTML will result in skipped posts (49 in the screenshot)

CP has added stricter checks on the HTML that's allowed in posts, so you should see this less frequently as time progresses. Once the analysis is done, you can use the Export feature to save the results in a CSV file. You can now open this CSV file in Excel and do further analysis and statistical charting.

Handy Tip

If you hover the mouse over a display name it'll highlight the display name and the mouse cursor turns into a hand. This means you can click the display name to open the user's CP profile in the default browser, and you can do this even as an analysis is in progress.

Exporting to CSV and foreign language member-names

It should correctly choose the comma-separator based on your current locale (thanks to Mika Wendelius for helping me get this right) but I do not save the file as Unicode. That's because Excel seems to have trouble with it and treats it as one big single column (instead of 3 separate columns). So right now I am using Encoding.Default which is a tad better than not using any, but you may run into weirdness in Excel if any of the member display names have Unicode characters. I have not figured out how to work around that and at the moment I don't know if I want to spend time researching a fix. If any of you know how to resolve that, I'd appreciate any suggestions you have for this.

Implementation details

The core class that fetches all the data from the website is the ForumAnalyzer class. It uses the excellent HtmlAgilityPack for HTML parsing. Here are some of the more interesting methods in this class.

private void InitMaxPosts()
{
    string html = GetHttpPage(GetFetchUrl(1), this.timeOut);

    HtmlDocument document = new HtmlDocument();
    document.LoadHtml(html);

    HtmlNode trNode = document.DocumentNode.SelectNodes(
        "//tr[@class='forum-navbar']").FirstOrDefault();
    if (trNode != null)
    {
        if (trNode.ChildNodes.Count > 2)
        {
            var node = trNode.ChildNodes[2];
            string data = node.InnerText;
            int start = data.IndexOf("of");
            if (start != -1)
            {
                int end = data.IndexOf('(', start);
                if (end != -1)
                {
                    if (end - start - 2 > 0)
                    {
                        var extracted = data.Substring(start + 2, end - start - 2);
                        Int32.TryParse(extracted.Trim(), 
                          NumberStyles.AllowThousands, 
                          CultureInfo.InvariantCulture, out maxPosts);
                    }
                }
            }
        }
    }
}

That's used to determine that maximum number of posts in the forum. Since the pages are dynamic, you won't get an error if you try fetching pages beyond the last page, but it will waste time and bandwidth and also mess up the statistics. So it's important to make sure that we know what the maximum number of pages we can fetch safely.

public ICollection<Member> FetchPosts(int from)
{
    if (from > maxPosts)
    {
        throw new ArgumentOutOfRangeException("from");
    }

    string html = GetHttpPage(GetFetchUrl(from), this.timeOut);

    HtmlDocument document = new HtmlDocument();
    document.LoadHtml(html);

    Collection<Member> members = new Collection<Member>();
    
    foreach (HtmlNode tdNode in document.DocumentNode.SelectNodes(
        "//td[@class='Frm_MsgAuthor']"))
    {
        if (tdNode.ChildNodes.Count > 0)
        {
            var aNode = tdNode.ChildNodes[0];
            int id;
            if (aNode.Attributes.Contains("href") 
                && TryParse(aNode.Attributes["href"].Value, out id))
            {
                members.Add(new Member(id, aNode.InnerText));
            }
        }
    }
    
    return members;
}

This is where the post data is extracted. It takes advantage of the Frm_MsgAuthor CSS class that Code Project uses. Now that I've mentioned this here, I bet Murphy's laws will reveal themselves and Chris will rename that class arbitrarily. Note that this class will just return post data in big chunks so it's up to the caller to actually do any analysis on the data. I do that in my application's view-model. This decision may be questioned by some people who may feel that a separate wrapper should have done the calculations and the VM should have then merely accessed that. If so, yeah, they're probably right but for such a simple app I went for simplicity versus design purity.

The code that uses the ForumAnalyzer class is called from a background worker thread, and when it completes, a second background worker is spawned to sort the results. I've also used Parallel.For from the Task Parallel Library which gave me a significant speed boost. Initial runs took 8-9 minutes on my connection (15 Mbps, boosted to 24 Mbps) but once I added the Parallel.For, this went up to a little over a minute. Going from around 8 minutes to 1 minute was quite impressive! There were a few side effects though which I will talk about after this code listing.

private void Fetch()
{
    canFetch = false;
    canExport = false;
    this.logs.Clear();

    var dispatcher = Application.Current.MainWindow.Dispatcher;
    Stopwatch stopWatch = new Stopwatch();
    
    BackgroundWorker worker = new BackgroundWorker();
    worker.DoWork += (sender, e) =>
        {
            ForumAnalyzer analyzer = new ForumAnalyzer(this.SelectedForum);

            dispatcher.Invoke((Action)(() =>
            {
                this.TimeElapsed = TimeSpan.FromSeconds(0).ToString(timeSpanFormat);
                this.Total = 0;
                this.results.Clear();
                AddLog(new LogInfo("Started fetching posts..."));
            }));

            Dictionary<int, MemberPostInfo> results = 
                  new Dictionary<int, MemberPostInfo>();
            stopWatch.Start();

            ParallelOptions options = new ParallelOptions() 
              { MaxDegreeOfParallelism = 8 };
            Parallel.For(0, Math.Min((int)(PostCount)this.PostsToFetch, 
                analyzer.MaxPosts) / postsPerPage, options, (i) =>
            {
                ICollection<Member> members = null;
                int trials = 0;

                while (members == null && trials < 5)
                {
                    try
                    {
                        members = analyzer.FetchPosts(i * postsPerPage + 1);
                    }
                    catch
                    {
                        trials++;
                    }
                }

                if (members == null)
                {
                    dispatcher.Invoke((Action)(() =>
                    {
                        AddLog(new LogInfo(
                            "Http connection failure", i, postsPerPage));
                    }));

                    return;
                }

                if (members.Count < postsPerPage)
                {
                    dispatcher.Invoke((Action)(() =>
                    {
                        AddLog(new LogInfo(
                            "Html parser failure", i, postsPerPage - members.Count));
                    }));
                }

                lock (results)
                {
                    foreach (var member in members)
                    {
                        if (results.ContainsKey(member.Id))
                        {
                            results[member.Id].PostCount++;
                        }
                        else
                        {
                            results[member.Id] = new MemberPostInfo() 
                              { Id = member.Id, DisplayName = member.DisplayName, 
                                  PostCount = 1 };

                            dispatcher.Invoke((Action)(() =>
                            {
                                this.results.Add(results[member.Id]);
                            }));
                        }
                    }

                    dispatcher.Invoke((Action)(() =>
                    {
                        this.Total += members.Count;
                        this.TimeElapsed = stopWatch.Elapsed.ToString(timeSpanFormat);
                    }));
                }
            });
        };

    worker.RunWorkerCompleted += (s, e) =>
        {
            stopWatch.Stop();

            BackgroundWorker sortWorker = new BackgroundWorker();
            sortWorker.DoWork += (sortSender, sortE) =>
            {
                var temp = this.results.OrderByDescending(
                    ks => ks.PostCount).ToArray();

                dispatcher.Invoke((Action)(() =>
                {
                    AddLog(new LogInfo("Sorting results..."));
                    foreach (var item in temp)
                    {
                        this.results.Remove(item);
                        this.results.Add(item);
                    }
                }));
            };

            sortWorker.RunWorkerCompleted += (sortSender, sortE) =>
                {
                    AddLog(new LogInfo("Task completed!"));
                    canFetch = true;
                    canExport = true;
                    CommandManager.InvalidateRequerySuggested();
                };

            sortWorker.RunWorkerAsync();                    
        };

    worker.RunWorkerAsync();
}

When I added the Parallel.For, the first thing I noticed was that the number of errors and time outs significantly went up to the point where the results were almost useless. What was happening was that I was fighting CP's built-in flood protection and I realized that if I spawned too many connections in parallel, this just would not work. With some trial and error, I finally reduced the maximum level of concurrency to 8 which gave me the best results. Coincidentally I have 4 cores with hyper threading, so that's 8 virtual CPUs - so this was perfect for me I guess. Note that this is pure coincidence, the reason I had to reduce the parallelism was the CP flood-prevention system and not the number of cores I had.

A major side effect of using Parallel.For was that I lost the ability to fetch pages in a serial order. Had I not used the parallel loops, I could detect an HTML parsing error, and then skip that one post and continue with the post after that one. But with concurrent loops, if I hit an error, I am forced to skip the rest of the page. Of course, it's not impossible to handle this correctly by spawning off a side-task that will fetch just the skipped posts minus the malformed one, but this seriously increased the complexity of the code. I decided that I can live with 50-100 lost posts out of 10,000. That's less than a 1% deviation in accuracy which I thought was acceptable for the application.

Well, that's it. Thanks for reading this article and for trying out the application. As usual, I appreciate any and all feedback, criticism and comments.

References

Acknowledgements

Thanks to the following CPians for their help with testing the application! Really, really appreciate that. I only listed the first 3 folks, but many others helped too. So thanks goes to all of them, and I apologize for not listing everybody here (I didn't realize so many would be so helpful)!

History

  • March 26, 2011 - Article first published

License

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

About the Author

Nish Sivakumar

United States United States
Nish is a real nice guy who has been writing code since 1990 when he first got his hands on an 8088 with 640 KB RAM. Originally from sunny Trivandrum in India, he has been living in various places over the past few years and often thinks it’s time he settled down somewhere.
 
Nish has been a Microsoft Visual C++ MVP since October, 2002 - awfully nice of Microsoft, he thinks. He maintains an MVP tips and tricks web site - www.voidnish.com where you can find a consolidated list of his articles, writings and ideas on VC++, MFC, .NET and C++/CLI. Oh, and you might want to check out his blog on C++/CLI, MFC, .NET and a lot of other stuff - blog.voidnish.com.
 
Nish loves reading Science Fiction, P G Wodehouse and Agatha Christie, and also fancies himself to be a decent writer of sorts. He has authored a romantic comedy Summer Love and Some more Cricket as well as a programming book – Extending MFC applications with the .NET Framework.
 
Nish's latest book C++/CLI in Action published by Manning Publications is now available for purchase. You can read more about the book on his blog.
 
Despite his wife's attempts to get him into cooking, his best effort so far has been a badly done omelette. Some day, he hopes to be a good cook, and to cook a tasty dinner for his wife.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
BugEditorial BugmemberBassam Abdul-Baki30-Sep-11 6:00 
Acknowledgements
Thanks to the following CPians for their help with testing the application! Really, really appreciate that. I only listed the first 3 folks, but many others helped too. So thanks goes to all of them, and I apologize for not listing everybody here (I didn't realize so many would be so helpful)!
 
•Abhinav S
•Joan Murt
•Mika Wendelius
•Sandeep Mewara

GeneralRe: Editorial BugmvpNishant Sivakumar30-Sep-11 7:03 
Yeah, Mika pointed this out here:
 
http://www.codeproject.com/Messages/3830700/My-vote-of-5.aspx[^]
 
I just never got around to fixing it Smile | :)
Regards,
Nish
My technology blog: voidnish.wordpress.com

BugBug! Bug! Bug!memberNagy Vilmos22-Jun-11 3:21 
Oh Nish, I found a bug. Frown | :(
 
The list of forums is incomplete, the Java and JavaScript forums are not listed.


Panic, Chaos, Destruction. My work here is done.
Drink. Get drunk. Fall over - P O'H
OK, I will win to day or my name isn't Ethel Crudacre! - DD Ethel Crudacre
I cannot live by bread alone. Bacon and ketchup are needed as well. - Trollslayer
Have a bit more patience with newbies. Of course some of them act dumb - they're often *students*, for heaven's sake - Terry Pratchett

GeneralRe: Bug! Bug! Bug!mvpNishant Sivakumar22-Jun-11 3:23 
Nagy Vilmos wrote:
The list of forums is incomplete, the Java and JavaScript forums are not
listed.

Smile | :)
 
The forum list is hardcoded - so those omissions were intentional!
Regards,
Nish
Are you addicted to CP? If so, check this out:
The Code Project Forum Analyzer : Find out how much of a life you don't have!
 
My technology blog: voidnish.wordpress.com

GeneralRe: Bug! Bug! Bug!mvpJohn Simmons / outlaw programmer30-Jun-11 2:22 
I'm honestly surprised that someone noticed they were even missing. Smile | :)
".45 ACP - because shooting twice is just silly" - JSOP, 2010
-----
You can never have too much ammo - unless you're swimming, or on fire. - JSOP, 2010
-----
"Why don't you tie a kerosene-soaked rag around your ankles so the ants won't climb up and eat your candy ass." - Dale Earnhardt, 1997

GeneralRe: Bug! Bug! Bug!mvpNishant Sivakumar30-Jun-11 4:12 
John Simmons / outlaw programmer wrote:
I'm honestly surprised that someone noticed they were even missing.

Nagy's a closet java-lover! Big Grin | :-D
Regards,
Nish
Are you addicted to CP? If so, check this out:
The Code Project Forum Analyzer : Find out how much of a life you don't have!
 
My technology blog: voidnish.wordpress.com

GeneralMy vote of 5memberNagy Vilmos13-Jun-11 5:06 
Wow Nish. You wrote this only to find out that DD posts more gibberish than anyone. Could have saved you a lot of effort!
 
Jokes aside, this is pretty cool!
GeneralRe: My vote of 5mvpNishant Sivakumar22-Jun-11 3:23 
Thanks Nagy!
Regards,
Nish
Are you addicted to CP? If so, check this out:
The Code Project Forum Analyzer : Find out how much of a life you don't have!
 
My technology blog: voidnish.wordpress.com

GeneralMy vote of 5memberashishkumar0081-Jun-11 7:02 
Great work...
GeneralRe: My vote of 5mvpNishant Sivakumar22-Jun-11 3:24 
Thanks Ashish.
Regards,
Nish
Are you addicted to CP? If so, check this out:
The Code Project Forum Analyzer : Find out how much of a life you don't have!
 
My technology blog: voidnish.wordpress.com

GeneralQuestion for you NishmvpSacha Barber25-May-11 1:00 
Nish sorry to ask this here but, you know your book CLI in action, having never programmed in C++ do you think I would be able to follow it?
Sacha Barber
  • Microsoft Visual C# MVP 2008-2011
  • Codeproject MVP 2008-2011
Open Source Projects
Cinch SL/WPF MVVM

Your best friend is you.
I'm my best friend too. We share the same views, and hardly ever argue
 
My Blog : sachabarber.net

GeneralRe: Question for you NishmvpNishant Sivakumar25-May-11 1:04 
Sacha Barber wrote:
Nish sorry to ask this here but, you know your book CLI in action, having never
programmed in C++ do you think I would be able to follow it?

Hey Sacha,
 
One premise the book makes is that the reader has previously used C++ as well as .NET. That said, someone who's at expert-level in C# (such as yourself) would probably not have any issues reading the book. There may be a few odd instances where some of the text may sound a little confusing. But in general, I don't see any issues.
 
There are two sample chapters here:
 
http://www.manning.com/sivakumar/[^]
 
So perhaps going through those will give you an idea of whether you will find the book useful or not.
Regards,
Nish
Are you addicted to CP? If so, check this out:
The Code Project Forum Analyzer : Find out how much of a life you don't have!
 
My technology blog: voidnish.wordpress.com

GeneralRe: Question for you NishmvpSacha Barber25-May-11 2:17 
Thanks for that Nish. Have a tonne (like loads) of stuff that I would like to get to grips with 1st, Like I would really like to learn F#, and have really big web based idea that is going to keep me busy for ages, but I was just curious. So thanks for the feedback.
Sacha Barber
  • Microsoft Visual C# MVP 2008-2011
  • Codeproject MVP 2008-2011
Open Source Projects
Cinch SL/WPF MVVM

Your best friend is you.
I'm my best friend too. We share the same views, and hardly ever argue
 
My Blog : sachabarber.net

GeneralRe: Question for you NishmvpNishant Sivakumar25-May-11 2:19 
You are most welcome, Sacha.
Regards,
Nish
Are you addicted to CP? If so, check this out:
The Code Project Forum Analyzer : Find out how much of a life you don't have!
 
My technology blog: voidnish.wordpress.com

GeneralRe: Question for you NishmvpPete O'Hanlon26-May-11 9:43 
Any help you need with the C++/CLI concepts, feel free to ask me mate. I tend to keep relatively quiet about it, but I did a hell of a lot of C++ back in the day, and I rewrote a lot of our core C++ libraries into CLI.

Forgive your enemies - it messes with their heads

My blog | My articles | MoXAML PowerToys | Mole 2010 - debugging made easier - my favourite utility


GeneralRe: Question for you NishmvpSacha Barber26-May-11 11:25 
Cool thanks, Fredrik has told me not bother with it, as he thinks its the worst of both worlds, but he purest C++ chap or purest C# chap.
 
I will look into it and make my own mind up. Thanks though man, champion
Sacha Barber
  • Microsoft Visual C# MVP 2008-2011
  • Codeproject MVP 2008-2011
Open Source Projects
Cinch SL/WPF MVVM

Your best friend is you.
I'm my best friend too. We share the same views, and hardly ever argue
 
My Blog : sachabarber.net

GeneralMy vote of 5memberZeeroC00l25-Apr-11 19:28 
My 5. Smile | :) Nice work
GeneralRe: My vote of 5mvpNishant Sivakumar26-Apr-11 1:28 
Thanks.
Regards,
Nish
Are you addicted to CP? If so, check this out:
The Code Project Forum Analyzer : Find out how much of a life you don't have!
 
My technology blog: voidnish.wordpress.com

GeneralMy vote of 5memberOshtri Deka24-Apr-11 6:42 
Idea itself deserves 5.
GeneralRe: My vote of 5mvpNishant Sivakumar24-Apr-11 6:49 
Thank you!
Regards,
Nish
Are you addicted to CP? If so, check this out:
The Code Project Forum Analyzer : Find out how much of a life you don't have!
 
My technology blog: voidnish.wordpress.com

GeneralMy vote of 5memberPompeyBoy319-Apr-11 6:10 
Just downloaded and had a little play. Very Interesting.
 
Suggestion - It would be good if you could implement a way of displaying what rep points were earned for the posts aswell as. For example
 
posts member rep points
3 Thatraja 33
 
Don't see how you can implement it though.
GeneralRe: My vote of 5mvpNishant Sivakumar19-Apr-11 6:12 
Thanks Pompey.
 
Yeah since the rep points info is private to each member, I don't think there's any way to do that.
Regards,
Nish
Are you addicted to CP? If so, check this out:
The Code Project Forum Analyzer : Find out how much of a life you don't have!
 
My technology blog: voidnish.wordpress.com

GeneralRe: My vote of 5memberPompeyBoy319-Apr-11 6:14 
Shame, I reckon I might be top of that one. Wink | ;)
GeneralRe: My vote of 5mvpNishant Sivakumar19-Apr-11 6:15 
Smile | :)
Regards,
Nish
Are you addicted to CP? If so, check this out:
The Code Project Forum Analyzer : Find out how much of a life you don't have!
 
My technology blog: voidnish.wordpress.com

GeneralMy vote of 5memberkoolprasad200319-Apr-11 0:03 
Great
GeneralRe: My vote of 5mvpNishant Sivakumar19-Apr-11 2:11 
Thank you.
Regards,
Nish
Are you addicted to CP? If so, check this out:
The Code Project Forum Analyzer : Find out how much of a life you don't have!
 
My technology blog: voidnish.wordpress.com

GeneralMy vote of 5mvpAbhijit Jana18-Apr-11 23:54 
Great One !!
GeneralRe: My vote of 5mvpNishant Sivakumar19-Apr-11 2:11 
Thanks AJ!
Regards,
Nish
Are you addicted to CP? If so, check this out:
The Code Project Forum Analyzer : Find out how much of a life you don't have!
 
My technology blog: voidnish.wordpress.com

GeneralMy vote of 5memberSChristmas12-Apr-11 3:19 
Good article
GeneralRe: My vote of 5mvpNishant Sivakumar12-Apr-11 3:25 
Thank you!
Regards,
Nish
Are you addicted to CP? If so, check this out:
The Code Project Forum Analyzer : Find out how much of a life you don't have!
 
My technology blog: voidnish.wordpress.com

GeneralMy vote of 5membermkgoud12-Apr-11 3:15 
Nice article.
GeneralRe: My vote of 5mvpNishant Sivakumar12-Apr-11 3:16 
Thanks!
Regards,
Nish
Are you addicted to CP? If so, check this out:
The Code Project Forum Analyzer : Find out how much of a life you don't have!
 
My technology blog: voidnish.wordpress.com

GeneralMy vote of 5member d@nish 6-Apr-11 5:38 
Nice one Nish.
 
One thing I noticed, the forum list is not complete. Is there any reason for it?
GeneralRe: My vote of 5mvpNishant Sivakumar6-Apr-11 5:40 
d@nish wrote:
One thing I noticed, the forum list is not complete. Is there any reason for it?

I picked a list of the most active forums. It's a hard-coded list of forums (in an enum).
 
I meant to add code to dynamically pull this data but eventually never got around to doing it.
Regards,
Nish
Are you addicted to CP? If so, check this out:
The Code Project Forum Analyzer : Find out how much of a life you don't have!
 
My technology blog: voidnish.wordpress.com

GeneralRe: My vote of 5member d@nish 6-Apr-11 6:57 
Get it. I should have taken pains to at least download and view the code. Just took the executable. Lazy me.
"Your code will never work, Luc's always will.", Richard MacCutchan[^]

GeneralRe: My vote of 5mvpNishant Sivakumar6-Apr-11 7:00 
No problem, happy to explain! Smile | :)
Regards,
Nish
Are you addicted to CP? If so, check this out:
The Code Project Forum Analyzer : Find out how much of a life you don't have!
 
My technology blog: voidnish.wordpress.com

GeneralMy vote of 5mvpAspDotNetDev5-Apr-11 10:10 
Finally, I am immortalized in a screenshot in an article on CP Big Grin | :-D
 
Great to see utilities with real world uses.
GeneralRe: My vote of 5mvpNishant Sivakumar5-Apr-11 10:11 
AspDotNetDev wrote:
Finally, I am immortalized in a screenshot in an article on CP

Smile | :)
 
And thank you!
Regards,
Nish
Are you addicted to CP? If so, check this out:
The Code Project Forum Analyzer : Find out how much of a life you don't have!
 
My technology blog: voidnish.wordpress.com

GeneralMy vote of 5memberManfred R. Bihy5-Apr-11 4:14 
Nice, I like it!
GeneralRe: My vote of 5mvpNishant Sivakumar5-Apr-11 4:45 
Thank you! Smile | :)
Regards,
Nish
Are you addicted to CP? If so, check this out:
The Code Project Forum Analyzer : Find out how much of a life you don't have!
 
My technology blog: voidnish.wordpress.com

GeneralMy vote of 5memberPetr Pechovic5-Apr-11 2:04 
cool
GeneralRe: My vote of 5mvpNishant Sivakumar5-Apr-11 4:00 
Thank you!
Regards,
Nish
Are you addicted to CP? If so, check this out:
The Code Project Forum Analyzer : Find out how much of a life you don't have!
 
My technology blog: voidnish.wordpress.com

GeneralMy vote of 5mvpMarcelo Ricardo de Oliveira4-Apr-11 3:25 
That's cool article, Nish, got 5 from me. Thumbs Up | :thumbsup:
cheers
marcelo
Take a look at Snail Quest here in The Code Project.

GeneralRe: My vote of 5mvpNishant Sivakumar4-Apr-11 3:28 
Thank you! Smile | :)
Regards,
Nish
Are you addicted to CP? If so, check this out:
The Code Project Forum Analyzer : Find out how much of a life you don't have!
 
My technology blog: voidnish.wordpress.com

GeneralMy vote of 5mvpthatraja27-Mar-11 4:18 
Because I have a life. Smile | :)
Again nice CP application from you. BTW where is the update for your CPVanityLite?
Cheers.
GeneralRe: My vote of 5mvpNishant Sivakumar27-Mar-11 4:26 
Thanks! Smile | :)
 
thatraja wrote:
BTW where is the update for your CPVanityLite?

 
Been procrastinating doing that Blush | :O

GeneralMy vote of 5membermaq_rohit27-Mar-11 3:54 
its a good article and ofcourse good future enhancement for my CP tool as well for mobile http://www.codeproject.com/KB/android/CPDroid.aspx..
 
5*****
GeneralRe: My vote of 5mvpNishant Sivakumar27-Mar-11 4:03 
Thank you!

GeneralMy vote of 5memberSlacker00727-Mar-11 2:41 
Thanks Nish!
 
I can't begin to thank you for providing yet another tool for showing me that I truly have ZERO life ambitions and that next month's bills are just a click away.
 
Smile | :)
AnswerRe: My vote of 5mvpNishant Sivakumar27-Mar-11 2:49 
Slacker007 wrote:
Thanks Nish!

I can't begin to thank you for providing yet another tool
for showing me that I truly have ZERO life ambitions and that next month's bills
are just a click away.


Laugh | :laugh:
 
You're welcome!

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

Permalink | Advertise | Privacy | Mobile
Web03 | 2.6.130617.1 | Last Updated 26 Mar 2011
Article Copyright 2011 by Nish Sivakumar
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid