Dailycode.info

Short solution for short problems

Passing objects in methods by ref or not....

public void Foo(Image image)
{
    // This change won't be seen by the caller: it's changing the value
    // of the parameter.
    image = Image.FromStream(...);
}

public void Foo(ref Image image)
{
    // This change *will* be seen by the caller: it's changing the value
    // of the parameter, but we're using pass by reference
    image = Image.FromStream(...);
}

public void Foo(Image image)
{
    // This change *will* be seen by the caller: it's changing the data
    // within the object that the parameter value refers to.
    image.RotateFlip(...);
}
Source: Stackoverflow

.Net: Parse 24 hour data time from utc to central europe time

While I was handling time format differences, I noticed different things. For example, if the time or date comes in as 1/1/2016 1:1:1.

Then if you specified 'dd/MM:yyyy hh:mm:ss' it will not work. You will get an exception because the time format is not known. Change the format to 'd/m/yyyy h:m:s' and it will work. 

Just one problem still, of you get a time above 12, eg 1/1/2016 13:1:1 it will again fail saying time format not known. Because of the 'h' as hour format. Changing this into capital 'H' will handle the 24 hour format.

So my code for a deserialization of a property looks like this:

[OnDeserialized]

void OnDeserializing(StreamingContext context)

{

    if (this.SyncTimestampString == null)

        this.SyncTimestamp = null;

    else

    {

        try

        {

            //2/03/2016 15:40:47

            var result = DateTime.ParseExact(this.SyncTimestampString, "d/M/yyyy H:m:s", CultureInfo.InvariantCulture);

            TimeZoneInfo cstZone = TimeZoneInfo.FindSystemTimeZoneById("Central European Standard Time");

            this.SyncTimestamp = TimeZoneInfo.ConvertTimeFromUtc(result, cstZone);

        }

        catch (Exception er)

        {

            this.SyncTimestamp = null;

            LoggingComponent.LogError(this.ToString(), "SyncTimestampStringToSyncTime", er);

        }

    }

}

 



Grabbing the image from AXIS (P1346) Network Camera

Thanks to the wonderful API this camera has, you do not need DLL's or Active X controls. You can just get an image for example by the API.

Here an example to get the image from the camera using c# (this can be used in a service, web service or other applications):

Uri test = new Uri("http://192.0.0.100/jpg/image.jpg");

WebClient wc = new WebClient();

wc.Credentials = new NetworkCredential("MyUser", "MyPassW0rd");

wc.DownloadFile(test, @"C:\TakePicture\picFromWS.jpg");

wc.Dispose(); 

 

 


Creating a service for your class library

During development, I always use a small WPF client to test the program, when test are going ok I create the service.

This week I used this tutorial twice, it only took me 1 hour to set it up correctly and needly (with event logging etc).

http://msdn.microsoft.com/en-us/library/zt39148a(v=vs.80).aspx

Logging I do with the aidf of a simple extra class (code found at the end of this post)

EventLogWriter.Instance.WriteToLog("Service Stopped", EventLogEntryType.Information);

I use this simple singleton class to help with the event logging:

 

/// <summary>

    /// Class enabling writing to the eventlog

    /// </summary>

    public class EventLogWriter

    {

        private System.Diagnostics.EventLog eventWriter;

 

        #region Singleton Pattern

 

        // Singleton.

        private static EventLogWriter _instance;

 

        /// <summary>

        /// Singleton Pattern.

        /// </summary>

        public static EventLogWriter Instance

        {

            get

            {

                if (EventLogWriter._instance == null)

                {

                    EventLogWriter._instance = new EventLogWriter();

                }

 

                return EventLogWriter._instance;

            }

        }

 

        #endregion

 

        /// <summary>

        /// Constructor

        /// </summary>

        public EventLogWriter()

        {

            // 

            // init eventWriter

            // 

            eventWriter = new EventLog();

            eventWriter.Log = "Application";

            eventWriter.Source = "SFIAutoMeasurementService";

        }

 

        /// <summary>

        /// Writes an entry to the eventlog

        /// </summary>

        /// <param name="msg">Message to write</param>

        /// <param name="entryType">Eventlog entry type</param>

        public void WriteToLog(string msg, EventLogEntryType entryType)

        {

 

            try

            {

                if (System.Diagnostics.EventLog.SourceExists("SFIAutoMeasurementService"))

                {

                    eventWriter.WriteEntry(msg, entryType);

                }

            }

            catch { }

 

        }

    }

How to read an excel 2007 or 2010 file with the OleDbConnection.

How to read an excel 2007 or 2010 file with the OleDbConnection. My mistake was that I started out from a older connection string:

 

sConnectionString = @"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + uploadPath + ";Extended Properties=Excel 8.0;";

 

 

I got 2 different errors:

1 Could not find installable ISAM.

2 External table is not in the expected format.

It could only be fixed off course by using the correct connection string. So instead of using the Jet.OLEDB I used the ACE.OLEDB (Microsoft Access Database Engine 2010)

 

sConnectionString = @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + uploadPath + ";Extended Properties=Excel 12.0";

 

 

Then here is the fill code to read en Excel file into a DataSet

 

private void Upload(string uploadPath)
        {
            //Doupload
            string sConnectionString;
            //sConnectionString = @"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + uploadPath + ";Extended Properties=Excel 8.0;";
            sConnectionString = @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + uploadPath + ";Extended Properties=Excel 12.0";
           
            OleDbConnection Exlcon = newOleDbConnection(sConnectionString);
            string sDate = "";
            string sRowsNtInserted = "";
            int iRows = 0;
            DateTime date1;
            string sMonthName = "";
 
            try
            {
                Exlcon.Open();
            }
            catch
            {
                //ShowAlertMessage("Please select valid excel file.");
                return;
            }
            OleDbCommand objCmdSelect = new OleDbCommand("SELECT * FROM [Sheet1$]", Exlcon);
            OleDbDataAdapter objAdapter1 = new OleDbDataAdapter();
            objAdapter1.SelectCommand = objCmdSelect;
            DataSet objDataset1 = new DataSet();
            objAdapter1.Fill(objDataset1, "XLData");
 
            //Read the dataset line by line and process the tasks, see if they already exist.
            if (objDataset1 != null)
            {
                foreach (DataRow dr in objDataset1.Tables[0].Rows)
                {
                    //dosomething
                }
            }
        }

 

 

 


How to kill a process on an other machine?

Found a good solution that does the trick! It takes only 9 line of code!

private void btnKillProcess_Click(object sender, EventArgs e)

{

ManagementScope scope = new ManagementScope(@"\\MyPCName\root\cimv2");

scope.Connect();

ObjectQuery query = new ObjectQuery("SELECT * FROM Win32_Process WHERE Name = process.exe'");

ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query);

ManagementObjectCollection objectCollection = searcher.Get();

foreach(ManagementObject managementObject in objectCollection)

{

managementObject.InvokeMethod("Terminate", null);

}

}

Source: http://weblogs.asp.net/stanleygu/archive/2010/03/31/tip-13-kill-a-process-from-local-to-remote.aspx


Entity frame work with self tracking entities database changes.

There are many ways to implement the entity framework. I chose to add a link to the template in a different project. This implementation can be found here.

Now this article doesn’t describe in detail what to do when the database changes. This can be a very pain full operation if you have to figure it out yourself. That’s why I wrote this post.

In this case I chose to change an existing database table and add a new table to the database.

I divided the solution in 3 layers, the database layer, a process layer and a GUI. In between you’ll find the entities going from top to bottom. So no use of DTO or any kind of mapping.

 

The edmx model is located in the DataLayer. Also the generated tt files for the self-tracking entities is located there.  In the CMDBProcessLayer  I added the context as link and in the CMDBentities project I added the self-tracking objects as linked files.

Let go to the update process.

Step 1 is off course update the database.

Step 2: Remove the linked files to the entities and the context.

 

 

Step 3: Update the database model (edmx file)

before:

 

after: (Do not forget to save the model, else you could get problems creating the code generation items)

 

Step 4: Delete the old tt files in the DataLayer

 

Step 5: Generate new tt files

 

Step 6: Turn off code generation on the entity model.tt file

 

Step 7: Delete all remaining file generated by the entities.tt file:

 

Stap 8: repeat step 6 and 7 for the context.tt file

 

Step 9: Add the Entity.tt file to your entities shared projects. (If you do not see the files, choose 'All Files' in the file filter box on your lower right.)

 

Step 10: add the context.tt file as linked file to the process layer

 

Step 11 (Last step): Change the namespace of context.tt file to the namespace of the shared entities project.

 

Now you can build and you have the new data structure.

 


Track changes without binding controls

When you are working with windows forms .net without binding your controls to a data object, you still need to check if a control is changed or not. For example if a user closes a form without saving it, you might want to tell the user this and ask him to save or not.

This post will show you a very simple implementation that will easy the development effort. To use this, you will need to create control wrappers for every control that you want to auto implement the track changes functionality.

Let’s begin with creating or modifying an interface that is implemented by all controls that need change tracking. I will add the property IsDirty to the interface. The interface is called: IControlBase

 

#region Properties

 

bool IsDirty { get; set; }

 

#endregion

 

Next we implement the interface in our controls and set the IsDirty flag whenever a value is changed. I will give 2 examples:

Textbox:

#region Implementation of IControlBase

 

public bool IsDirty

{

    get;

    set;

}

#endregion

protected override void OnKeyPress(KeyPressEventArgs e)

{

    IsDirty = true;

    base.OnKeyPress(e);

}

 

Combobox:

#region Implementation of IControlBase

 

public bool IsDirty

{

    get;

    set;

}

 

 

protected override void OnTextChanged(EventArgs e)

{

    IsDirty = true;

    base.OnTextChanged(e);

}

 

So this will make sure that the events we want will set the IsDirty flag. For the combobox I had the problem that the event was raised when I filled it, so I created a function that will clear all IsDirty flags after loading the form:

 

public static void ClearIsDirty(Control currentControl)

{

 

    foreach (Control isDirtyctrl in currentControl.Controls)

    {

        if (isDirtyctrl.Controls.Count > 0)

        {

            ClearIsDirty(isDirtyctrl);

        }

        if (isDirtyctrl.Parent as IControlBase != null)

        {

            ((IControlBase)isDirtyctrl.Parent).IsDirty = false;

        }

    }

}

 

After the page is loaded and all controls are filled, I simply run this function and pass the parent control to it. So it will clear itself and all child controls. The control could be a panel or the form itself:

GlobalFunctions.ClearIsDirty(tpGeneral);

 

Then the last piece of code needs to be written when the user leaves the form without saving. So the onleave of your control is captured and then we call a second function that will check all controls of the form on their IsDirty flag. Here is the function that does the trick, put this function somewhere in your general functions namespace.

private static bool _isDirty=false;

 

public static bool CheckIsDirty(Control currentControl)

{

 

    if ((_isDirty == true))

    {

        return _isDirty;

    }

 

    foreach (Control isDirtyctrl in currentControl.Controls)

    {

        if (isDirtyctrl.Controls.Count > 0)

        {

            CheckIsDirty(isDirtyctrl);

        }

        else

        {

            if (isDirtyctrl.Parent as IControlBase != null)

            {

                if ((((IControlBase)isDirtyctrl.Parent).IsDirty == true))

                {

                    _isDirty = true;

                    return _isDirty;

                }

            }

        }

    }

    return _isDirty;

}

 

Here is the implementation of this function (I check 2 tabpages on the IsDirtyFlag, if the user wants to save I save the project. At the end I clear the IsDirty flags):

private void tbcontProject_Leave(object sender, EventArgs e)

{

    if (GlobalFunctions.CheckIsDirty(tpGeneral) || GlobalFunctions.CheckIsDirty(tpInfo))

    {

        DialogResult res = MessageBox.Show("Information has been changed, do you want to save?", "Information changed", MessageBoxButtons.YesNo);

        if (res == DialogResult.Yes)

        {

            SaveProject();

        }

        GlobalFunctions.ClearIsDirty(tpGeneral);

        GlobalFunctions.ClearIsDirty(tpInfo);

    }

 


Clone a reference object with automapper

If you want your business objects to implement the ICloneable interface, using the automapper to clone your object could be very easy.

Here's how I did this. I implemented the ICloneable interface on my User object. The implmentation looks like this:

public object Clone()

{

    User clone = new User();

    AutoMapper.Mapper.CreateMap<IUser, User>();

    return (User)AutoMapper.Mapper.Map(this, typeof(IUser), typeof(User));

Then just Clone it:

foreach (User u in result)

{

    _newUserList.Add((User)u.Clone());

}