Posts

Unit testing MonoRail controllers

I spent yesterday finishing off (mostly) my business model, then the end of yesterday + today writing test cases for those classes. Everything was going great, I found at least 3 errors in my code that I hadn’t realised was there and also realised there were a few more things I needed. Then it was time to start testing the controllers in my MonoRail site. What a disaster! Attempt 1: [Test] public void AdminOnly_Home() {   AdminController controller = new AdminController();   controller.Home();   Assert.IsTrue(Controller.Response.WasRedirected, "Should have been redirected"); } The problem with this was pretty obvious, Controller doesn’t have a Response etc set up. So along came attempt 2: [Test] public void AdminOnly_Home() {   AdminController controller = new AdminController();   PrepareController(controller);   controller.Home();   Assert.IsTrue(Controller.Response.WasRedirected, "Should have been redirected"); } Now the controller is set up with mock objects a

Validation

I have a model like so Product 1----* ProductVersion ProductVersion 1----* ProductEdition ProductVersion can been in one of two states: UnderDevelopment / Released ProductEdition has a DownloadUrl:string attribute which is only required if self.version.status = #Released The validation for ProductEdition works perfectly, I cannot leave the DownloadUrl blank if the ProductVersion has already been released. Unfortunately when I already have a number of ProductEdition instances with no DownloadUrl and then make my Productversion live the editions are not validated because they are not dirty. So I needed some way to ensure that when ProductVersion is validated all related ProductEdition instances are also validated. Step 01: Add a way to allow ProductVersion to identify other objects to be validated. In the business classes project I added the following interface. public interface IValidationExtender {   IEnumerable GetConstraintedObjects(); } My ProductVersion can do this IEnumerable

EcoRail

The whole idea of having a controller and a view is so that the view renders only exactly what it is given, and the controller is able to give it whatever data it likes from wherever it needs to obtain it. After working with ECO and Monorail for a while it has been a real pleasure, but I am starting to think that maybe exposing ECO objects directly to the view is not the right approach. If for example I put an Employee into the PropertyBag the view can easily display $Employee.Salary. This might not be a problem when you develop both the controllers and the view but in my case someone else will ultimately create the views. Do I really want them to be able to have access to this information? In addition, what if the view engine they use has a scripting language that is able to set values? Setting $Employee will merely set the PropertyBag["Employee"] value, but setting $Employee.Salary could see a certain view developer buying a new car next month. I am very tempted to chan

Your bug is my bug

I recently released an update to some software and a bug slipped through the net. It introduced some odd behaviour with a control named SmartGrid. After some testing I was able to determine that it wasn't my fault and that I could reproduce a bug in SmartGrid. I hate bugs in other people's source code, I can't fix it, I am at their complete mercy. Thankfully the Resco support was amazing! I posted on their forums and immediately someone sent me instructions on where to send my project. The next morning I was disappointed to see an email saying that the project worked fine. I posted again and almost immediately someone had offered to chat on skype. We did that for a while, both confused by the problem. We then went on to use Remote Assistance so that he could observe my bug which he wasn't experiencing. In the end the problem was very confusing. I had Version A of the DLL in which the error occurred. I upgraded to the latest version (B) and it still occurred. T

Converting a recurring decimal to a fraction

For a couple of hours a week I am doing a beginner's level maths course. The topic today was converting recurring decimals into fractions. For example (the [] are the repeating digits 0.[6]  1x = 0.[6] 10x = 6.[6] 9x = 10x - 1x 9x = 6.[6] - 0.[6] = 6 Therefore the answer is 6/9, or 2/3 When it got to numbers like 0.12[34] (ie 0.12343434343434.....) the lesson was really complicated, but I came up with a more simple approach, so here it is if ever you need it. My first observation was that we need a large number and a small number. So let's start with the 10x we used above  1x = 0.12[34] 10x = 1.2[34] therefore 9x = 10x - 1x which is  1.2[34] -0.12[34] This is going to give us 1.1(something) My second observation is that fractions cannot have decimal values in them. In order to get rid of the fraction we need the big number to have the exact same fraction as the small number. e.g.  B.[34] -S.[34] =X.[00] So our small number needs to end with [34]. Given the number 0.12[34]

MaxLength

Implementing HTML maxlength was a bit of a pain. Not to write the helpers though, that was easy.... $EcoModelHelper.AttributeLength($Product, "ID") But when it came to specifying that in the <input> it was too much work! This is how it is done statically... $FormHelper.TextFieldValue("Product.ID", $Product.ID, "%{maxlength='32'}") Now I had to replace the static 32 with the EcoModelHelper code. #set ($ProductIDLength = $EcoModelHelper.AttributeLength($Product, "ID")) $FormHelper.TextFieldValue("Product.ID", $Product.ID, "%{maxlength='$ProductIDLength'}") This was starting to look like too much typing! So instead I have decided to add new methods to the EcoFormHelper. Here is the first: $EcoFormHelper.ObjectTextField("Product.ID", $Product, "ID") This will output something like this <input type="text" id="Product_ID" name="Product.ID" value="Alt

EcoRail validation

Here is yesterday's update. I wanted a way to validate the user input. Seeing as there are constraints in the model to me this was the obvious approach to take. The HTML in my main layout (MasterPage) was changed like so <body>   #if ($Errors && $Errors.Count > 0)     <ul class="errors">       #foreach ($currentError in $Errors)         <li>$currentError</li>       #end     </ul>   #end   $childContent </body> This outputs all errors passed in PropertyBag["Errors"] or in my case I used Flash["Errors"]. To validate my product input I changed my controller like so: [AllowEcoSpaceDeactivateDirty(true)] public void Modify([EcoDataBind("Product", Allow = "ID,Name", NoObjectIdAction = ObjectIdAction.CreateNewInstance)]Product product) {   PropertyBag["Product"] = product;   IList<string> errors = GetErrorsForAllDirtyObjects();   if (errors.Count > 0)     Flash["Erro

Changing the URL structure

I wanted the following URL structure in my website www.mysite.com/product/myproductname/whatsnew but the default url mapping in MonoRail would translate this as www.mysite.com/[controller]/[action]/[id] So it would expect to find this public class ProductController {   public void MyProductName(string id)   {   } } whereas what I actually want is public class ProductController {   public void WhatsNew(string productName)   {   } } Open Web.Config Locate the monorail node Locate the routing child node Now add a new <rule> to the top of the list: <rule> <pattern>/(product)/(\w+)/(\w+)</pattern> <replace><![CDATA[ /product/$3.rails?productName=$2]]></replace> </rule> As this is at the top of the list it will have the highest priority. If the URL matches /product it will remap the url From: www.mysite.com/product/myproductname/whatsnew To: www.mysite.com/product/whatsnew.rails?productname=MyProductName without the user ever seein

ECO docs progress

I'm currently in the process of migrating the QuickStart series from BDS over to VS and recreating the accompanying source code. There's quite a lot of information in those articles, I hadn't realised how much I had written! Well, the transcription is going quite well. So far I have made it as far as article number 5. This one is going a bit slower because it is also a translation from VCL .NET to WinForms.

Inversion of control

As you may already know I am writing a website. I've chosen to use MonoRail for the web part and ECO for the persistence. Today has been great fun! I have modified the Castle.MonoRail.EcoSupport library with the following enhancements. You can now specify a [DefaultEcoSpaceType(typeof(MyEcoSpace))] on either the class or method. On the EcoDataBind reflection attribute you can now specify as little as [EcoDataBind("Product")] on your method parameter, this will use the specified DefaultEcoSpaceType specified, or throw an exception if no default was specified. This lets me write code like this [AllowEcoSpaceDeactivateDirty(true)] [UseEcoSpacePool(false)] [UseEcoSpaceSession(EcoSpaceStrategyHandler.SessionStateMode.Never)] public class ProductAdminController : BaseController {   public void Create()   {     PropertyBag["Product"] = new Product(GetEcoSpace<MyWebSiteEcoSpace>());     RenderView("Modify");   } } I can now easily create actions Creat

MonoRail

I'm working on a new website for work. I've decided to use ECO for the business model due to how much time it saves me. I took a look at the new MVC ASP approach provided by Microsoft recently and was a bit disappointed. There were bugs in some pretty basic errors that would have been an annoyance to code around, and it just didn't feel "ready". So, I've decided to take another look at MonoRail. I'd already written an ECO implementation for MR in the past but I decided to start the implementation from scratch. This was mainly inspired by the new EcoSpaceManager in ECOIV for ASP .NET. Using an EcoSpaceManager you can easily utilise many instances of different types of EcoSpace in the same page. I decided I would do the same. Unlike the EcoSpaceManager I haven't gone for unique string values for identifying the EcoSpace instance I want. That approach is good in ASP .NET where you want to bind different components together to generate your HTML bu

What's in a name?

When thinking of a name for a new product I wish people would be more original. For example, I have just spent ages looking for information about how to create a ternary in a scripting language known as Brail. Instead of finding what I want I have had to work my way through loads of information about blind people.

Single application instance

I needed my app to be a single-instance app. It was easy to implement, like so: bool mutexIsNew; Mutex mutex = new Mutex(true, "SomeUniqueID", out mutexIsNew); if (mutexIsNew) Application.Run(new MainForm()); A problem arose though when my app started to need to receive command line arguments. How do you also pass those onto the original app? There is a class for this purpose named "WindowsFormsApplicationBase", it's in Microsoft.VisualBasic.dll 01: Add a class to your project like so: internal class SingleInstanceApplication : WindowsFormsApplicationBase { private MainForm MainFormInstance; internal SingleInstanceApplication() { IsSingleInstance = true; EnableVisualStyles = true; MainFormInstance = new MainForm(); MainForm = MainFormInstance; } protected override bool OnStartup(StartupEventArgs eventArgs) { return base.OnStartup(eventArgs); MainFormInstance.AcceptCommandArguments(eventArgs.CommandLine); } protected o

ExternalID is not related to ECO_TYPE

I just thought I'd blog about this because it seems to be causing some confusion. ECO_TYPE Use: In integer used in the database to identify the type of object a table row represents. Obtained from: The ECO_TYPE table using the name of the class. Life span: Permanent. The name of the class in ECO_TYPE changes when you rename your class, but the integer value never changes. ExternalId Use: A way of identifying a class instance across EcoSpace instances. Kind of like a string version of a pointer to an object. Obtained from: Index of the class in TypeSystem.AllClasses + "!" + the ECO_ID of the instance. Life span: Although the ECO_ID never changes the class index might when you add or remove classes within the model. I just want to point out that ExternalID and ECO_TYPE are unrelated. When you change your model it does not mean that the ECO_TYPE in your DB must change. Here is an example 01: You create a model with 2 classes in it. The first class is the root, the next is a

Why I don't use ExternalID for URLs

An External ID consists of two parts, ! ClassID isn't really required for ECO controlled DB structures because there is always a root table containing the ObjectID + ClassID, but when you use ECO to map to an existing DB structure there needs to be a way to know that object 1234 needs to be fetched from the PERSON table. So, now that we know why the ExternalID consists of two parts on to why I don't use it (much). If I am writing a website with ECO and I use the ExternalID for my URL like so www.mysite.com/showarticle.aspx?id=23!1234 The number 23 is determined by looking for the class's index in the list of all classes in the model. This is the problem! If you change your model by adding a new class then your index may change from 23 to 24. Not a big problem for your application, but persistent links to that URL from other sites such as Google will no longer work. An ExternalID is just like an object's pointer address. When you restart your application that addre

RSA signed streams

I'm writing an app that needs me to be able to write to a file and make sure that nobody changes it. The idea that I had was to create 2 classes: WritableSignedStream: Accepts a targetStream parameter + a privateKeyXml string. I add some space at the beginning of the target stream to reserve it for header info. You then write to the stream as normal (it reports a smaller Length than that of the target stream so your app is unaware of the header). When you close the stream it writes the public key to the stream + an RSA encrypted hash of the data part of the file. ReadableSignedStream: Accepts a sourceStream parameter in the constructor. Just before you read for the first time it will compute an MD5 hash of the data part of the file, and then compare it with the signed hash in the file (which I first decrypt using the stored public key). These classes therefore provide two functions: You can sign a stream, the app can check the stream was signed by you by inspecting the public key w

No symbols loaded

This has been driving me mad for hours now! Whenever I run my PocketPC compact framework app I cannot debug it! None of the breakpoints will stop, each breakpoint just shows as an empty circle instead of a solid one. So, what was the solution? I tried deleting all PDB files on my hard disk but that didn't do it. In the end manually deleting all of the files previously deployed to my PPC did the trick. Maybe VS couldn't overwrite them or something? No idea, but at least it works now :-)

Geek quotes

This one is probably my favourite: "There are 10 types of people in the world, those who understand binary and those who don't". Here is one I came up with myself some years ago and used to use in my newsgroup signature: "Blessed are the geek, for they shall public class GeekEarth : Earth".

Derived properties that you don't want cached

I'm rewriting a Win32 application using ECO. One of the things this application allows the user to do is to specify their preferred unit of measurement for height, distance, depth, weight, and speed. To achieve this I have an ECO class ApplicationSettings which is a singleton which identifies the units to use. I then have 2 properties for each value.... InternalLandingDistance DisplayLandingDistance The idea is that I should never expose Internal* properties in the GUI but display their corresponding Display* property instead. The Display* property will read/write the Internal* property and perform some kind of conversion on it. If I always store my values using the unit with the highest accuracy (Distance = feet, Depth = millimetres, Weight = Pounds, Speed = KPH) then I just need to convert them by the correct factor when reading/writing from the Display* properties. This isn't rocket science, obviously I can just implement these as reverse derived attributes right? The pr

Mr thicko thicky thickpants

Well, I feel stupid. Worse than that, I generally feel very thick. Especially yesterday! So, what happened yesterday? I went to Bletchley Park . What a brilliant place! Walking around what was for approximately 50 years one of the biggest secrets of WWII was really quite strange. The stuff these people did was simply amazing! One guy managed to figure out the inner workings of a machine none of them had ever seen just by looking at two *almost* identical messages enciphered using the same machine configuration. The second message was 5 characters shorter than the first because the operator repeated the message but decided to abbreviate some of the words to save some time. This was all they needed. Not only was the functionality of the machine divined but what seems to be the world's first (semi) programmable computer was then designed + built to decipher messages received by wireless and then transcribed to punch holes. This thing has a optical reader that works at 5,

RetrieveChanges(out ignoredChanges)

Here's another quick blog about a new ECO IV feature. I asked for this during development because I had a particular problem I had to solve. My new application has a class named "PlannedCall". When the user logs in they see a list of planned calls that are A: Active B: Not already actioned C: Assigned to the current user, or not assigned to anyone D: EarliestCallTime <= Today + 1 As time goes on there will be a lot of instances of this class in my DB, so obviously I want to use the OclPSHandle to select my objects otherwise I will end up with a whole load of objects in memory that I do not need. However, when another user actions the planned call the Actioned property becomes true. If I use an ExpressionHandle then this planned call would disappear from the presented list, but with OclPSHandle it will not. This is where the new feature comes in! When you call PersistenceService.RetrieveChanges a collection of DBChange will be sent to the client from the server. T

ECO IV

CodeGear are letting some people blog about features in the next release of Delphi (Highlander) before it has even been released. How cool is that? A lot less secrecy, what a great move! Sooooo. How about I spill some beans about ECO IV? Maybe I can find a thing or two to mention :-) I'll just throw together something unplanned, so expect a weird mixture of stuff in no logical order whatsoever! Well, first of all , you're going to get a whole load of source code. I mean *lots* of it! There's a new service called the ICacheContentService . Let's say you know for a fact that there is an object in the DB with the ECO_ID 1234 and it is a Customer. Instead of loading that object into the cache with an OclPS evaluation you can simply use this service to register it in the cache. I've found this really useful in an app I am writing where I use SQL to find customers matching a certain sales criteria. I then create an IObjectList of these customers by injecting the

More secure passwords

Storing a plain-text password in a DB leaves your system open to abuse from anybody with access to the tables (sys admin for example). Here is the technique I recently used. Instead of storing the password itself I store a hash of the password, and a random "salt" that was used to create the hash to make it less predictable. [UmlTaggedValue("Eco.Length", "255")] private string PasswordHash { get { ... } set { ... } } [UmlTaggedValue("Eco.AllowNULL", "True")] [UmlTaggedValue("Eco.Length", "40")] private string PasswordSalt { get { ... } set { ... } } As you can see I do not store the password, just a hash + salt, both of which are private. Here are the methods used to set the values of these properties. public void SetPassword(string newPassword) { if (newPassword == null) throw new ArgumentNullException("password"); if (newPassword.Length < 6) throw new

Printing bitmaps using CPCL

I've had no end of grief trying to print a PCX to a Zebra Printer using the CPCL printer language. Silly me, didn't notice the EG command (expanded graphics) so there was no need to convert my BMP to a PCX and then struggle with binary data. I still had a bit of grief working out how to print using the EG command because the documentation is quite frankly crap. The expected command format is EG {WidthInBytes} {HeightInPixels} {XPos} {YPos} {Data}\r\n The printer expects a 1 bit pixel matrix. So if pixel(0, 0) is set you will set "80" in the data. If pixel(0, 0) is set and pixel (7, 0) is also set you would sent "81". Basically what you need to do is to read each set of 8 horizontal pixels and then use bit operations to create a byte value 0..255, and then output this as hex 00..FF. Here's the routine :-) public void DrawBitmap(Bitmap bmp, int xPosition, int yPosition) { if (bmp == null) throw new ArgumentNullException("bmp");

The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)

This new compile error was driving me mad! My project used to work, then I upgraded to a newer version of ECO. There were 3 projects using an EcoSpace, 2 would compile but not the 3rd. In the end the solution was simple but annoying to track down so I thought I'd mention it here just in case anyone ever strolls across it and finds it useful. In my licenses.licx files for the 2 projects I had the line Eco.Handles.DefaultEcoSpace, Eco.Handles but in the project that was failing somehow a strong name had been used, even though I originally entered it manually! Changing it back to the weak name fixed the problem.

Source control

At work we use SourceSafe for our version control, and I used SourceAnyWhere as the client. I would like to outline the facts and let you decide what happened for yourself. 01: I checked out my model (EcoModeler) 02: I added a new class. 03: Generated code. 04: Checked in the mode. 05: Checked out. 06: Added two new associations 07: Generated code. 08: Checked in. 09: Checked out. 10: Added a parameter to a method. 11: Changes a state machine diagram. 12: Checked in. After each of the changes I would implement code in my application that used them, so if the changes were lost at any point during this process then I would notice because my app would no longer compile. Today I checked out the model and noticed that my new class was missing. I backed up my generated source code and then regenerated code from the model. Using BeyondCompare I checked for differences and came up with the list of changes in the steps above. Somehow the model in my source control had 3 revisions missing. I

UndoBlocks, SyncServer, and multiple EcoSpaces

In an ECO app I am writing it is very important that updates by other users are identified as soon as possible. This is because there will be multiple users all selecting jobs to do from a predefined list, and it is not only possible but also very likely that more than one user will select the same job at the same time (the job at the top of the list). To implement this I chose to use the remote persistence feature of ECO and in particular its Sync Server feature. Every 5 seconds my client apps will contact the server and retrieve a list of updates made by other users, it will then apply those updates to the cache of its own EcoSpace. So when a user selects a job to do at the top of the list their app will stamp it as InProgress and update the DB, the job will then automatically disappear from the screens of all other users. As I like to use undo blocks in my app to allow the user to cancel changes (using my DirtyObjectCatcher component) it is highly likely that during these synchro

CapableObjects announced

There are exciting times ahead! The team that brought you ECO for Delphi are now a separate company named Capable Objects ( http://www.capableobjects.com ). ECO will still be part of the next release of Delphi, but according to the official statement ( http://dn.codegear.com/article/3673> ) and comments in the newsgroups it is quite obvious there will also be a version of ECO for Visual Studio! In the past the ECO guys released patches for ECO bugs, unfortunately it was not always possible to provide a patch. With the guys now being a separate company they are free to decide their own release schedules. Instead of having to wait for a Delphi update they can now release updates as often as they wish. Just like the good old BoldSoft days when we used to get an official update really quickly if ever a critical bug was found. Not only that, but it would also seem that they will be shipping source code too! But that's not all John! The guys at Capable Objects have asked me to wr

I've changed my mind on MonoRail

It is amazing! I'll leave that previous post just in case anyone ever needs to create an ECO object instance first and then connect it with an EcoSpace afterwards, but you don't need it for MonoRail! public void Join([EcoDataBind("User")]User user) { PropertyBag["User"] = user; if (this.Params["User.FirstName"] != null) { GetErrors(user.AsIObject(), Errors); if (Context.Params["ConfirmEmailAddress"] != user.EmailAddress) Errors.Add("Email address confirmation does not match email address."); if (Errors.Count == 0) { //TODO EcoSpace.UpdateDatabase(); Redirect("Account", "Home"); }//No errors } } That's all there is to it now! I have created a small set of classes to enable ECO support in MonoRail. Instead of descending your controllers from SmartDispatcherController you will now descend from EcoSmartDispatcherController . This gives the following abi

MonoRails, loving it

So I didn't like Ruby on Rails much. More accurately I didn't like the Ruby language or ActiveRecord much, but the "Rails" part I really quite liked! So my investigation continues and I have found myself looking at MonoRails. MonoRails is what I would have as a child called "a rip off", but these days it is known as a "clone" :-) It's basically a .NET version of Rails, which obviously appeals to me because I liked the Model-View-Controller approach of Rails and I obviously like C#. MonoRails has its own version of ActiveRecord (which I shall be avoiding) and an interface into NHibernate too (which I haven't looked at in great depth, but it certainly doesn't look as powerful as ECO). So I have been trying to get MonoRails working with ECO instead. Considering I don't know MonoRails at all I am surprised at how quickly I managed to do what I wanted. Take the following controller method as an example, when the user visits localho

Quantum bugs

I've just been driven mad by a "Quantum bug". What is a quantum bug? Well, it's a bug that doesn't exist unless you look at it :-) I kept getting a NullReferenceException in my code. It happened whenever I changed a property of a class. I assumed it was something in the framework, but it was in fact in a library of my own. When the property changed it would trigger an observer I had attached, the purpose of this observer is to check if the form that owns my component is the active form, if it is then it records the object that changed; the purpose is to know which objects were modified by which form. Anyway, to check if the form is active I do this Form activeForm = System.Windows.Forms.Form.ActiveForm; Form activeMdiChildForm = activeForm.ActiveMdiChild; if (activeForm == this.Form || activeMdiChildForm == this.Form) ..... Now the quantum! If you are debugging your app Form.ActiveForm will always return null! How useful is that eh? :-) So, when debugging

Cocoa, falling at the first hurdle?

I was REALLY looking forward to programming some apps on the Mac using Cocoa and objective-C. I am reading "Cocoa programming for MAC OS X" by Aaron Hillegas. I had read as far as page 30 when I saw the following: "Objective-C is a very simple language. It has no visibility specifiers: All methods are public; and all instance variables are protected. (Actually, there are instance specifiers for instance variables, but they are rarely used. The default is protected, and that works nicely.)" WHAT? Works nicely? I disagree! It is actually possible to make a class's method private by not including it in the interface declaration (myclass.h) and just adding the implementation file instead, but what about protected methods? public I expose as little as needed to ensure the class provides the service it was designed to. The signatures/names of members in my public area change as little as possible so as not to break other people's code. Public members are

Enough rails for me

That's it, I've had enough of Ruby on Rails! I like the rails part, it's a very clever approach, but I really dislike the Ruby part! The final straw occurred yesterday. It's very common in OOP to have the constructor set default values for your object just in case the consumer of your class does not set them. In C# I would do something like this..... public class Post : MyBaseClass { private bool isPost = true; } In Ruby I was trying to achieve this simple behaviour... 01: IsPost is set to true 02: A form is displayed with the default value 03: User changes the value 04: My Post instance is updated with the values from the form I tried to override Initialize() only. def Initialize super is_post = true end Now Post.new(params[:post]) is not reachable for some reason. So in my Post class I did this def Initialize(* params) super(params) is_post = true end The problem here is when I try to initialize the values from the form in my controller class. post = Pos

Installing Rails on a Mac

What a lot of grief! After trying more simple steps on another site (and failing) I eventually managed to get the following steps to work: http://hivelogic.com/narrative/articles/ruby-rails-mongrel-mysql-osx There were however some changes: 01: Make sure you download TextMate. I kept reading it as TextEdit for some reason, so just be aware of that when "mate ~/.bash_login" wont work. 02: One of the steps tells you to type "make ~/.bash_login". I found that adding the suggested text to that file made no difference when you log out/in or close the Terminal window. This was because a file named "~/.bash_profile" existed. If this file exists then you should modify it instead of the one mentioned in the article. 03: When trying to do "rake db:migrate" I would experience the following error: otherwise you will experience the following error: dyld: NSLinkModule() error dyld: Library not loaded: /usr/local/mysql/lib/mysql/libmysqlclient.15.dylib Re

Convert absolute path to relative path

Today I needed to convert an absolute path to a relative path based on a specified base path. E.g. c:\a\b\c -> c:\a\b\c\d\file.txt = d\file.txt c:\a\b\c -> c:\a\file.txt = ..\..\file.txt c:\a\b\c -> c:\a\x\file.txt = ..\..\x\file.txt I am surprised there is nothing in the .NET framework so I had a hunt around and converted the code from the following URL ( http://www.vergentsoftware.com/blogs/ckinsman/default.aspx?date=2006-08-07 ) into C#.... private string RelativePath(string absolutePath, string relativeTo) { string[] absoluteDirectories = absolutePath.Split('\\'); string[] relativeDirectories = relativeTo.Split('\\'); //Get the shortest of the two paths int length = absoluteDirectories.Length < relativeDirectories.Length ? absoluteDirectories.Length : relativeDirectories.Length; //Use to determine where in the loop we exited int lastCommonRoot = -1; int i

Acer Skoda - I mean Ferrari

I have owned an Acer Ferrari now for approximately 13 months. Previously I had a problem with it freezing randomly. I spent some time trying to reproduce the problem and after a month or two was finally able to reproduce it 100% of the time. I sent my laptop back to Acer armed with exact steps and as a result my laptop was returned to me after only a couple of days. For the past 2-3 months I have been seeing very rare, random resets. Obviously I blamed Windows, as you do :-) Some software I had to convert AVI to MPEG would always reset the laptop, but I just put that down to dodgy software. More recently I noticed that 7-zip would also reset my laptop *only* if I used ULTRA compression on a file larger than 500MB. So I tried Winzip, same problem. I installed Vista and tried both Winzip and 7-zip in there, same problem. With steps to reproduce + proof that it was not the OS I felt I could finally send the laptop back for repair without running the risk of it coming back "No