iWatchSyncer – iTunes workflow – part II

iwatchsyncer
Well since iExporter is going so well on CodePlex ( thanks LifeHacker 😉 ), I’ve added my latest version of iWatchSyncer also to CodePlex!!

I finally got around the annoying problem in Windows when you Move folders ( the event handling is different then the Copy action ). So everything should be alright now!

A quick overview: iWatchSyncer will monitor a given path for file or folder additions and will automatically add all mp3 files contained in these folders to the iTunes Music library!

[Tags]iWatchSyncer, iTunes[/Tags]

iExporter – iTunes workflow – part II

iexporter

I’ve been working on my small iTunes playlist exporting program iExporter. Currently I’m at version 1.6 and it seems it’s been getting some good feedback from several users! Because I’ve seen different websites mentioning it and each release I’ve done so far has had 200 downloads each.

In version 1.6 you can again export existing playlists that are available in your iTunes, but now you’ll also be able to export several artists! The program will search for all tracks in your iTunes collection that have the selected artist as Album Artist, this way you’ll get all albums from that artists!

I hope you like it and if you do, you can now also donate through use of the Paypal donate button available in the iExporter.

iexporterscreenshot

[Tags]iExporter, iTunes, Paylists, Mp3[/Tags]

Entity Framework – usage hurdles and tips

Well… let me start with a counter to this blog title! I actually like Entity Framework and don’t mind spending time on getting things done with it.
But, I have to be honest, some things just don’t seem to be right when I’m using it.
It could all just be me, but let me get my message out and share my experience. So here goes… my current hurdles with Entity Framework.

First of, some common issues are already listed on other sites. So first go check this list of issues and then read this post on how to tackle some of those items!

Secondly, most of my ‘problems’ are related to the interaction of the Winforms DataGridView control with EF, so maybe not everything is really due to EF itself.

  • Missing metadata
  • This element is not actually true, because EF has all the metadata a programmer needs. But it’s to far hidden, in my opinion!
    Lets give an example… in my program I want to have several managing forms that actually do nothing more than CRUD actions. So the setup of each form is almost the same, the only thing that is different is the Entity Objects being used in the Grid to show the data.
    But due to the nature of the DataGridView and the usage of ObjectQuery as BindingSource, you will get all the columns that are defined in the ObjectQuery. Meaning Key columns and relational mapping columns will appear inside the grid!
    This is something I don’t want to show inside my grid ( this is my setup, so maybe for some people those columns can be relevant ).

    So I wanted to hide these columns and I didn’t want to do this manually in the designer of the DataGridView for each form. I even didn’t want to know about the names of those fields/columns and write something against that. So the only way I could make this generic was by using the EF metadata of the Entity Object. But that’s where I was stuck… how could I get this information quickly?

    Well my solution uses Extension so I don’t have to type much code to get the metadata

    public static EntityType MetaData(this EntityObject entity, ObjectContext entityContext)
    {
    return entityContext.MetadataWorkspace.GetItemCollection(DataSpace.CSpace).GetItem(entity.GetType().FullName);
    }

    What this allows me to do is get the metadata of an entityobject instance like this

    var col = fooObjectEntity.MetaData(DataContainer.GetInstance().DataEntities).KeyMembers;

    One small problem with this solutions is that you have to pass along the ObjectContext.
    Some people solve this by adding something similar to the ObjectContext itself, take a look here ( it are some thoughts on a question Julie Lerman asked ).
    Passing the ObjectContext is needed, because it’s not possible to get it from the EntityObject itself, as talked about here! ( although I haven’t checked out Patrick’s version of a possible solution yet… look here )

  • Setting the bindingsource
  • I don’t know why, but for some reason I can’t just bind the ObjectQuery to the DataGridView.DataSource directly! Ok maybe wrong again, I can do this and the grid will show the data, but when I add a EntityObject to the given ObjectContext and do a .SaveChanges(), the grid will not refresh the data!! ( after the SaveChanges() I reset the DataSource of the grid to the ObjectQuery )
    I don’t have a clue why this is… updating data will work fine, but adding rows/objects won’t!
    The only solution I found, that solves this is to use Object instantiator of the ObjectQuery. In my case the .ToList() method.

    this.categoryBindingSource.DataSource = DataContainer.GetInstance().DataEntities.Category.ToList();

  • Using related data inside the DataGridView
  • Something that annoyed me was the fact that DataGridView didn’t pick up related data fields as columns.
    For example when you have some EntityObject Member that has a relationship to Address, doing following in code will not get the Address fields as columns inside the grid.

    this.memberBindingSource.DataSource = DataContainer.GetInstance().DataEntities.Member.Include("Address").ToList();

    A pity it doesn’t do this… because when I want to get a row back from the grid I still want to have a EntityObject of type Member, so writing some ObjectQuery myself with all the data seems not the good solution.
    For this little problem I asked what Julie Lerman would do. And she pointed out that the way she does it, is by inserting the values manually during the moment that the grid gets populated. Details are in the comments here. So the solution I used was getting hold of the CellFormatting event and pasting the needed values in the correct cell.

    private void gridSchool_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
    {
    if (!this.gridSchool.Rows[e.RowIndex].IsNewRow && this.gridSchool.Columns[e.ColumnIndex].Name.Equals("addressStreet", StringComparison.OrdinalIgnoreCase))
    {
    School currentSchool = this.gridSchool.Rows[e.RowIndex].DataBoundItem as School;
    e.Value = currentSchool.Address.addressStreet;
    }
    }

Well that’s it for the moment… like you see most of the things I stumbled upon are also stuff other people noticed, so maybe they will get addressed during v2 of the Entity Framework ?
On the other hand I still do like the EF as a concept and I hope Microsoft will invest much time and effort into it :).

[Tags]Entity Framework, C#[/Tags]

Culture sensitivity in List<string> – how to do comparison

I recently stumbled upon a small c# problem I thought would have been easy to fix… But even now with the .Net framework 3.5, I can’t find a good solution!

So first the details on the problem. When you are using Generics, it’s very easy to construct lists of strings! Example: List<string> foo = null;
And when you want to search for a specific value inside this string list, you would most likely use the .Contains() method… But this has one huge drawback, it will only use the default equality comparer!
Details can be found in the MSDN information of the .Contains() method on List<T>.

In other words, you can’t search for Culture insensitive stuff, nor can you search for Case insensitive stuff!!
To illustrate, in following example the boolean value of contains will be FALSE, because “test” is not the same as “TEST” based on the case sensitivity of the default equality comparer.


List<string> foo = new List<string>();
foo.Add("test");
bool contains = foo.Contains("TEST");

But thanks to the Exists method on List<T>, we are able to write some extra code that will allow us to check against case insensitive strings.


List<string> foo = new List<string>();
foo.Add("test");
bool containsValue = foo.Exists(delegate(string argument)
{
return argument.Equals("TEST", StringComparison.OrdinalIgnoreCase);
});

In this last example, after the Exists method, the boolean value of containsValue will be TRUE… This because now we use the StringComparer class with the indication that we are not interested in case sensitivity!

The given problem has already been brought up by “Andrew Webb” as an enhancement request for the .Net framework ( cfr. his comment in this BCL Team blog post for .Net 4.0 ) and it seems the BCL team will take a look at it. ( fingers crossed )

[tags]c#, Generics[/tags]

SelectionChangeCommited event on Combobox not triggered

There seems to be a problem with the .Net Combobox control ! Microsoft is stating it isn’t actually a real problem, but still it is something a programmer should know and if needed take care of.

Let me first explain the problem… If you use the mouse to open a combobox, but then use the arrow keys to navigate in the list and change focus with the tab key, the combobox will select the highlighted value, but will NOT trigger the SelectionChangeCommited event !!
So in other words, even though the programmes subscribes to this event to know when a user has selected a value, the program will not notice it.

According to this post : http://weblogs.asp.net/grobinson/archive/2005/09/21/425711.aspx, Microsoft is aware of this and regards it as standard behaviour. So we are left with the only option to write a workaround ourselves.

I’ve found a good starting solution here : https://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=3409311&SiteID=1, but I think this can be improved ! Because with this given solution, if a user still would use the mouse to select an item we would get the SelectionChangeCommited event twice.
So the workaround is to suppress the base event and only trigger our own. Here is the code…

[tags]SelectionChangeCommitted, combobox, c#[/tags]

Serialize/Deserialize objects in .Net – don’t forget to initialize

Recently in our project I had a weird exception popping up in C#. We found the problem and fixed it… but the problem was something we didn’t expect ! So I’ll post my findings here so other people can benefit from it.
I must say, I don’t know if this behaviour is anywhere described in MSDN, so could be I missed the information.

Consider this class Foo with only 1 member O1 that is Serializable.

[Serializable]
public class Foo
{
private object _O1;

public object O1
{
get { return _O1; }
set { _O1 = value; }
}

public Foo()
{
O1 = new object();
}
}

Now we are going to save an instance of this Foo class to file through Serialization ! ( here done through unittesting with NUnit )

[Test]
public void SerializeTest()
{
Foo foo = new Foo();
Assert.IsNotNull(foo.O1);

BinaryFormatter formatter = new BinaryFormatter();
formatter.AssemblyFormat = FormatterAssemblyStyle.Simple;
FileStream stream = new FileStream(@"c:\temp\foo.dat", FileMode.Create, FileAccess.Write, FileShare.None);
formatter.Serialize(stream, foo);
}

Now we have a binary representation of Foo on file, called foo.dat !
After this, we change the Foo class and add a second member called O2.

[Serializable]
public class Foo
{
private object _O2;

public object O2
{
get { return _O2; }
set { _O2 = value; }
}

private object _O1;

public object O1
{
get { return _O1; }
set { _O1 = value; }
}

public Foo()
{
O1 = new object();
O2 = new object();
}
}

And now for the big problem… we Deserialize the foo.dat file with this new Foo class code.

[Test]
public void DeserializeTest()
{
BinaryFormatter formatter = new BinaryFormatter();
FileStream stream = new FileStream(@"c:\temp\foo.dat", FileMode.Open, FileAccess.Read, FileShare.Read);
Foo foo = (Foo)formatter.Deserialize(stream);
Assert.IsNotNull(foo.O2);
}

And what do you notice ? The test wil FAIL !! Yes… what we didn’t expect was the fact that .Net somehow can initialize the Foo object without going through it’s default constructor !!
Resulting in a Foo object with a O2 member that equals NULL instead of new Object() !

This would mean that if you need to deserialize newer class versions of existing binary objects, you should use the interface ISerializable and use protected Foo(SerializationInfo info, StreamingContext context) to be sure all members ( and new members ) are serialized and initiated ?

Can anyone shed some light on this ?

[Update] Jelle has given me the correct link to the MSDN documentation that gives the answer to this phenomenon !! Thanks Jelle ! http://msdn2.microsoft.com/en-us/library/4abbf6k0(VS.71).aspx

[tags]C#, .Net, Visual Studio[/tags]

To comment or not to comment

Damn, Chad Myer‘s post about mistakes of comment usage in code made me think !

I tend to agree with him about the fact that your own code should be self explanatory, so that code comment is redundant.
But on the other hand, sometimes a little comment about the flow of the code always tends to help me understand the code itself better.
That aside, my code doesn’t have that much of code comment ( except for the //TODO: lines ) !
So I had to search a bit, but found a good example IMO, to show of the need of code comment… This to answer Chad’s question !

So here it is, what do you think ? Is the comment valid, should it stay in the code ? I think it should ! It still seems very obvious, but I would like to keep it in.


/// The general list has 2 internal lists:
/// * one pointing to the actual objects in the database
/// * one pointing to the actual objects in memory
/// To get the total count we have to take following flow into account
/// * the memory reference can be different from the database reference, so we combine the 2 counts and subtract the objects that are already available in the database list
public int Count
{
int totalCount = 0;

totalCount = ReferenceEquals(this.internalListMemory, null) ? 0 : this.internalListMemory.Count;
totalCount += ReferenceEquals(this.internalListDatabase, null) ? 0 : this.internalListDatabase.listCount;
foreach (DictionaryEntry internalListDataObjectsElement in this.internalListMemory)
{
if (!ReferenceEquals(this.internalListDatabase, null) && this.internalListDatabase.ListFind(internalListDataObjectsElement.Key))
totalCount -= 1;
}

return totalCount;
}

[Update]
Like I stated above, maybe the code comment is a bit to abvious ( so it could be omitted, but I’m in favour to let it in ).
So here maybe another example… but also here a small suggestion, this could maybe be changed to a //TODO: version. Depending on the work flow of programmer and his Task list.


/// There is a bug with the Excel interop for Office XP ! We first need to set the current culture to en-US to get correct date time values
public void StartTimeProcessing()
{
System.Threading.Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.CreateSpecificCulture("en-US");

- Rest of code with use of the interop code
}

Default user Locale through .Net

kick it on DotNetKicks.com

For who doesn’t know this yet, I’m a software programmer !
Currently I’m working with Visual Studio 2005 and develop software with C#.

And every now and then you get stuck in a situation that seems hopeless :). Even with a large team of capable people and the vast code example base available on the internet, some problems seem unsolvable !
So let me tell you a small story about one of this problems I recently had.

First the current layout of the project, we create software, but we actually sell a complete system to our customers. This means that we will ship a Dell desktop model together the software ! Then our service people will run the install scripts on site and configure it to the needs of the customer. But during the configuration, the service guy has to create several users through the configuration program. These users are stored in Windows XP as actual users, so when the service guys creates a new user, the default settings for this user are coming from Windows XP itself.
More technical detail : there is a .Default user defined in the Windows Registry that acts as a template for each new user !

Now the problem with this setting… Each time the service guy adds a user he has to set this user to the correct Locale, depending on the country where the software is going to get used ! This because the user account for the service people is put to English – US and it could be that each user has to be set to Dutch – Belgium.

To facilitate the install, we had the idea of manipulating Windows XP in such a manner that during configuration of our software the service guy can pick one Locale that will have the effect that each time he adds a new user it will already have those Locale settings.

For this problem I was asked to come up with a good solution in C# !!
And well to cut a long story short, I haven’t found one !!!!! So I was stuck.
The only real solution I found had to many pitfalls, we regarded it as a ‘no go’. It consist of creating a CultureInfo object from a given LCID and dumping all data into the Registry node of HKEY_USERS\.Default\Control Panel\International ! Even though I think this should/could work, I think that string manipulating each value to the correct format would lead to many possible errors.

What happens when I’m stuck… I go around the internet and search for topics that are closely linked. Well let me say that since the dawn of Blogs, we are blessed with information and knowledge that has impact on real life development !!
As a blogger myself, I know that writing a good article with some tutorial knowledge so since developers started using this medium my life got a lot easier :).
Because of my current working position I follow a lot of MSDN blogs that have a close or near relationship with .Net, Visual Studio or C#. One of those blogs is the one of Shawn Steele, and let me tell you his blog is superb ! Easy to follow and the example code/solutions he posts are all eye openers for me.

Well because he had already written many posts about cultural settings, I tried to contact him to see if he could shed some light on my problem. And guess what, I got a solution within 24 hours !!!!! That isn’t even damn fast, that is just amazingly brilliant !! His original answer is situated here.
Thanks again Shawn !!

After looking at the solution, there are 2 lesson to be made :

1. Not everything can be done with .Net ( so hence the reason why I got stuck 🙂 )
2. Not all solutions need to be difficult ( just one Windows script command line does exactly what we wanted )

Now for all other people out there who would stumble upon this same problem, here is the code I used in .Net to launch the script, enjoy.


public void StoreCultureInfo(int lcid)
{
try
{
//First create a CultureInfo object from the given LCID code
CultureInfo cultureInfo = CultureInfo.GetCultureInfo(lcid);

//Setting the .Default user in the Registry can't be done through .Net code in a straightforward manner !
//But there is a way to do this through use of command line syntax, the details can be found here : http://support.microsoft.com/default.aspx?scid=kb;en-us;289125
//Reminder : This option will only work for Windows XP, in Windows Vista detailed solution can be found here : http://www.microsoft.com/globaldev/vista/vista_tools/vista_command_line_international_configuration.mspx

//First we need to create a text file with the correct Locale for the Default user
//The locale should be specified in Hexadecimal format !
string hexadecimalLCID = cultureInfo.LCID.ToString("X");
string localeConfigurationFile = Path.Combine(PathHelper.TempDirectory, "regopts.txt");
//Be sure this configuration file doesn't exist yet
if (File.Exists(localeConfigurationFile))
FileHelper.DeleteFileEvenIfReadonly(localeConfigurationFile);

using (StreamWriter streamWriter = File.CreateText(localeConfigurationFile))
{
streamWriter.WriteLine("[RegionalSettings]");
streamWriter.WriteLine("UserLocale_DefaultUser = {0}", hexadecimalLCID);
streamWriter.Close();
}

//Now execute the command line option to swith the default user locale !
Process process = new Process();
process.StartInfo.FileName = "rundll32.exe";
process.StartInfo.Arguments = string.Concat("shell32,Control_RunDLL intl.cpl,,/f:", "\"", localeConfigurationFile, "\"");
process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
process.Start();
process.WaitForExit();

int processExitCode = process.ExitCode;

if (processExitCode != 0)
throw new ApplicationException("Problem occured while setting the Default user locale !");
break;
}
}
catch (ApplicationException ex)
{
}
}

Technorati tags: , , , ,

Clean .Net program install package = ILMerge

I just had to post about this little tool ! I think all people who are busy in software development using .Net, should at least have a look at it ;).

What am I talking about, well, a small tool called ILMerge. It’s available from the research part of Microsoft. So what is it about ?

Best way to explain a tool is by giving an example : Imagine you have several .Net projects that, all of them, create separate dll’s ! This is not uncommon and you probably designed your projects this way, because they reflect some sort of internal business architecture… so no worries here. But on the other hand you probably also have some solutions that incorporate several projects, who have some kind of common link between them. So wouldn’t it be nice if you could get all those projects, that are linked one way or another, inside one dll instead of separated ones ?

Well with ILMerge you can accomplish this ! It will combine several input dll’s into one target dll or even better, combine an exe and several dll’s into just one exe ! Another example is to combine code dll’s together with their resource assemblies !

This procedure is of course only relevant for deployment of your software, so developers don’t have to perform this step and still can program with the complete original dll base ! But before packaging the software, it would be ideal to merge several dll’s to get a cleaner, smaller install package.

On a side note, I received a small update by Scott Guthrie, that there will be an ASPNet_Merge.exe MS Build task with the Visual Studio 2008 release !! But no ILMerge task yet…

Technorati tags: , , , , , ,

DateTime formatting the .Net way

Back in the ‘old’ days when we where using Visual Studio 6 and made our first Visual Basic programs, we had to rely on ‘good luck’ and ‘plumbing’ to get some tasks done !

What I mean to say is, that sometimes the software would have a mind of his own ! Some code just didn’t perform in the correct expected manner. And this wasn’t something you actually could have avoided, no the software had some flaws !

But with the arrival of Visual Studio .Net and the new programming languages like C#, this seemed a thing of the past ! Until now that is ! Because I have a small code example I would like to show you, that would seems very straightforward, but has me ‘bugged’ whole week.

The thing I’m trying to do, is cast a normal DateTime.Now to a Time format, but depending on the current user settings ( in the regional settings ). What would seem like an obvious thing to do… So here we go with our little experiment !

  • First set your regional settings correct : English ( US )

  • Then go to Customize and in the Time pane change the time to display using the 24 hours notation ( and loose the AM & PM )

  • Create a small console application and paste following code ( we are talking Visual Studio 2005 here )

// Expected : True, Actual : True
Console.WriteLine(Thread.CurrentThread.CurrentCulture.UseUserOverride.ToString());
// Expected : H:mm:ss, Actual : h:mm:ss
Console.WriteLine(Thread.CurrentThread.CurrentCulture.DateTimeFormat.ShortTimePattern);
// Expected : H:mm:ss, Actual : h:mm:ss
Console.WriteLine(System.Globalization.DateTimeFormatInfo.CurrentInfo.ShortTimePattern);
// Expected : 10/13/2006 13:31, Actual : 10/13/2006 01:31
Console.WriteLine(DateTime.Now.ToString("g"));
// Expected : 10/13/2006 13:31:28, Actual : 10/13/2006 13:31:28 !!!!!!
Console.WriteLine(DateTime.Now.ToString());
// Expected : 13:31, Actual : 01:31
Console.WriteLine(DateTime.Now.ToString("t"));
Console.ReadLine();

So as you can see, the DateTime.Now.ToString(“t”) option will NOT take into account the current user settings, found on the regional settings pane ! This is not something I would expect… I would just like my code to be as little dependent as possible. So I WANT to use the default DateTime formatting options and not having to wander about what the user chooses. It must be up to the user to get the right format he wants, I just want to be able to tell the program to give me the Time and not the complete DateTime.

After this little experiment, I searched further for any information, but got back empty handed.

The only document on MSDN that says something significant about DateTime and the regional settings can be found here. But it just states the things I would expect in my test and they just aren’t true.

After this set back I contacted Chris Sells Program Manager in the Distributed Systems Group at Microsoft, hoping maybe he could shed a little light on my issue ! To be honest this guy is amazing ;), knowing he’s probably swamped with work, he still managed to reply me in a very fast time frame ( thanks Chris ) !

The first thing Chris noticed was that I could get the good user settings information through the following code :

System.Globalization.DateTimeFormatInfo.CurrentInfo.FullDateTimePattern

But this wasn’t helping me much… the real problem is not getting the info about the DateTime format, but displaying it correctly using the default formatters in .Net ! So this info is a bonus, yes, but still I’m stuck !!

So for now I use a small work around, that I would love to delete as soon as possible, by reading out the users settings of the regional settings through the HKEY_CURRENT_USER in the registry ( \Control Panel\International ).

Chris will still check his huge background information repository 😉 and hopefully come back with some good news. But if ANYBODY knows how I can solve this ‘little’ problem, please help me out !

UPDATE : well Chris got back to me on this problem… he submitted my question on some community and he got an answer from Michael Kaplan !
It seems he has answered this question before !! Take a look here for more info on the solution.

In short : “A lot of the confusion is due to the fact that the .NET Framework has two time formats (long and short) while Windows only has one time format (long) which can optionally be truncated in GetTimeFormat.” And : “So the answer to the original customer inquiry, to wit: “The main issue is that I don’t understand why/when .Net uses the user overrides of the Regional Settings” is that only one of the settings in .NET directly relates to the one in Windows, even though they both look like they ought to….”

Currently listening to : Autoharp – Hooverphonic ( The Magnificent Tree )
Del.icio.us tags: , , ,