Showing posts with label C#. Show all posts
Showing posts with label C#. Show all posts

December 31, 2012

C# - SQL Helper Class

Below I have mentioned my SQL Helper class that is used to communicate SQL in better way.

using System;
using System.Data;
using System.Data.SqlClient;
 
namespace Utility
{
    public static class SqlHelper
    {
        #region "FILL DATA TABLE"
 
        public static void Fill(DataTable dataTable, String procedureName)
        {
            SqlConnection oConnection = new SqlConnection(AccessConfig.GetConnectionString());
            SqlCommand oCommand = new SqlCommand(procedureName, oConnection);
            oCommand.CommandType = CommandType.StoredProcedure;
 
            SqlDataAdapter oAdapter = new SqlDataAdapter();
 
            oAdapter.SelectCommand = oCommand;
            oConnection.Open();
            using (SqlTransaction oTransaction = oConnection.BeginTransaction())
            {
                try
                {
                    oAdapter.SelectCommand.Transaction = oTransaction;
                    oAdapter.Fill(dataTable);
                    oTransaction.Commit();
                }
                catch
                {
                    oTransaction.Rollback();
                    throw;
                }
                finally
                {
                    if (oConnection.State == ConnectionState.Open)
                        oConnection.Close();
                    oConnection.Dispose();
                    oAdapter.Dispose();
                }
            }
        }
 
        public static void Fill(DataTable dataTable, String procedureName, SqlParameter[] parameters)
        {
            SqlConnection oConnection = new SqlConnection(AccessConfig.GetConnectionString());
            SqlCommand oCommand = new SqlCommand(procedureName, oConnection);
            oCommand.CommandType = CommandType.StoredProcedure;
 
            if (parameters != null)
                oCommand.Parameters.AddRange(parameters);
 
            SqlDataAdapter oAdapter = new SqlDataAdapter();
 
            oAdapter.SelectCommand = oCommand;
            oConnection.Open();
            using (SqlTransaction oTransaction = oConnection.BeginTransaction())
            {
                try
                {
                    oAdapter.SelectCommand.Transaction = oTransaction;
                    oAdapter.Fill(dataTable);
                    oTransaction.Commit();
                }
                catch
                {
                    oTransaction.Rollback();
                    throw;
                }
                finally
                {
                    if (oConnection.State == ConnectionState.Open)
                        oConnection.Close();
                    oConnection.Dispose();
                    oAdapter.Dispose();
                }
            }
        }
 
        #endregion
 
        #region "FILL DATASET"
 
        public static void Fill(DataSet dataSet, String procedureName)
        {
            SqlConnection oConnection = new SqlConnection(AccessConfig.GetConnectionString());
            SqlCommand oCommand = new SqlCommand(procedureName, oConnection);
            oCommand.CommandType = CommandType.StoredProcedure;
 
            SqlDataAdapter oAdapter = new SqlDataAdapter();
 
            oAdapter.SelectCommand = oCommand;
            oConnection.Open();
            using (SqlTransaction oTransaction = oConnection.BeginTransaction())
            {
                try
                {
                    oAdapter.SelectCommand.Transaction = oTransaction;
                    oAdapter.Fill(dataSet);
                    oTransaction.Commit();
                }
                catch
                {
                    oTransaction.Rollback();
                    throw;
                }
                finally
                {
                    if (oConnection.State == ConnectionState.Open)
                        oConnection.Close();
                    oConnection.Dispose();
                    oAdapter.Dispose();
                }
            }
        }
 
        public static void Fill(DataSet dataSet, String procedureName, SqlParameter[] parameters)
        {
            SqlConnection oConnection = new SqlConnection(AccessConfig.GetConnectionString());
            SqlCommand oCommand = new SqlCommand(procedureName, oConnection);
            oCommand.CommandType = CommandType.StoredProcedure;
 
            if (parameters != null)
                oCommand.Parameters.AddRange(parameters);
 
            SqlDataAdapter oAdapter = new SqlDataAdapter();
 
            oAdapter.SelectCommand = oCommand;
            oConnection.Open();
            using (SqlTransaction oTransaction = oConnection.BeginTransaction())
            {
                try
                {
                    oAdapter.SelectCommand.Transaction = oTransaction;
                    oAdapter.Fill(dataSet);
                    oTransaction.Commit();
                }
                catch
                {
                    oTransaction.Rollback();
                    throw;
                }
                finally
                {
                    if (oConnection.State == ConnectionState.Open)
                        oConnection.Close();
                    oConnection.Dispose();
                    oAdapter.Dispose();
                }
            }
        }
 
        #endregion
 
        #region "EXECUTE SCALAR"
 
        public static object ExecuteScalar(String procedureName)
        {
            SqlConnection oConnection = new SqlConnection(AccessConfig.GetConnectionString());
            SqlCommand oCommand = new SqlCommand(procedureName, oConnection);
 
            oCommand.CommandType = CommandType.StoredProcedure;
            object oReturnValue;
            oConnection.Open();
            using (SqlTransaction oTransaction = oConnection.BeginTransaction())
            {
                try
                {
                    oCommand.Transaction = oTransaction;
                    oReturnValue = oCommand.ExecuteScalar();
                    oTransaction.Commit();
                }
                catch
                {
                    oTransaction.Rollback();
                    throw;
                }
                finally
                {
                    if (oConnection.State == ConnectionState.Open)
                        oConnection.Close();
                    oConnection.Dispose();
                    oCommand.Dispose();
                }
            }
            return oReturnValue;
        }
 
        public static object ExecuteScalar(String procedureName, SqlParameter[] parameters)
        {
            SqlConnection oConnection = new SqlConnection(AccessConfig.GetConnectionString());
            SqlCommand oCommand = new SqlCommand(procedureName, oConnection);
 
            oCommand.CommandType = CommandType.StoredProcedure;
            object oReturnValue;
            oConnection.Open();
            using (SqlTransaction oTransaction = oConnection.BeginTransaction())
            {
                try
                {
                    if (parameters != null)
                        oCommand.Parameters.AddRange(parameters);
 
                    oCommand.Transaction = oTransaction;
                    oReturnValue = oCommand.ExecuteScalar();
                    oTransaction.Commit();
                }
                catch
                {
                    oTransaction.Rollback();
                    throw;
                }
                finally
                {
                    if (oConnection.State == ConnectionState.Open)
                        oConnection.Close();
                    oConnection.Dispose();
                    oCommand.Dispose();
                }
            }
            return oReturnValue;
        }
 
        #endregion
 
        #region "EXECUTE NON QUERY"
 
        public static int ExecuteNonQuery(string procedureName)
        {
            SqlConnection oConnection = new SqlConnection(AccessConfig.GetConnectionString());
            SqlCommand oCommand = new SqlCommand(procedureName, oConnection);
 
            oCommand.CommandType = CommandType.StoredProcedure;
            int iReturnValue;
            oConnection.Open();
            using (SqlTransaction oTransaction = oConnection.BeginTransaction())
            {
                try
                {
                    oCommand.Transaction = oTransaction;
                    iReturnValue = oCommand.ExecuteNonQuery();
                    oTransaction.Commit();
                }
                catch
                {
                    oTransaction.Rollback();
                    throw;
                }
                finally
                {
                    if (oConnection.State == ConnectionState.Open)
                        oConnection.Close();
                    oConnection.Dispose();
                    oCommand.Dispose();
                }
            }
            return iReturnValue;
        }
 
        public static int ExecuteNonQuery(string procedureName, SqlParameter[] parameters)
        {
            SqlConnection oConnection = new SqlConnection(AccessConfig.GetConnectionString());
            SqlCommand oCommand = new SqlCommand(procedureName, oConnection);
 
            oCommand.CommandType = CommandType.StoredProcedure;
            int iReturnValue;
            oConnection.Open();
            using (SqlTransaction oTransaction = oConnection.BeginTransaction())
            {
                try
                {
                    if (parameters != null)
                        oCommand.Parameters.AddRange(parameters);
 
                    oCommand.Transaction = oTransaction;
                    iReturnValue = oCommand.ExecuteNonQuery();
                    oTransaction.Commit();
                }
                catch
                {
                    oTransaction.Rollback();
                    throw;
                }
                finally
                {
                    if (oConnection.State == ConnectionState.Open)
                        oConnection.Close();
                    oConnection.Dispose();
                    oCommand.Dispose();
                }
            }
            return iReturnValue;
        }
 
        #endregion
 
    }
}


How to Use:

public static int YourFunction1(int param1, int param2)
{
    SqlParameter[] objParameter = new SqlParameter[2];
    objParameter[0] = new SqlParameter("@param1", param1);
    objParameter[1] = new SqlParameter("@param2", param2);
    return Convert.ToInt32(Data.ExecuteScalar("YourProcedureName", objParameter));
}
 
public static int YourFunction2()
{
    return Data.ExecuteNonQuery("YourProcedureName");
}
 
public static void YourFunction3(int param1, int param2, int param3, ref DataTable dt)
{
    SqlParameter[] objParameter = new SqlParameter[3];
    objParameter[0] = new SqlParameter("@param1", param1);
    objParameter[1] = new SqlParameter("@param2", param2);
    objParameter[2] = new SqlParameter("@param3", param3);
    dt.Fill("YourProcedureName", objParameter);
}
 

Feedback are accepted.

November 28, 2012

C# - Accessing Remote File By Using Impersonation

Sometime we may face “Could not create the file” or “Access denied on 'Some file Name' ” or "Unable to copy file. Access to the path is denied"  error while try to access or modify a file on a remote machine. After reviewing the code you find out, that because the current user does not have access on a remote machine.

Now we want to force your application to do some restricted activity by a user that who not having privileges to do. we call this procedure Impersonation.

In General Impersonation is, A person act like another.

Unprivileged user can access remote machine like privileged one by using privileged users credentials.

We can achieve Impersonation in may ways, I`m taking "WNetCancelConnection2" function from  GAC dll ("mpr.dll").

Note:
mpr.dll is a module containing functions used to handle communication between the Windows operating system and the installed network providers.

Download Here or copy and use below Remote Access Helper class

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.ComponentModel;
using System.Net;
 
namespace SomeNamespace.Utility
{
    public class RemoteAccessHelper
    {
        public class NetworkConnection : IDisposable
        {
            string _networkName;
 
            public NetworkConnection(string networkName, NetworkCredential credentials)
            {
                _networkName = networkName;
 
                var netResource = new NetResource()
                {
                    Scope = ResourceScope.GlobalNetwork,
                    ResourceType = ResourceType.Disk,
                    DisplayType = ResourceDisplaytype.Share,
                    RemoteName = networkName
                };
 
                var result = WNetAddConnection2(
                    netResource,
                    credentials.Password,
                    credentials.UserName,
                    0);
 
                if (result != 0)
                {
                    throw new Win32Exception(result, "Error connecting to remote share");
                }
            }
 
            ~NetworkConnection()
            {
                Dispose(false);
            }
 
            public void Dispose()
            {
                Dispose(true);
                GC.SuppressFinalize(this);
            }
 
            protected virtual void Dispose(bool disposing)
            {
                WNetCancelConnection2(_networkName, 0, true);
            }
 
            [DllImport("mpr.dll")]
            private static extern int WNetAddConnection2(NetResource netResource,
                string password, string username, int flags);
 
            [DllImport("mpr.dll")]
            private static extern int WNetCancelConnection2(string name, int flags,
                bool force);
        }
 
        [StructLayout(LayoutKind.Sequential)]
        public class NetResource
        {
            public ResourceScope Scope;
            public ResourceType ResourceType;
            public ResourceDisplaytype DisplayType;
            public int Usage;
            public string LocalName;
            public string RemoteName;
            public string Comment;
            public string Provider;
        }
 
        public enum ResourceScope : int
        {
            Connected = 1,
            GlobalNetwork,
            Remembered,
            Recent,
            Context
        };
 
        public enum ResourceType : int
        {
            Any = 0,
            Disk = 1,
            Print = 2,
            Reserved = 8,
        }
 
        public enum ResourceDisplaytype : int
        {
            Generic = 0x0,
            Domain = 0x01,
            Server = 0x02,
            Share = 0x03,
            File = 0x04,
            Group = 0x05,
            Network = 0x06,
            Root = 0x07,
            Shareadmin = 0x08,
            Directory = 0x09,
            Tree = 0x0a,
            Ndscontainer = 0x0b
        }
    }
}


Below i`m describing some piece of code to show, how to use RemoteAccessHelper.cs ?

var oNetworkCredential = 
    new System.Net.NetworkCredential()
    {
        Domain = "domainName",
        UserName = "domainName" + "\\" + "admin login name",
        Password = "admin password"
    };
            
using (new RemoteAccessHelper.NetworkConnection(@"\\" + "domainName", oNetworkCredential))
{
    String[] sFolderNames = Directory.GetDirectories( "domainName" + "\\FolderName");
    foreach (String sFolderName in sFolderNames)
    {
        string[] sarrZipFiles = Directory.GetFiles(sFolderName, "*.txt");
        foreach (String sFile in sarrZipFiles)
        {
            // Some unprivileged operations
        }
    }
}
Source: Stackoverflow

October 22, 2012

C# - Check File is being used by another process, if not delete files


Some times while try to deleting a file we may got a error message like
"It is being used by another person or program."

This means we can't delete a file, if it is being used.

I provide a solution to handle this kind of exception.


 
        /// <summary>
        /// This function is used to check specified file being used or not
        /// </summary>
        /// <param name="file">FileInfo of required file</param>
        /// <returns>If that specified file is being processed 
        /// or not found is return true</returns>
        public static Boolean IsFileLocked(FileInfo file)
        {
            FileStream stream = null;
 
            try
            {
                //Don't change FileAccess to ReadWrite, 
                //because if a file is in readOnly, it fails.
                stream = file.Open
                (
                    FileMode.Open, 
                    FileAccess.Read, 
                    FileShare.None
                );
            }
            catch (IOException)
            {
                //the file is unavailable because it is:
                //still being written to
                //or being processed by another thread
                //or does not exist (has already been processed)
                return true;
            }
            finally
            {
                if (stream != null)
                    stream.Close();
            }
 
            //file is not locked
            return false;
        }


     /// This function is used to delete all files inside a folder 
     public static void CleanFiles()
     {
            if (Directory.Exists("FOLDER_PATH"))
            {
                var directory = new DirectoryInfo("FOLDER_PATH");
               foreach (FileInfo file in directory.GetFiles())
               { 
                  if(!IsFileLocked(file)) file.Delete(); 
               }
            }
     }

Source: Internet

September 22, 2012

C# - Avoid SQL Injection By Validating Strings


What is SQL Injection:
SQL injection is an attack in which malicious code is inserted into strings that are later passed to an instance of SQL Server for parsing and execution.
By MSDN

For Eg:
Assume the below dynamic query going to execute
String sql = "select * from Products where ProductID = '" + @ProductID + "'";

However, assume a user enters @ProductID as P213445'; drop table Products--

After assembled the above query will be
select * from Products where ProductID = 'P213445'; drop table Products--

This one syntactically correct, if this executes means we lost a table, Right..!!
So We should keep in mind SQL Injection while developing.
We can avoid SQL Injection by several methods, I given one of it.

Use the below one validate user input

//** Doubles up single quotes to stop breakouts from SQL strings **
public static string SQLSafe(string strRawText)
{
    string strCleanedText = "";
    int iCharPos = 0;
 
    while (iCharPos < strRawText.Length)
    {
        //** Double up single quotes, but only if they aren't already doubled **
        if (strRawText.Substring(iCharPos, 1) == "'")
        {
            strCleanedText = strCleanedText + "''";
            if (iCharPos != strRawText.Length)
            {
                if (strRawText.Substring(iCharPos + 1, 1) == "'")
                    iCharPos = iCharPos + 1;
            }
        }
        else
        {
            strCleanedText = strCleanedText + strRawText.Substring(iCharPos, 1);
        }
 
        iCharPos++;
    }
 
    return strCleanedText.Trim();
}

August 24, 2012

C#/LINQ - Split Number From Strings

Code to Split Number From Strings

/// <summary>
/// This Function used to spilt No from word
/// </summary>
/// <param name="strInput">Given String</param>
/// <returns>Expected No, If not found then returns -1</returns>
public Int64 SpiltNumberFromString(String strInput)
{
    string[] digits = Regex.Split(strInput, @"\D+", RegexOptions.Compiled);
    string numbers = string.Empty;
    foreach (string value in digits)
    {
        int number;
        if (int.TryParse(value, out number))
            numbers = numbers + number.ToString(CultureInfo.InvariantCulture);
    }
    return numbers.Length == 0 ? -1 : int.Parse(numbers);
}


LINQ Approach

/// <summary>
/// This Function used to spilt No from word
/// </summary>
/// <param name="strInput">Given String</param>
/// <returns>Expected No, If not found then returns -1</returns>
public Int64 SpiltNumberFromString(String strInput)
{
    int number = -1;
    string numberString = Regex.Split(strInput, @"\D+", RegexOptions.Compiled)
                            .Where(value => int.TryParse(value, out number))
                            .Aggregate(string.Empty, (current, value) => current + number.ToString(CultureInfo.InvariantCulture));
    return Int64.Parse(numberString);
}

C# – Convert Numbers into Words

Convert Money Numbers into Strings

public static string NumberToWords(int number)
{
    if (number == 0)
        return "ZERO";
 
    if (number < 0)
        return "MINUS " + NumberToWords(Math.Abs(number));
 
    string words = "";
 
    if ((number / 1000000) > 0)
    {
        words += NumberToWords(number / 1000000) + " MILLION ";
        number %= 1000000;
    }
 
    if ((number / 1000) > 0)
    {
        words += NumberToWords(number / 1000) + " THOUSAND ";
        number %= 1000;
    }
 
    if ((number / 100) > 0)
    {
        words += NumberToWords(number / 100) + " HUNDRED ";
        number %= 100;
    }
 
    if (number > 0)
    {
        if (words != "")
            words += "AND ";
 
        var unitsMap = new[] { "ZERO", "ONE", "TWO", "THREE", "FOUR", "FIVE", "SIX", "SEVEN", "EIGHT", "NINE", "TEN", "ELEVEN", "TWELVE", "THIRTEEN", "FOURTEEN", "FIFTEEN", "SIXTEEN", "SEVENTEEN", "EIGHTEEN", "NINETEEN" };
        var tensMap = new[] { "ZERO", "TEN", "TWENTY", "THIRTY", "FORTY", "FIFTY", "SIXTY", "SEVENTY", "EIGHTY", "NINETY" };
 
        if (number < 20)
            words += unitsMap[number];
        else
        {
            words += tensMap[number / 10];
            if ((number % 10) > 0)
                words += "-" + unitsMap[number % 10];
        }
    }
 
    return words;
}

June 7, 2012

StringBuilder - Overview, Tips & Tricks

StringBuilder

MSDN describes StringBuilder is a Mutable (Changeable) string of characters.
Syntax:
   1:  [SerializableAttribute]
   2:  [ComVisibleAttribute(true)]
   3:  public sealed class StringBuilder : ISerializable

The term "Sealed" describes in above syntax, cannot be inherited.

What is the use of string builder ?

StringBuilder is a Mutable object for concatenating strings without need of new reference (New memory) for every concatenation.

Now your brain may arise a question, the same (Concatenation) can be achieved from system.String class then what is the use of StringBuilder.

Why StringBuilder when there is String ?

1. Strings are immutable (Unchangeable) so StringBuilder is best for concatenating unknown no of iterations.
ie. If you try to change it with the Concatenation or with the Replace, PadLeft, PadRight or substring etc, it finally ended with entirely new string. The existing memory remains same until garbage collected. Allocations of new memory costly in terms of both memory and performance.
2. StringBuilder can modify string without having to allocate new memory. It is made to do complex and large concatenation. But keep large-object-heap in mind.

Now you may ask

Why String ? Can't we use StringBuilder everywhere ?

We must really think about the overhead of initialization. StringBuilder doubles its capacity, meaning it reallocates its buffers so it can store twice as many characters each time.
Don't use in smaller concatenations.

Where we use StringBuilder ?

1. When you don't have a loop, generally you should avoid StringBuilder.
2. Don't use StringBuilder in zippy concatenation.
eg:
   1:  string str = string1(...) + string2(...)  + string3(...)  + string4(...)
StringBuilder won't help. Because this is single concatenation, ordinary string contate better than string builder
but the pattern like this, surely you need string builder
   1:  foreach(...)
   2:  {
   3:      if(..) str  += string1(...)
   4:      if(..) str  += string2(...)
   5:      if(..) str  += string3(...)
   6:      if(..) str  += string4(...)
   7:  }


StringBuilder Tips:

1. Don't Use + (plus) inside StringBuilderAppend()
2. For lesser concatenation string builder slow down. because of allocation of the StringBuilder object.
3. String Builder uses internal memory to concatenate string, if your concatenation increses string builder performance increases and vice versa.
4. StringBuilder has no advance knowledge of the required result buffer size and has to reallocate each time the buffer size is exceeded.

C# - Large Object Heap

Large Object Heap

Objects larger than some 85,000 bytes get allocated on a separate heap, called the large object heap. This heap has one special characteristic: it never gets compacted, because that would be too costly, moving those large objects would take too long. Without compaction, there are many situations, both theoretical and practical, that may and eventually will lead to an out-of-memory situation due to fragmentation.
StringBuilder in C# 4.0 this issue is fixed by using linked list.

String - Intern Pool

Intern Pool

The common language runtime conserves string storage by maintaining a table, called the Intern pool, that contains a single reference to each unique literal.
Eg:
   1:  using System;
   2:   
   3:  namespace ProveStringIsImmutable
   4:  {
   5:      class Program
   6:      {
   7:          static void Main(string[] args)
   8:          {
   9:              string foo = "I`m a good boy";
  10:              string bar = "I`m a good boy";
  11:              Console.WriteLine(Object.ReferenceEquals(foo, bar));
  12:              foo = foo + " with some stuff";
  13:              Console.WriteLine(Object.ReferenceEquals(foo, bar));
  14:          }
  15:      }
  16:  }
  17:   
  18:  //Output:
  19:  //--------------------
  20:  //true
  21:  //false

Initially foo and bar have unique string literals, so foo and bar got same reference. In Brief While try to assigning bar, CLR smart enough to check the given literals already exists in intern table or not, if yes then, returns same existing memory reference of unique string literals.

Here We can also able to prove string immutability , when we try to alter foo, The resulted reference not match with old one, that means CLR assigned new memory reference for altered string.
"If we try to change or modify a string, it finally ended with entirely new string - String Immutability"

June 4, 2012

String Builder Append vs String Concate vs String Format vs StringBuilder AppendFormat vs Ordinary Concatenation

Which one is faster method.?
   1:  string str1 = string.Format("{0}{1}{2}{3}{4}","String1","String2","String3","String4","String5");
   2:  string str2 = new StringBuilder().Append("String1").Append("String2").Append("String3").Append("String4").Append("String5");
   3:  string str3 = string.Concat(new string [] { "String1", "String2", "String3", "String4", "String5"});
   4:  string str4 = "String1" + "String2" + "String3" + "String4" + "String5";

You may think string builder or string concate but result is over 1 lakh iterations traditional "+" Operator faster in terms of memory and time.

Why traditional "+" Operator faster:
Reason behind traditional "+" Operator faster is it used String.Concat with length.
compiler convert this piece of code:
   1:  string str = "String1" + "String2" + "String3" + "String4" + "String5";
to this
   1:  string str = String.Concat(new Object[] { "String1", "String2", "String3", "String4", "String5"});

To do traditional zippy concatenation like above, don't confuse yourself, just use traditional "+" concatenation that's enough, c# does jobs for you..

January 10, 2012

Remove Wild Characters & HTML from a string

While try to parse email or try to get string from Rich Text Editor (RTE) we may found some Junk Data (HTML, Wild Characters & etc.) inside that string.

In that time we need a eliminator like below.
   1:  public string RemoveHTMLandWildChar(string input)
   2:  {
   3:      //Remove HTML
   4:      input = Regex.Replace(input, @"&lt;(.|\n)*?&gt;", string.Empty);
   5:   
   6:      //Remove Wild characters 
   7:      input = Regex.Replace(input, @"\[\w+]", string.Empty);
   8:      return input;
   9:  }

Description: This is what \[\w+] means:
  • \[ - Regualar Expressions don't have to start with a backslash (\). The reason why we started with a \ in this case, is that the opening square bracket has a special meaning to the RegEx parser and thus you have to escape it using the backslash. \[ means that "start with an opening backslash"
  • \w - This means a word character which is an alphanumeric character or the underscore character.
  • + - The plus sign means "find one or more". Thus \w+ means find one or more alphanmeric characters. The * character, by the way, means "find zero ore more".
  • ] - The closing square bracket doesn't need to be escaped, thus we don't need a \ before it.
Thus, the whole expression,
 \[\w+], - "match one or more alphanumeric characters that are surrounded by squre brackets".
If you want this to say "match zero or more..." then you have to change your regular expression to \[\w*].