Pages

Ads 468x60px

Thursday, August 16, 2012

ProgressBar not Updating Fix - C#

It has been sited by many StackOverflow questions that, usually when using a BackgroundWorker, your ProgressBar will not update correctly when using C#. I do not know why this happens, however some people suggest that it is because of the threaded interface in Windows Vista and Windows 7.The ProgressBar would get to about 75% full when it should have been at its maximum, and would revert back to 0% before it was fully drawn. Here is what that looked like:

And this is the example code I used:
        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            for (int i = 1; (i <= 100); i++)
            {
                    // Perform a time consuming operation and report progress.
                    System.Threading.Thread.Sleep(20);
                    backgroundWorker1.ReportProgress((i ));
            }
        }

        private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            progressBar1.Value = e.ProgressPercentage;
            if (progressBar1.Maximum == e.ProgressPercentage)
                progressBar1.Value = 0;
        }

However, Mark Lansdown from StackOverflow found a very useful solution, taken from this question.

What he suggested is to draw the value, then draw the value minus 1, because that would force a redraw on the ProgressBar. To to that, I just changed my ProgressChanged event to:

private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            progressBar1.Value = e.ProgressPercentage;
            if (e.ProgressPercentage != 0)
                progressBar1.Value = e.ProgressPercentage - 1;
            progressBar1.Value = e.ProgressPercentage;
            if (progressBar1.Maximum == e.ProgressPercentage)
                progressBar1.Value = 0;
        }

And the result is that the ProgressBar will now be smoothly redrawn to 100% before it is reverted.

And while this is most certainly strange behavior, I can verify that it works, and now the ProgressBar will fill all the way up.

I hope you enjoyed!

Center A Form to another form in C#

Recently, while I was using C#, I had an issue. I wanted to center a form in the middle of another form. After drawing a chart and doing some math, I have come up with this piece of code:

form2.SetDesktopLocation(form1.Location.X + ((form1.Width / 2) - form2.Width / 2), form1.Location.Y + ((form1.Height / 2) - form2.Height / 2));
What this code actually does, is it first gets the location of form1 X. It then adds that to form1 Width / 2, and subtracts that from form2's width / 2, and does the same for Y. It does that, because you get the X position, and that position needs to be in the center of form1's width. Then, you need to factor in half of form2's width per side, because form1's width was divided by 2. Don't worry if you do not understand. This code assumes the form you want to center is form2, and the form you want to center it around is form1. You have to create a variable for the current instance of form1 and form2. Here is an example of that:

Form1 form1 = (Form1)Application.OpenForms[0];
What this code does, is it gets a current array of the open forms. If form2 is your child form, and form 1 is your main form, form1 would be position [0] and form2 would be position [1].

Here is a picture of this:



I hope it helps!

Sunday, August 12, 2012

How to access Opera History in C#

Hi all! Today, I will be continuing my series on getting browser history in C#. I am going to focus on Opera today. Opera is different from Chrome and Firefox, in the fact that it does not use an SQLite Database to store browser history. Instead, it uses a text file. Each URL entry has four lines. The first line is the title, the second is the URL, the third is the time visited in Unix, or Epoch, time, and the last is the frequency. You can find this file in your appdata folder, by typing %appdata% into run, then browsing to Opera/Opera/global_history.dat and opening it with a text editor, such as NotePad++. Here is an example of my file:

The default frequency, for a site that has been visited one time, is -1. If it has been visited more than once, it will rise up into the millions. I am not sure how the frequency corresponds to the number of visits. If you know, please tell me.





To access this in C#, you will need to read the file line by line, and determine if the line is the title, url, etc. I have come up with this code that should help you:
 public IEnumerable GetHistory(bool display)
 {
  // Get Current Users App Data
  string documentsFolder = GetFolder();
  //If directory exists
  if (Directory.Exists(documentsFolder))
  {
   //This is the line number of the history file
   int lineNumber = 1;
   //This is the history file in the documents folder
   string historyFile = documentsFolder + "global_history.dat";
   //URL Variables
   string title = null;
   string url = null;
   int frequency = 0;
   DateTime visited = new DateTime();
   //These variables tell you if each line has been parsed
   //and each part has been assigned
   bool urlAssigned = false;
   bool titleAssigned = false;
   bool frequencyAssigned = false;
   bool visitedAssigned = false;
   //The url to assign to the URL table
   URL u;
   //Create a new StreamReader using the history file
   //to read the file line by line
   System.IO.StreamReader file =
 new System.IO.StreamReader(historyFile);
   //The line that is being read
   string line;
   //While the line that is being read is being read by
   //file.ReadLine, and is not null
   while ((line = file.ReadLine()) != null)
   {
    /*This is a table of what each line is
     * Line 1 = The Title of the URL
     * Line 2 = The URL of the URL
     * Line 3 = The Unix Time of which the URL was visited
     * Line 4 = The frequency of visits, which cannot convert 
     */
    //If the line number is the first, or if the line number minus 1
    //is a multiple of 4, for example, line number 5 - 1 is 4, which 
    //is a multiple of 4
    if (lineNumber == 1 || (lineNumber - 1) % 4 == 0)
    {
     Debug.WriteLine(line);
     title = line;
     titleAssigned = true;
    }
    //If line number is the second, or line number - 2 is a multiple
    //of 4, ex. 6 - 2 = 4, which is a multiple of 4
    if (lineNumber == 2 || (lineNumber - 2) % 4 == 0)
    {
     url = line;
     urlAssigned = true;
    }
    //If the line number is the third, or if line number - 3 is a
    //multiple of 4, ex. 7 - 3 = 4
    if (lineNumber == 3 || (lineNumber - 3) % 4 == 0)
    {
     //If the line is the correct length for Unix time
     if (line.Length == 10)
     {
      //then convert the number to a local datetime
      visited = FromUnixTime(Int64.Parse(line)).ToLocalTime();
     }
     else
      MessageBox.Show("An error occured while parsing the date \n" + line);
     visitedAssigned = true;
     frequencyAssigned = true;
    }
    //If all of the values have been assigned
    if (urlAssigned == true && titleAssigned == true 
&& frequencyAssigned == true && visitedAssigned == true)
    {
     //create a new URL with the values
     u = new URL(url, title, "Opera", visited, frequency);
     //And add the URL to the URLs array
     URLs.Add(u);
     //Reset the assigned values
     urlAssigned = false;
     titleAssigned = false;
     frequencyAssigned = false;
     visitedAssigned = false;

    }

    if (lineNumber == 4000 || file.EndOfStream == true)
    {
     MessageBox.Show("done " + URLs.Count.ToString());
    }
    
    lineNumber++;
   }

  }
  return URLs;
 }

 private static string GetFolder()
 {
  string folder = "\\Opera\\Opera\\";
  string documentsFolder = Environment.GetFolderPath
      (Environment.SpecialFolder.ApplicationData);
  documentsFolder += folder;
  return documentsFolder;
 }
 public DateTime FromUnixTime(long unixTime)
 {
  var epoch = new DateTime(1970, 1, 1, 0, 0, 0);
  return epoch.AddSeconds(unixTime);
 }
Note: To use this, you will need to include:
using System.Diagnostics;
using System.IO;

This script also reuses the URL class from my post on IE history. I have commented on most parts of this, so it should be easy to understand. This is the underlying method on how to get Opera's history with C#.

If you have any more questions or comments, please let me know!

Friday, June 29, 2012

How to access Internet Explorer History in C#

So, you want to know how to access history for various browsers in C#? I found it very difficult to get it working correctly, so here is my top choices for Chrome, Firefox, and IE history code. Internet Explorer First off, here is IE. IE is, I think, the easiest history to be obtained. Browser history for IE is stored in the registry key of HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\TypedURLs. Now, Microsoft has published an interface on IUrlHistory, however that was not a C# wrapper. So, an article on CodeProject has a UrlHistoryLibrary.dll file which allows access to read and modify IE history.  The article shows how to to use the whole interface, however here is some prewritten code for returning IE history:
public class IE
    {
        public IEnumerable<URL> GetHistory()
        {

            UrlHistoryWrapperClass urlHistory;
            UrlHistoryWrapperClass.STATURLEnumerator enumerator;
            List<STATURL> list = new List<STATURL>();

            urlHistory = new UrlHistoryWrapperClass();
            enumerator = urlHistory.GetEnumerator();
            enumerator.GetUrlHistory(list);

            List<URL> URLs = new List<URL>();

            foreach (STATURL url in list)
            {
                string browser = "-- Internet Explorer";

                bool containsBoth = url.URL.Contains("file:///");

                if (url.Title != "" && containsBoth == false){
                    Console.WriteLine(String.Format("{0} {1} {2}", url.Title, url.URL, browser));
                    Thread.Sleep(500);
                    }

            }
            return URLs;
        }
    }
Here is the URL class:
public class URL
{
string url;
string title;
string browser;
public URL(string url, string title, string browser)
{
this.url = url;
this.title = title;
this.browser = browser;
}
}
 Here is how you use this code:
  1. Go to the Codeproject page, and download the demo project. You may have to sign up for a free account. Now, open up the "UrlHistoryLibrary" project in Visual Studio and then build it. You should now have a "UrlHistoryLibrary.dll" file in /bin/debug.
  2. Now, create a new console project in Visual Studio. I use the 2010 Pro version.
  3. Right click the "References" folder, in the Solution Explorer, and choose the option to "Add Reference". Now, select the "Browse" folder and navigate into your "UrlHistoryLibrary/Bin/Debug" folder and select "UrlHistoryLibrary.dll". 
  4. Now, in your references, add 
    using UrlHistoryLibrary;
    using System.Diagnostics;
    using System.Threading;
  5. Now, add the above IE class to your code. Right under that, outside of the IE class, add the URL class.  
  6. Add a main class, or public static void Main(string[] args). Inside of that, include the following:
    Process[] process_IE = Process.GetProcessesByName("iexplore");
    
    if (process_IE.Length == 0)
                {
                    IE ie = new IE();
    
                    ie.GetHistory();
                }
                else
                    Console.WriteLine("Sorry, IE is open. Please close IE and try again.");
  7. Now, when you run your console program, you should get a list of History visited, in the format of Title, Url, Broswer.
A few notes:
  • I have modified this a bit from the original code. I have made it so that the results will not display results with "file:///" in the url. It will also not display any empty titles.
  • In the main function, I have added a check that will tell you if you have IE open, when you try to run. If so, it will give you an error message.
  • I have added a 5 second delay between each URL.
Here is the complete tested source code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Threading;
using UrlHistoryLibrary;


namespace BlogTestIE
{
    class Program
    {
        static void Main(string[] args)
        {
            Process[] process_IE = Process.GetProcessesByName("iexplore");

            if (process_IE.Length == 0)
            {
                IE ie = new IE();

                ie.GetHistory();
            }
            else
                Console.WriteLine("Sorry, IE is open. Please close IE and try again.");

        }
    }

    public class IE
    {
        public IEnumerable GetHistory()
        {

            UrlHistoryWrapperClass urlHistory;
            UrlHistoryWrapperClass.STATURLEnumerator enumerator;
            List list = new List();

            urlHistory = new UrlHistoryWrapperClass();
            enumerator = urlHistory.GetEnumerator();
            enumerator.GetUrlHistory(list);

            List URLs = new List();

            foreach (STATURL url in list)
            {
                string browser = "-- Internet Explorer";

                bool containsBoth = url.URL.Contains("file:///");

                if (url.Title != "" && containsBoth == false)
                {
                    Console.WriteLine(String.Format("{0} {1} {2}", url.Title, url.URL, browser));
                    Thread.Sleep(500);
                }

            }
            return URLs;
        }
    }

    public class URL
    {
        string url;
        string title;
        string browser;
        public URL(string url, string title, string browser)
        {
            this.url = url;
            this.title = title;
            this.browser = browser;
        }
    }
}

Wednesday, June 20, 2012

Download and Convert Youtube videos to MP3 -- No Ads

I came across a very cool site, and it allows you to convert any Youtube video to Full Quality MP3 Files, that you can use with iTunes, WMP, or your MP3 Player. This site has no ads and it can even give you a button on a YouTube Video page to convert videos.

You can find this site here, and install the YouTube Firefox or Chrome extension here. Below is a video on how to get started: