# Thursday, June 11, 2009

Installation Error if Diagnostics Log location moved...

I was installing a new Sharepoint Server in the farm, mostly because the currently had was too small.

I ran into errors with the Office Server Web Services (it kept saying it could not find the path, although the path to that website was fine (I checked it three times). The Root virtual directory could not be found...

I tried many things. Finally I ran the Office wizard to remove the new server from the farm. I then ran it again to reinstall it (after making sure that various dbs had the Sharepoint Server as a user - see previous log). And I got the error below:

The error in the log informed me that I it was missing the location of the Diagnostics Logs that I had moved to the E: drive on the old, slow server. So I moved the Diagnostics logs to the D: drive before running the wizard to try to join the farm again. No dice. Same error. I moved the logs back to there original locale in the 12-spot. No dice.
 
I try renaming the D: drive to E: - it refuses.
 
On the point of uninstalling/reinstalling MOSS on the new server I hesitate...
 
Searching through Regedit in the NEW server (not currently on the Farm) I find an entry in HKLM\Software\Microsoft\Shared Tools\Web Server Extensions\12.0\WSS called LogDir. And guess what is in it? You got it - a reference to the entry on the E: drive...
 
Manually changed the regedit entry to match to the new d: location (on both servers) and VOILA!!!
 
So be warned - if you move the Diagnostics Logs location in a farm, a folder must be available on ALL servers (makes sense).
 
And the Office Server IIS site is gone. Probably a carryover from before...

# Monday, June 08, 2009

Microsoft.Exchange.Data.Storage.StoragePermanentException - There was a problem accessing Active Directory

Recently we added some new hires to the system only to discover that when one of them tried to use OWA that an error was triggered - notably that there was an error accessing Active Directory and that the InnerException was Microsoft.Exchange.Data.Directory.InvalidADObjectOperatorException (see below)

Now this only happened with new users. Old users, ones we migrated from x03 to x07 could use OWA with no problem. I should note (and this is critical) that we still had our old x03 up, even though we had migrated all the old user mailboxes. This was because of our unified messaging needing to still run (for a wee bit) on a legacy system. A quick check on the hub server looking at the mailboxes verified my fears - the mailboxes had been created as 'Legacy' mailboxes.

How could this have happened? I checked with my cohort and he confirmed that when we created the boxes in AD he specified a storage group that was on the x07 server. A quick check verified this. Obviously when a new mailbox is created in a mixed environment (at least in ours) it defaults to the least-common-denominator - in this case x03.

The solution was fairly straightforward - move the mailbox. But how? It already WAS on an x07 storage group. Simple - move to a different storage group - voila!

Except.... it is still a problem...

DOH!!!

I peek into AD using ADSI Edit and discover that the mxExchVersion for the problem people IS NOT SET!!! A quick search brings me here -> http://support.microsoft.com/kb/941146.

Running the Set-Mailbox User_name -ApplyMandatoryProperties is the final step and everything is beautiful. OWA functions and the sun comes out.

On to the next quirk......

 

# Thursday, June 04, 2009

DropDownList, GridView, and Dynamically selecting the appropriate ListItem during Edit...

I have seen a number of questions regarding how to specify what the selected ListItem is on a DropDownList used in an EditRow of A GridView. So I thought it might make a good blog.

Note: for an example that uses Ajax, specifically the CascadingDropDown, look here http://www.myfriedmind.com/techBlog/2009/06/22/CascadingDropDownListsGridViewsAndDynamicallySelectingTheAppropriateListItemDuringEdit.aspx.

Basically what people are trying to do is use a DropDownList as one of the input controls on a DataRow when edit is selected for that Row. This, of course, limits what people can enter which is a good thing. For example, what if you wanted to create a DropDownList that specified which state someone was from, or what time (using 15-minute increments)?

Creating the DropDownList is fairly straightforward, as is populating it. What is confusing people is how to specify what the selected value is. To do that you need to handle the OnRowDataBound event, snag the DataItem and select the ListItem that matches the appropriate property. Like so:

Sample DataObject (in c#)

class MyObject
{
   public int ObjId {get; set;}
   public string StateAbbreviation {get; set; }
}

Sample DataObject (in vb.net)

Class MyObject
    Public ObjId As Integer
    Public StateAbbreviation As String
End Class


Entry on the SampleGridview.aspx page (as simple as you can get it )

<asp:GridView runat="server" ID="lstMyData" DataKeyNames="ObjId"
    AutoGenerateColumns="false" EnableViewState="true"
    AutoGenerateEditButton="true"
    OnRowDataBound="lstMyData_RowDataBound" >
    <Columns>
        <asp:TemplateField>
            <ItemTemplate>
                <asp:Label runat="server" ID="lblState" Text='<%# Eval("StateAbbreviation") %>' />
            </ItemTemplate>
            <EditItemTemplate>
                <asp:DropDownList runat="server" ID="uxState" />
            </EditItemTemplate>
        </asp:TemplateField>
    </Columns>
</asp:GridView>

Codebehind (in c#) SampleGridview.aspx.cs

protected void lstMyData_RowDataBound(object sender,
        GridViewRowEventArgs e)
{
    // verify this is a DataRow, not a Header, Footer, etc...
    if (e.Row.RowType == DataControlRowType.DataRow)
    {
        // in case you want to do something else here....
       
        // see if this is the Row used for Editing
        if ((e.Row.RowState & DataControlRowState.Edit) != 0)
        {
            // get the DataItem that is bound
            // and cast it accordingly
            MyObject _myObject = (MyObject)e.Row.DataItem;

            // get the dropdownlist
            DropDownList _uxState =
                (DropDownList) e.Row.FindControl("uxState");

            // dynamically create the DDL for demo...
            // this could also be done statically in the aspx page
            _uxState.Items.Add(new ListItem("Hawaii", "HI"));
            _uxState.Items.Add(new ListItem("Iowa", "IA"));
            _uxState.Items.Add(new ListItem("Minnesota", "MN"));
            _uxState.Items.Add(new ListItem("Wisconsin", "WI"));

            // find the matching ListItem and Select it
            ListItem _matchingItem =
                _uxState.Items.FindByValue(_myObject.StateAbbreviation);
            if (_matchingItem == null)
            {
                // Houston we have a problem, no match...
                // handle this as you see fit
            }
            else
            {
                _matchingItem.Selected = true;
            }
        }
    }
}

Protected Sub lstMyData_RowDataBound(ByVal sender As Object, _
    ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) _
    Handles lstMyData.RowDataBound
    If e.Row.RowType = DataControlRowType.DataRow Then

            ' in case you want to do something else here....

            ' see if this is the Row used for Editing
            If (e.Row.RowState And DataControlRowState.Edit) <> 0 Then


                ' get the DataItem that is bound
                ' and cast it accordingly
                Dim _myObject As MyObject = _
                    DirectCast(e.Row.DataItem, MyObject)

                ' get the dropdownlist
                Dim _uxState As DropDownList = _
                    DirectCast(e.Row.FindControl("uxState"), DropDownList)

                ' dynamically create the DDL for demo...
                ' this could also be done statically in the aspx page
                _uxState.Items.Add(New ListItem("Hawaii", "HI"))
                _uxState.Items.Add(New ListItem("Iowa", "IA"))
                _uxState.Items.Add(New ListItem("Minnesota", "MN"))
                _uxState.Items.Add(New ListItem("Wisconsin", "WI"))

                ' find the matching ListItem and Select it
                Dim _matchingItem As ListItem = _
                    _uxState.Items.FindByValue(_myObject.StateAbbreviation)
                If _matchingItem Is Nothing Then
                    ' Houston we have a problem, no match...
                    ' handle this as you see fit
                Else
                    _matchingItem.Selected = True
                End If
            End If
     End If
End Sub

So basically what you are doing is getting a hold of both the value that you want selected (by using the e.Row.DataItem) and the DropDownList (by using e.Row.FindControl) and then simply doing a match...

Hope this helps...

# Wednesday, June 03, 2009

Error Code: 403 Forbidden. ISA Server is configured to block HTTP requests that require authentication. (12250)

When moving to a new IP address range I decided to clean up some of my ISA rules. I consolidated a number of websites into a new listener, but when I tried to access them I got:

Error Code: 403 Forbidden. ISA Server is configured to block HTTP requests that require authentication. (12250)

Now I was pretty sure I had setup the listener for No Authentication, and sure enough it was. But I have forgotten to specify that the client could allow authentication over HTTP (see image below). Once it was "allowed" everything was back to normal...

Edge Server unable to send or receive emails

Hint: it isn't ISA

We recently moved to a new set of IP addresses and a new router and while most everything was running fine our Edge Server was having trouble sending/receiving from the world at large.

Now I have the Edge in a DMZ in order to use a public address since ISA does not doing client NATing at all (curse you!) and initially I suspect there was something in my subnetting or some such that was the problem. Maybe it was the "Perimeter" network object that was the issue? Could it be something whacky with my ruleset?

However, I was able to connect from our hub server to the edge server (ie from in to out). I was able to connect back to the hub server. I could even get out from the hub server (using the default NAT address). I just could not get OUT from the edge server. No DNS lookup (using outside), no web browsing, and definitely no SMTP happening here...

I kept going over and over looking for what I had configured wrong on ISA or on the Edge server or in DNS...

So I enabled pinging on the ISA server for all Networks so I could check and sure enough, while I could ping the "External" Nic's ip addresses from the router, I could not ping the DMZ Nic, much less the Edge server on the other side of it.

There was no route manually specified for the particular IP address that the Edge server was running. DOH!!!! A wee bit o cisco magic and *voila* email flowing like there is no tomorrow.

Assumptions, assumptions, assumptions...

# Tuesday, June 02, 2009

Cannot open database requested in login 'SharedServicesDatabase'. Login fails. Login failed for user MYDOMAIN\MyServer$

You may get an error like:
 
Cannot open database requested in login 'SharedServicesDatabase'. Login fails.
Login failed for user ' MYDOMAIN\MyServer$'.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.Data.SqlClient.SqlException: Cannot open database requested in login 'SharedServicesDatabase'. Login fails.
Login failed for user ' MYDOMAIN\MyServer$'.
 
This is triggered by the odd fact (which I can not find documented anywhere) that the server that is housing the Sharepoint site must have its computer account listed as a user within the Shared Services database for the search to function.

# Monday, June 01, 2009

Note to self - watch out for ISA 2006 Listeners and Sharepoint AAM

I had setup AAM w/ Sharepoint and our ISA servers. What had not occured to me was that the Connection Verifier was tied to port 80 (I had not put it somewhere else). So when I removed that site *boom*.
 
Changed ISA Verifier to the correct port and it works fine...

# Friday, May 29, 2009

Getting errors nicely via email from your website the vb.net version

For the c# version look here -> http://www.myfriedmind.com/techBlog/2009/05/29/GettingErrorsNicelyViaEmailFromYourWebsiteTheCVersion.aspx

It is always nice to get notified that there is an error on your website in some other way than a user on the other end of the phone.

One of the nicest ways I know of in .net is to use the Application_Error portion of Global.asax to shoot me an email listing the information that is needed. I have included some basic code below but you can feel free to modify it as you choose. For example you may prefer to include the System.Net.Mail info on the SmtpServer in the web.config so you can use it on other portions of the site rather than repeat it.

In the code I use reflection to roll through both the Request object and the Exception that is passed. You can modify it if you want to display more (such as innerexceptions, etc) or to exclude, but Reflection can be nice in pulling up all the data quickly.

=================
In vb.net

In Web.Config
        <customErrors mode="On" defaultRedirect="~/ErrorOnWebsite.aspx"/>

In Global.asax (don't do this and you get an endless loop!)
    Sub Application_Error(ByVal sender As Object, ByVal e As EventArgs)
        Server.Transfer("~/ErrorOnWebsite.aspx")
    End Sub

On ErrorOnWebsite.aspx (you don't actually have to use a label, you can provide some other means of apology)
        <asp:Label runat="server" ID="lblApology"></asp:Label>

This is Error.OnWebsite.aspx.vb (I like code-behinds) - note the use of the HtmlTextWriter and Reflection!

Imports System
Imports System.IO
Imports System.Net.Mail
Imports System.Web.UI
Imports System.Web.UI.WebControls
Imports System.Reflection

Partial Class ErrorOnPage
    Inherits System.Web.UI.Page

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        Dim exc As Exception = Server.GetLastError()

        If (exc Is Nothing) Then
            ' there is no error, why are they here?
            Response.Redirect("~/")
        Else
            SendNotificationEmail(exc)
            WriteApology()
            Server.ClearError()
        End If
    End Sub

    Private Sub WriteApology()
        lblApology.Text = "Oops, sorry, the master of light and sound has been notified..."
    End Sub

    Private Sub SendNotificationEmail(ByVal exc As Exception)
        ' Create the format holder for the data, I like tables...
        Dim _infoTable As Table = New Table()
        _infoTable.Attributes.Add("border", "1")
        _infoTable.Attributes.Add("cellpadding", "3")

        Dim _infoRow As TableRow
        Dim _infoNameCell As TableCell
        Dim _infoDataCell As TableCell

        _infoRow = New TableRow()
        _infoNameCell = New TableCell()
        _infoNameCell.Text = "Server Request Properties"
        _infoNameCell.BackColor = System.Drawing.Color.Gray
        _infoNameCell.ColumnSpan = 2
        _infoRow.Cells.Add(_infoNameCell)
        _infoTable.Rows.Add(_infoRow)

        ' I like to use reflection because I hate to type...
        Dim _requestType As Type = Request.GetType()
        Dim _pInfo As PropertyInfo

        For Each _pInfo In _requestType.GetProperties()

            If (Not _pInfo.Name = "Item") Then

                _infoRow = New TableRow()

                _infoNameCell = New TableCell()
                _infoNameCell.Text = _pInfo.Name
                _infoRow.Cells.Add(_infoNameCell)

                _infoDataCell = New TableCell()
                Dim _value As Object = _pInfo.GetValue(Request, Nothing)
                If _value Is Nothing Then
                    _infoDataCell.Text = ""
                Else
                    _infoDataCell.Text = Server.HtmlEncode(_value.ToString())
                End If
                _infoRow.Cells.Add(_infoDataCell)

                _infoTable.Rows.Add(_infoRow)
            End If
        Next

        _infoRow = New TableRow()
        _infoNameCell = New TableCell()
        _infoNameCell.Text = "Exception Properties"
        _infoNameCell.BackColor = System.Drawing.Color.Gray
        _infoNameCell.ColumnSpan = 2
        _infoRow.Cells.Add(_infoNameCell)
        _infoTable.Rows.Add(_infoRow)

        Dim _exceptionType As Type = exc.GetType()
        For Each _pInfo In _exceptionType.GetProperties()        
            _infoRow = New TableRow()

            _infoNameCell = New TableCell()
            _infoNameCell.Text = _pInfo.Name
            _infoRow.Cells.Add(_infoNameCell)

            _infoDataCell = New TableCell()
            Dim _value As Object = _pInfo.GetValue(exc, Nothing)
            If (_value Is Nothing) Then
                _infoDataCell.Text = ""
            Else
                _infoDataCell.Text = Server.HtmlEncode(_value.ToString())
            End If
            _infoRow.Cells.Add(_infoDataCell)

            _infoTable.Rows.Add(_infoRow)
        Next

        ' note the use of the HtmlTextWriter to render the table
        ' into a string
        Dim _bodyWriter As StringWriter = New StringWriter()
        Dim _writeToBody As HtmlTextWriter = New HtmlTextWriter(_bodyWriter)
        _infoTable.RenderControl(_writeToBody)

        Dim _message As MailMessage = New MailMessage("error@mysite.com", "myemail@mysite.com")
        _message.Subject = String.Format("Error on website - {0}", exc.Message)
        _message.Body = _bodyWriter.ToString()
        _message.IsBodyHtml = True

        Dim _mailClient As SmtpClient = New SmtpClient("mymailserver")
        _mailClient.Send(_message)

    End Sub

End Class

Getting errors nicely via email from your website the c# version

For the vb.net version - go here -> http://www.myfriedmind.com/techBlog/2009/05/29/GettingErrorsNicelyViaEmailFromYourWebsiteTheVbnetVersion.aspx

It is always nice to get notified that there is an error on your website in some other way than a user on the other end of the phone.

One of the nicest ways I know of in .net is to use the Application_Error portion of Global.asax to shoot me an email listing the information that is needed. I have included some basic code below but you can feel free to modify it as you choose. For example you may prefer to include the System.Net.Mail info on the SmtpServer in the web.config so you can use it on other portions of the site rather than repeat it.

In the code I use reflection to roll through both the Request object and the Exception that is passed. You can modify it if you want to display more (such as innerexceptions, etc) or to exclude, but Reflection can be nice in pulling up all the data quickly.

=================
In c#

In Web.Config
        <customErrors mode="On" defaultRedirect="~/ErrorOnWebsite.aspx"/>

In Global.asax (don't do this and you get an endless loop!)
    void Application_Error(object sender, EventArgs e)
    {
        Server.Transfer("~/ErrorOnWebsite.aspx");
    }

On ErrorOnWebsite.aspx (you don't actually have to use a label, you can provide some other means of apology)
        <asp:Label runat="server" ID="lblApology"></asp:Label>

This is Error.OnWebsite.aspx.cs (I like code-behinds) - note the use of the HtmlTextWriter and Reflection!

using System;
using System.IO;
using System.Net.Mail;
using System.Reflection;
using System.Web.UI;
using System.Web.UI.WebControls;

public partial class ErrorOnWebsite : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        Exception exc = Server.GetLastError();

        if (exc != null)
        {
            SendNotificationEmail(exc);
            WriteApology();
            Server.ClearError();
        }
        else
        {
            // if there is no error, why are they here?
            Response.Redirect("~/", true);
        }
    }

    private void WriteApology()
    {
        lblApology.Text = "Oops, sorry, the master of light and sound has been notified...";
    }

    private void SendNotificationEmail(Exception exc)
    {
        // Create the format holder for the data, I like tables...
        Table _infoTable = new Table();
        _infoTable.Attributes.Add("border", "1");
        _infoTable.Attributes.Add("cellpadding", "3");

        TableRow _infoRow;
        TableCell _infoNameCell;
        TableCell _infoDataCell;

        _infoRow = new TableRow();
        _infoNameCell = new TableCell();
        _infoNameCell.Text = "Server Request Properties";
        _infoNameCell.BackColor = System.Drawing.Color.Gray;
        _infoNameCell.ColumnSpan = 2;
        _infoRow.Cells.Add(_infoNameCell);
        _infoTable.Rows.Add(_infoRow);

        // I like to use reflection because I hate to type...
        Type _requestType = Request.GetType();
        foreach (PropertyInfo _pInfo in _requestType.GetProperties())
        {
            if (_pInfo.Name != "Item")
            {
                _infoRow = new TableRow();

                _infoNameCell = new TableCell();
                _infoNameCell.Text = _pInfo.Name;
                _infoRow.Cells.Add(_infoNameCell);

                _infoDataCell = new TableCell();
                object _value = _pInfo.GetValue(Request, null);
                if (_value != null)
                {
                    _infoDataCell.Text = Server.HtmlEncode(_value.ToString());
                }
                else
                {
                    _infoDataCell.Text = "";
                }
                _infoRow.Cells.Add(_infoDataCell);

                _infoTable.Rows.Add(_infoRow);
            }
        }

        _infoRow = new TableRow();
        _infoNameCell = new TableCell();
        _infoNameCell.Text = "Exception Properties";
        _infoNameCell.BackColor = System.Drawing.Color.Gray;
        _infoNameCell.ColumnSpan = 2;
        _infoRow.Cells.Add(_infoNameCell);
        _infoTable.Rows.Add(_infoRow);

        Type _exceptionType = exc.GetType();
        foreach (PropertyInfo _pInfo in _exceptionType.GetProperties())
        {
            _infoRow = new TableRow();

            _infoNameCell = new TableCell();
            _infoNameCell.Text = _pInfo.Name;
            _infoRow.Cells.Add(_infoNameCell);

            _infoDataCell = new TableCell();
            object _value = _pInfo.GetValue(exc, null);
            if (_value != null)
            {
                _infoDataCell.Text = Server.HtmlEncode(_value.ToString());
            }
            else
            {
                _infoDataCell.Text = "";
            }
            _infoRow.Cells.Add(_infoDataCell);

            _infoTable.Rows.Add(_infoRow);
        }

        // note the use of the HtmlTextWriter to render the table
        // into a string
        StringWriter _bodyWriter = new StringWriter();
        HtmlTextWriter _writeToBody = new HtmlTextWriter(_bodyWriter);
        _infoTable.RenderControl(_writeToBody);

        MailMessage _message = new MailMessage("error@mysite.com", "myemail@mysite.com");
        _message.Subject = String.Format("Error on website - {0}", exc.Message);
        _message.Body = _bodyWriter.ToString();
        _message.IsBodyHtml = true;

        lblApology.Text = _bodyWriter.ToString();

        SmtpClient _mailClient = new SmtpClient("mymailserver");
        _mailClient.Send(_message);
    }

Howto: load a text file quickly into a DataTable

If you will be developing for a 64-bit Windows 7 box, please see this post as well -> TheMicrosoftJetOLEDB40ProviderIsNotRegisteredOnTheLocalMachineErrorOnWindows7

Someone asked about a quick way to load a text file and since the code is a bit lengthy I have included it before.

Basically one of the quickest ways (rather than opening and reading it line by line by line by line) is to use the OleDb connection to quickly push it into a Dataset. You can do this with any delimiter...

There are two procedures below - the first one UpdateSchemaIni does what it says - it updates the Schema.Ini so that the OleDbConnection knows what to parse on. This is necessary for non-csv files. The second - LoadDataFile - loads up the file and sticks it into a table of your naming and then returns a DataSet for you to play with.

Enjoy!!!

============ code below

private char m_delimiter

/// <summary>
/// Required to write the Schema.Ini in case the delimiter for the files are not simply CSV
/// </summary>
/// <param name="m_delimiter">System.Char representing the delimter to use in this file</param>
/// <param name="filename">Filename to pass, helping to locate the Schema.Ini and give the header for the section</param>
private static void UpdateSchemaIni(char m_delimiter, string filename)
{
    string _schemaFile = String.Format(@"{0}\{1}", Path.GetDirectoryName(filename), "Schema.ini");
    string _filenameHeader = String.Format("[{0}]", Path.GetFileName(filename)).ToLower();
    string _delimiterLine = String.Format("Format=Delimited({0})", m_delimiter);

    StreamReader _reader;
    StreamWriter _writer;

    string _tempFile = String.Format("{0}.{1}", _schemaFile, DateTime.Now.Ticks);
    while (File.Exists(_tempFile))
    {
        _tempFile += "0";
    }

    if (!File.Exists(_schemaFile))
    {
        using (_writer = new StreamWriter(_schemaFile))
        {
            _writer.WriteLine(_filenameHeader);
            _writer.WriteLine(_delimiterLine);
            _writer.Close();
        }
    }
    else
    {
        bool _successfullyUpdated = false;
        using (_writer = new StreamWriter(_tempFile))
        {
            using (_reader = new StreamReader(_schemaFile))
            {
                bool _entryOnNextLine = false;
                while (_reader.Peek() > 0)
                {
                    string _currentLine = _reader.ReadLine();
                    if (_currentLine.Trim().ToLower() == _filenameHeader)
                    {
                        _writer.WriteLine(_currentLine);
                        _entryOnNextLine = true;
                    }
                    else if (_entryOnNextLine)
                    {
                        _writer.WriteLine(_delimiterLine);
                        _entryOnNextLine = false;
                        _successfullyUpdated = true;
                    }
                    else
                    {
                        _writer.WriteLine(_currentLine);
                    }
                }
                _reader.Close();
            }
            if (!_successfullyUpdated)
            {
                _writer.WriteLine(_filenameHeader);
                _writer.WriteLine(_delimiterLine);
                _successfullyUpdated = true;
            }
            _writer.Close();
        }
        if (_successfullyUpdated)
        {
            File.Copy(_tempFile, _schemaFile, true);
            File.Delete(_tempFile);
        }
        else
        {
            throw new ApplicationException("Unable to updated Schema.Ini file");
        }
    }
}

private static DataTable LoadDataFile(string filename, string tableName)
{
    if (File.Exists(filename))
    {
        UpdateSchemaIni(m_delimiter, filename);
        FileInfo _fileInfo = new FileInfo(filename);

        string _connectionString =
             String.Format(@"Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0};Extended Properties='Text;HDR=YES;FMT=Delimited({1})';",
            _fileInfo.DirectoryName, m_delimiter);
        OleDbConnection _connection;
        using (_connection = new OleDbConnection(_connectionString))
        {
            DataTable _dataTable = new DataTable(tableName);
            _connection.Open();
            OleDbCommand _selectCommand = new OleDbCommand(String.Format("SELECT * FROM [{0}]", _fileInfo.Name), _connection);
            OleDbDataAdapter _adapter = new OleDbDataAdapter();
            _adapter.SelectCommand = _selectCommand;
            try
            {
                _adapter.Fill(_dataTable);
            }
            catch (Exception exc)
            {
                throw new ApplicationException(String.Format("Error when trying to create a table from file {0}. {1}", filename, exc.Message));
            }
            return _memberTable;
        }
    }
    else
    {
        throw new ApplicationException(String.Format("Specified file does not exist, unable to load file - {0}", filename));
    }
}