Thursday, July 28, 2016

Attach single event to a control array at run time

In a scenario wherein you need to attach a single event like CheckedChanged() to a control array such as CheckBox controls, the common way to do it is using for each or for loop. Another way to achieve it is using LINQ's ForEach() method as demonstrated below.
Event Code
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
void CheckBoxGeneric_CheckedChanged(object sender, EventArgs e)
{
 var checkBox = (CheckBox)sender;
 if (checkBox.Name == "chkBurger")
 {
  //...
 }
 else if (checkBox.Name == "chkSoda")
 {
  //...
 }
 else
 {
  //...
 }
}

Attach the event to the control array
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
private CheckBox[] OrderItems;
OrderItems = new CheckBox[] { chkBurger, chkSoda, chkIceCream };

private void Form1_Load(object sender, EventArgs e)
{
 //solution 1 using foreach loop
 //foreach (var checkControl in OrderItems)
 //{
 //    checkControl.CheckedChanged += new EventHandler(CheckBoxGeneric_CheckedChanged);
 //}

 //solution 2 using LINQ 
 OrderItems.ToList().ForEach(checkVal => checkVal.CheckedChanged 
   += new EventHandler(CheckBoxGeneric_CheckedChanged));
}

Sunday, July 10, 2016

Using Microsoft.mshtml with the WebBrowser control

When working with a WebBrowser to extract information from a webpage, the most common classes that are probably used to traverse or navigate it's DOM are from the System.Windows.Forms namespace such as HtmlDocument, HtmlElementCollection and etc.
Another way to navigate and traverse the DOM of the WebBrowser's HTMLDocument is using the Microsoft.mshtml namespace which contains interfaces for the rendering engine of Internet Explorer. So to access those interfaces and in your application, add reference to Microsoft.mshtml.

In the code sample below, set alias for the Microsoft.mshtml namespace. You need to explicitly specify the namespace of a class or interface as MSHTML since Windows.Forms also have same class names with the former. And one thing to remember is that, empty results in mshtml does not yield nulls. Instead, it produces DBNull value.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
using MSHTML = mshtml; //set namespace alias for form-level use
....
....
List<string> myVidsData = new List<string>();
MSHTML.IHTMLElementCollection anchorElements = 
        ((MSHTML.HTMLDocument)WebBrowser1.Document.DomDocument).getElementsByTagName("a");
 
if (anchorElements != null && anchorElements.length > 0)
{
    foreach (MSHTML.HTMLAnchorElement element in anchorElements)
    {
        var attribute = element.getAttribute("data-vids");
 
        //empty attributes return DBNull
        if(!System.DBNull.Value.Equals(attribute))
        {
            myVidsData.Add(element.getAttribute("data-vids"));
        }
    }
}

Saturday, July 9, 2016

IsDBNull() Equivalent in C#

When working with DBNull values in VB.NET you can check if that object is of type DBNull using IsDBNull(object). So, to do this in C#, I have two options to do this. The first one is to get the type of that object and compare it with typeof(System.DBNull).
Code
1
2
3
4
5
var attribute = element.getAttribute("data-mixvids");
if(attribute.GetType() != typeof(System.DBNull)) 
{
      lstElementVids.Add(element.getAttribute("data-mixvids"));
}

The other one is presented in MSDN docs using DBNull.Value.Equals(object) which returns true.
Code
1
2
3
4
5
var attribute = element.getAttribute("data-mixvids");
if(!System.DBNull.Value.Equals(attribute))
{
     lstElementVids.Add(element.getAttribute("data-mixvids"));
}

Reference: MSDN Convert.IsDBNull Method (Object)

Wednesday, July 6, 2016

WebBrowser how to fire click event of input submit element

Given in a webpage there are several input elements and you want to fire the click event of an input element of type submit, here's how to do it using the Webbrowser control.
C#
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
HtmlElementCollection htmlElementCollection = new HtmlElementCollection();
if (WebBrowser1.Document != null) 
{
    htmlElementCollection = WebBrowser1.Document.GetElementsByTagName("input");
    if (htmlElementCollection != null && htmlElementCollection.Count > 0)
    {
        foreach (HtmlElement element in htmlElementCollection) 
        {
            if (element.GetAttribute("value").Equals("Submit")) 
            {
                element.InvokeMember("click");
            }
        }
    }
}

VB.NET
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
Dim htmlElementCollection As HtmlElementCollection
If (WebBrowser1.Document IsNot Nothing) Then
    With WebBrowser1.Document
        htmlElementCollection = .GetElementsByTagName("input")
        If (Not htmlElementCollection Is Nothing And htmlElementCollection.Count > 0) Then
            For Each element As HtmlElement In htmlElementCollection
                If (element.GetAttribute("value").Equals("Submit")) Then
                    element.InvokeMember("click")
                End If
            Next
        End If
    End With
End If

Tuesday, July 5, 2016

Regex extract url from string using Regex.Matches()

Here's how to extract url(s) from a string or document using Regex.Matches() method. The Regex.Matches() method returns an array object MatchCollection in which you can access individual elements using it's index.
Code:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
string pattern = "(http|ftp|https):\\/\\/[\\w\\-_]+(\\.[\\w\\-_]+)+([\\w\\-\\.,@?^=%&amp;:/~\\+#]*[\\w\\-\\@?^=%&amp;/~\\+#])?";
string Input = "<<abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ\"abcd\" href=\"https://mediatemple.net\"" + 
               "Sample text for testing>http://regexr.com/foo.html?q=bar>";
 
string url1 = string.Empty;
string url2 = string.Empty;
if (Regex.Matches(Input, pattern).Count > 0) 
{
    MatchCollection matches = Regex.Matches(Input, pattern);
    url1 = matches[0].Value;
    url2 = matches[1].Value;
}

Monday, July 4, 2016

Remove cookies from CookieContainer class

The CookieContainer class does not contain a method that clears or removes the cookies associated with it. To remove them, you have to set each cookie's Expired property to True as shown below.
C#
1
2
3
4
var cookies = cookieContainer.GetCookies(new Uri("http://your_url_example_here"));
foreach (Cookie co in cookies) {
    co.Expired = true;
}

VB.NET
1
2
3
4
Dim cookies = cookieContainer.GetCookies(New Uri("http://your_url_example_here"))
For Each co As Cookie In cookies        
    co.Expired = True
Next

Sunday, July 3, 2016

Show all folders inside a directory sorted by creation time.

Here's a solution using LINQ that will retrieve all folders inside a specific directory in order of creation time.
C#
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
string path = @"C:\";
if (Directory.Exists(path)) {
    DirectoryInfo dir = new DirectoryInfo(path);
    DirectoryInfo[] directories = dir.GetDirectories().
                                    OrderByDescending(p => p.CreationTime).
                                    ToArray();
    if (directories.Length > 0) {
        foreach (DirectoryInfo directory in directories) {
            ListBox1.Items.Add(directory.Name);
        }
    }
}

VB.NET
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
Dim path As String = "C:\"
If Directory.Exists(path) Then
    Dim dir As New DirectoryInfo(path)
    Dim directories As DirectoryInfo() = dir.GetDirectories().
                                             OrderByDescending(Function(p) p.CreationTime).
                                             ToArray()
    If directories.Length > 0 Then
        For Each directory As DirectoryInfo In directories
            ListBox1.Items.Add(directory.Name)
        Next
    End If
End If