Wednesday, November 23, 2011

Compiling multiple projects into a single exe file in WPF


A long time ago I wrote a simple application using WPF (I will write about this utility in my next post) that I recently dug up from the lost archives and I wanted to use in my every day life (at work & at home).

I realized that this small application was made up of 3 projects, thus creating one exe file and 2 extra dll files.
Since I want to pack it light, and I truly see no reason to carry around 3 files that are all under 1MB, I looked for a way to compile all of this under one file.

After looking on the internet a little bit, I found a simple solution, which probably isn't the best way to do it but it works good enough for me...

First, in my main project, I created a folder called Assemblies, and put the other compiled dll's into this folder manually. Then, I defined these dlls' Build Action to be 'Embedded Resource' (this is found in the properties window of every file in your project - image attached).
This will cause the dll's to be compiled as resources embedded into the output exe file.



And now that the dll's are in the exe file, we can delete the dll's in our output folder and just run our exe file, right?
Wrong! The CLR will still look for these files in the folder (and also in the GAC) and when it doesn't find them it won't know what to do.

So all we need to do actually, is just tell the compiler where to look when it doesn't find the files in the original location.
This is done by overriding the method 'AssemblyResolve' in our current AppDomain object like this :

AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
    {
        String resourceName = "MyProject.Assemblies." + new AssemblyName(args.Name).Name + ".dll";
        using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName))
        {
            if (stream == null) return;

            byte[] assemblyData = new byte[stream.Length];
            stream.Read(assemblyData, 0, assemblyData.Length);
            return Assembly.Load(assemblyData);
        }
    };

What we did here is just retrieve all the embedded resources and find the specific assembly the CLR was looking for.

Now, after compiling your project, you can delete the other dll files in your output folder and the exe file will work on its own.

While thinking of this solution, I didn't like the idea of having to copy the assemblies after every change into the 'Assemblies' folder I created, and then compiling again... but after thinking about it for a while, I think it's not that bad in my case if I consider the circumstances - I'm talking about a very small solution, only 3 projects, and all i need this packing into one file for is to move it around. I also don't believe I will be working on it that much more, so this means I just need to do this once. If it was a current project at work or even for fun, I wouldn't go with this option, and i would've found a better way around this...


An extra note : While running the application for the first time, it immediately crashed. I opened it in debug mode (which actually meant I needed to put a Thread.Sleep() in the initialization and then attach to process through VS since I wanted to delete the dll files before debugging). I realized that the application was looking for an assembly called XmlSerializers that I never created. I don't know exactly why, but it turns out that this was automatically generated while compiling. No worries though, this can be taken care of. Just go to the project properties > Build > Output > Generate serialization assembly = Off.

Monday, November 7, 2011

Breaking The Build

Today was one of the hardest days at my new job (at Sears Israel) since I started working there...

It all started when I arrived very early at work (around 8:00am) because I wanted to get a lot done, but instead I arrived and immediately found out that one of the acceptance tests I wrote (automated UI testing) was failing and breaking the build on our integration server.
So instead of getting straight to my regular tasks, I started looking into the problem which unfortunately, took a big part of my day. I don't want to bore you with details about why the test was failing since there's nothing technically interesting about it, but I do want to share with you what I learned from it.

We write A LOT of tests! Unit tests, integration tests and acceptance tests. We spend a lot of time writing them and a lot of time thinking how we can improve the framework and make the tests even better in the future. I haven't been familiar to this kind of attitude in the past, but from what I see already at Sears, is that this attitude pays off big time in the long run!
Today, I spent a big part of the day "not getting any work done", and not learning anything new about good design, nor better programming techniques... I spent time digging into my code, until I finally found out that the problem had nothing to do with my code. Even though, I still think this is a good lesson to learn from. During the whole time spent debugging, all I could think about was putting an 'Ignore' attribute above my test, committing, and finally getting back to my regular work, but this would just be cheating and beating the point all together. Doing this would've been taking all the countless hours spent writing these tests in the company and saying they don't matter and just throwing them away. If we don't care enough to maintain these tests like they should be, then we are eventually throwing them away, along with all the time spent on them...

Today, if I start working on a project, even just for myself at home, just something for fun, I can't imagine doing that without writing the proper tests to go along with it. This is becoming an integral part of coding for me...

All in all, I went home today with a good feeling. I know that the tests work, the code is of good quality and I did my part to keep that true now, and in the future. This feeling is rewarding and pays forward to the "hard day" feeling I had while confronting the problem I just wrote about...

Monday, October 24, 2011

The New Environment

I just recently posted about moving on - the decisions I made, why I made them and what I feel about it...

Well, now that only two 'innocent' weeks have past since I started working here, I already have a lot to say about this. Off the bat, the decision was brilliant! The people here are great. Each one of them has many experience, each in his specific field, and they love doing what they do best. They also enjoy helping others and making sure the 'team' does a great job together which is amazing.

I won't even attempt to name all the new things I've learned during this short period working here, but just to name a few -

Agile :
DSM's, Poker Planning, and Retrospective meetings are all great ways to keep the team focused. They don't get in your way, and they always keep you on track with what's going on.
In my previous job, there were times when some people in the team don't know what some of the others are doing. This can cause a lot of code to be rewritten for no reason, people to be spending time on bugs that someone else on the team knows how to fix and poor design since the more people involved in the design the better it will turn out to be.

Productivity :
Everyone here is super productive and it seems like they dedicate time finding ways to be even more productive.
ReSharper is one of the gems in the field!! I never realized how much more coding can be done when you just have the right tool and I don't want to even try to imagine going back to programming without it. (This is said without even knowing half the features this tool has, even just knowing about Ctrl+T & Ctrl+Shift+T are enough!!)

Coding :
The first two weeks here the team leader let me solve bugs on the system, which I think is a brilliant way to learn the code. If the bugs are well chosen, then you will even learn everything there is to know about the system you'll need to work on very soon. While looking at the code, and fixing bugs, I learned a lot about designing good and maintainable code. I'm not gonna say it's perfect, as in every place, but there are so many concepts in design patterns I've learned just from debugging and reading the code.
Just some of the new concepts I've learned here are : IoC - Heavy use in many brilliant ways of the windsor container. Convention over Configuration - Never realized the great power of this concept before, how it effects your code and why you should always keep it in mind when coding. Continuous Integration - This is amazing! Never thought it would be possible to deploy to production so many times a week or even day! Selenium - Great automated way to check your web application across browsers. And the list goes on....

Hopefully I'll be posting more now that I'm learning a lot of new stuff.... :)

Monday, September 19, 2011

A New Direction

I finally decided to move on...
After working for two years at an Israeli credit card company (ICC a.k.a. C.A.L.) as a .net web developer, I think it's time for me to start something new!
Here are some of the thoughts and questions running through my head at the moment :

What did I accomplish in the past 2 years ?
My technical programming skills did improve, but not as much as I would want them too. That's exactly why I'm leaving.
I did gain experience and I feel that I did improve but not to my full potential. During these two years I had to learn a lot on my own, reading blogs on the internet, and trying to incorporate the new technologies at my work place. Most of the people at my workplace have been there for a couple of years prior to me arriving and they aren't keen on letting some new dude change the way they're used to working.
You know what they say - It's really hard to teach an old dog some new tricks... :)

What was I looking for ?
When I started looking for a job, I decided that the most important aspect to me is a place where I will advance technically and learn as much as I can from. As a programmer I believe that half the job (at least) is to always learn new technologies/frameworks/utilities that will help you become a better and more efficient developer. I believe that if the people at your current work place aren't always pushing to learn new technologies then it will be very hard to do it on your own... (If you succeed, tell me how).

Where am I going ?
After only a few interviews, I decided to start working for Sears Israel (SHC). The first thing that got me intrigued about them is that they were the only place that during the technical interviews actually asked me some questions that I didn't have a clue to the answer! During the interviews, from my first impression, it seems like the programmers there really know what they're doing and are fully dedicated to writing excellent code!
In addition to the technical stuff, the product seems interesting, and a very modern idea. It's basically a social shopping site, but with tons of interesting features. I know that the challenges they deal with are interesting - The most interesting to me is how do you create a site with great scalability?...

Some more general and honest thoughts about the new job...
Brutal truth to be said - I'm a little worried I won't live up to the standards at Sears. My new team leader sent me some subjects/frameworks to learn before I arrive so I'll feel a little more comfortable when I arrive. Some of these technologies/frameworks I haven't used much or at all in the past (like IoC & MVC3), and some (like Apache & Tomcat + Java) are totally new ground for me. But this just makes the job 10 times more interesting to me! I just hope I'll be able to learn all the new stuff fast enough so I can keep up with the pace.
But this doesn't make me put my self down, instead it just makes me want to get so much better at what I love doing (programming!). I don't have experience looking for and hiring employees, but I think that one of the most important things you should look for in a new employee is someone that loves what he does and that you know will always be open to learn new stuff from other sources. Of course you want someone that has a certain amount of programming knowledge, but someone who is very experienced but has no motivation will be a bad bet in the long run apposed to someone a little less experienced but fully motivated.
I believe I fit into the fully motivated category. I know for a fact that I love learning new stuff, and that I'm always open to changes, so I think i'm a good bet... :-p


Saturday, August 27, 2011

Unit testing FluentNHibernate...


As I recently posted, I just got back to unit testing...
I thought of a small personal project to start practicing on, and got to work. My project consisted of using Fluent NHibernate, so I wanted to create unit tests to make sure my mappings were good.

I came across an old blog post of Ayende explaining that he created a base class that exports all your mappings into an in-memory sqlite db just for testing.
This concept seemed really good to me, so I tried it myself, but ran into some small problems while trying to configure it for Fluent NHibernate, so I will post the new version to ayende's class that works for FNH :

In case you don't have the SQLite providers yet, you can download them here.

This is the class :
public class InMemoryDatabaseTest : IDisposable
{
    private static Configuration configuration;
    private static ISessionFactory SessionFactory;
    protected ISession session { get; set; }

    public InMemoryDatabaseTest(Assembly assemblyContainingMapping)
    {
        SessionFactory = Fluently.Configure()
            .Database(SQLiteConfiguration.Standard.InMemory().ShowSql())
            .ProxyFactoryFactory(typeof(ProxyFactoryFactory))
            .Mappings(m => m.FluentMappings
                            .Add(assemblyContainingMapping)
                      )
            .ExposeConfiguration(x => configuration = x)
            .BuildSessionFactory();

        session = SessionFactory.OpenSession();

        SchemaExport export = new SchemaExport(configuration);
        export.Execute(true, true, false, session.Connection, null);
    }

    public void Dispose()
    {
        session.Dispose();
    }
}

And then all you have to do to test your mapping would be something like this :
[TestClass]
public class UserTests : InMemoryDatabaseTest
{
    public UserTests() : base(typeof(UserMapping).Assembly)
    { }

    [TestMethod]
    public void UserMapping_CanSaveAndLoadUser()
    {
        object id;

        using (var tx = session.BeginTransaction())
        {
            id = session.Save(new Dal.Entities.User()
            {
                Username = "unittest",
                Password = "unittest1234",
                Email = "unittest@gmail.com"
            });

            tx.Commit();
        }

        session.Clear();

        using (var tx = session.BeginTransaction())
        {
            var user = session.Get<Dal.Entities.User>(id);

            Assert.AreEqual(user.Username, "unittest");
            Assert.AreEqual(user.Password, "unittest1234");
            Assert.AreEqual(user.Email, "unittest@gmail.com");

            tx.Commit();
        }
    }
}

It's that easy! :)

Thanks Ayende!

Monday, August 15, 2011

Beginning Unit Testing...


I finally decided to get back into Unit Testing...

I have worked once in the past for a short period of time (only a couple of months) with unit testing, and my experience is good with it. The problem is that where I currently work, my team isn't really into it, and aren't to keen on trying neither.

Since I haven't used it in a while, it feels to me as if I lost my unit testing mojo, and need to learn everything from scratch again.
At first, I though the best way to start is to actually write unit tests for projects I already wrote. This isn't TDD at all, but it's still something, and I feel as if I'm getting the "infrastructure" ready for the rest of the process...

Another thing I just thought about doing today was giving a lecture at work to my fellow team mates on unit testing, hoping that they will see the good side to it, and they'll want to know a little more on the subject!

Sometimes the best way to learn is by teaching! :)

I started building a demo project that I will show as part of a presentation i'm working on to go with my lecture. The project is just a simple calculator.

I am gathering all the points I need to discuss on this lecture, but trying to keep it simple and as convincing as possible to people who don't think it's useful or don't know what it is yet. Seems like quite a challenge, but I'm up for it!


So far this is what I got : (these are the points that are going into my presentation)

Let's say we're building a new class as part of a winform that does some calculation. How do we usually go about testing this ?
We would press f5 (debug) and play around with the UI a bit to see that everything's working...

Why is this bad ?
1. We have to do this again and again every time we change a little piece of code since we can't be sure it still works.
2. If someone else on the team changes our code, we'll need to run the tests again.
3. Someone might change a piece of code, play around with the UI and still not know about special corner-cases we were looking to handle in a specific way.
4. Time consuming!
5. In this case it's a winform and might be easy to test manually, but if we're just building a web service for example, I usually see people building these funny "tester" projects that they can send some sample input and see what happens.

Why does writing Unit Tests make life easier ?
1. By writing unit tests we are writing code that will check our functionality instead of doing it manually.
2. We can run the tests every change we make, and this will be much faster then manually testing.
3. If we write the tests properly and cover all the code we wrote, then someone else can change the code around or add some other functionality with the knowledge he didn't screw our code over!
4. Just by looking at the unit tests we can spot the corner-cases we should look out for.

What do we test and what not to test ?
1. Test all public methods in a class. If the tests are written good enough, then the private methods will be covered within these tests.
2. Make sure you're not writing tests to check the .net framework - this means you don't need to go crazy and start writing tests for each .net method!
3. Tests shouldn't need configuration. You should always be able to run the tests immediately. This means you need to avoid having your tests writing out to log files, db, network streams, etc. Instead, create mocks of these interfaces so they don't actually do this during testing.


Well, I feel like I'm new to this as well, so I'm looking for some feedback on these points I have for my presentation so far...
During the presentation I also want to show the simple demo test project I created, and how to write basic tests for it. I will show common cases when changing code can cause different behavior that might not be spotted at first by manually testing...

Seeya'...

P.S - Anyone interested in learning more about unit testing should check out these blogs : Ayende & Roy Osherove

Wednesday, July 27, 2011

Finding log4net hidden exceptions....


Recently I worked on a project that was mainly a couple of Web Services, and included a couple of more C# class libraries (e.g : a Data Access Layer, Common project with general utilities, etc..).

In the web services code, we had a lot of calls to our logging utility, which in this case used log4net. I had previous experience using log4net, so I knew (or thought i knew!) how to set it up quickly. I added what I needed in the web.config file, and thought it was enough.

Once I started testing the web services out, I realized that something was wrong with the log4net configuration. The problem was that it wasn't writing anything to any log file whatsoever. The bigger problem was that we didn't know why!?!...
log4net doesn't throw any exceptions if it doesn't work, and this way it doesn't interfere with your running application if, lets say, the log file it should write to has been deleted or is locked by another application for some reason...

However, log4net will write to a trace file, if you set one up...
This led me to the solution of my problem. All I did, was add a TextWriterTraceListener in my web.config, without even altering any code, and the log4net error was immediately written to my trace file.

In my case, I forgot to tell log4net to use Xml Configuration, but this is irrelevant. The point is that this might help you find out what your error is in the case of misconfiguration with log4net...

To set up a trace file through log4net, just add :

    
        
            
                
                
            
        
    

to your web.config file.

Trace listeners are a powerful tool when used wisely :)
You can read more about them here : MSDN - Trace Listeners

Happy Tracing...