DCSIMG
YsA.Net

Let’s say we have a web application which makes calls to other services via http. We want to inspect the calls for bug hunting.

If the calls where made from the browser on the client side then it is simple – use fiddler in order to inspect and analyze the calls.

If you try to do the same with calls made from IIS, you will see nothing by default. Why?

Fiddler is a proxy server for your calls. When you open it it creates a simple listener on 127.0.0.1:8888 and listens for calls. It also registers it self in the registry under HKCU so all calls from processes of the current user are first redirected to fiddler’s address.

You see where I getting at?

IIS runs under a different user and as windows service, so the calls are not redirected to fiddler.

The most simple solution for this problem is to configure your app to use a proxy for it’s calls in the web.config file:

   1: <system.net>
   2:       <defaultProxy>
   3:              <proxy usesystemdefault="False" proxyaddress="http://127.0.0.1:8888" />
   4:       </defaultProxy>
   5: </system.net>

This configuration make all the external calls IIS makes to fiddler. Just make sure that fiddler is running when this configuration is set – if not your site will not work…

You can read more about it here.

In my last post (which was way too long ago), I've wrote what is my ideal workplace. After a while I found it!

After a series of interviews I was hired by Sears Israel as a software developer for Sears Social.

Sears Social is a new social experience which creates a new shopping experience using your social connections.

After only a couple of months, I have to tell you – I made the right choice. This place is amazing! Great professional people, Agile practices and great atmosphere.

It was pretty amazing for me to see first hand how to practice continues deployment, informative DSM with 25 participants which takes less then 10 minutes and a great bunch of people which makes you smile when you go to the office in the morning and even a bigger smile when you leave in the evening.

So stay tuned…

with no comments

In a month I will be leaving my current position in my company. After six and so years it is time to move on.

In the last couple of months I've been thinking about where I would like to work – what is the ideal workplace for me?

  • Experienced and talented people from whom I can learn
  • An interesting an compelling product – I think it is very important to believe I what you do.
  • Agile environment, a team and management which believes in the agile process
  • A place where I can have fun doing what I love – writing lots of code

If you are looking for a developer who loves the job and wants to write great code, and you are in Israel , you can contact me and I will send you my CV.

Consider the following problem:

We have a web app which can send messages between the users that are connected to it. A user can send a message to any number of users.

The implementation is simple:

  • When a user sends a message:
    • The message is saved in the database
    • Cache value is inserted for each recipient. The saved value is a time stamp which indicates when the user last received a message.
  • Users that are suppose to see the message:
    • The client is polling the server and asks if the server has new messages. It does that with an initial time which is loaded when the page is loaded and saved in JavaScript.
    • If there is something new the client asks the server for the new messages (according to saved time) and the server returns the messages from the database and the last received time from the cache.
    • Client time stamp is updated with the received time and continues polling

Pretty simple…

Unfortunately the implementation has a critical bug which causes clients to lose messages.

Consider this code:

using (var t = OpenTransaction())
{
    SaveMessageToDb(message);
    
    foreach(var user in message.Recipients)
    {
        Cache[user.Code] = message.SendDate;
    }
    
    t.Commit();
}

Can you spot the bug?

Let say we have 1000 users that will receive the message. After saving the message to the db the code updates the cache for each client. Each client polls the server at a constant interval. Let say that user AAA polls the server – his cache key is updated but the loop that updates the cache is not yet over. The user send a request to get the new messages but because the transaction wasn't committed so the new messages will not be returned from a query – the loop that updates the cache is still going. The client then updates the last received time – and so the user will never get the message.

I must say that this was a very frustrating bug…

The solution was composed with changes in both the client and the server:

Client:

We changed the client script so that if the server claims that there are new messages but the clients receives an empty list of messages then the received time is not updated and another request is sent to the server until new messages are received.

Server:

What we need to do here is to make the cache join the transaction. In this case we couldn't because the transaction was a local oracle transaction – not a distributed transaction. If it was we could use System.Transactions to implement a transactional cache.

In this case we used an event which is triggered when the transaction is commited (in TransactionScope there is the AfterCommit event, in our case we had to implement this ourselves). It looks something like this:

using (var t = OpenTransaction())
{
    SaveMessageToDb(message);
    
    t.AfterCommit = (sender,e) => 
                    {
                        foreach(var user in message.Recipients)
                        {
                            Cache[user.Code] = message.SendDate;
                        }
                    }
    
    t.Commit();
}

Way not simply update the cache outside the transaction?

Because we don't actually know when the transaction is committed. Maybe another method calls this method with a transaction of her own and the commit is actually done there (the OpenTransaction method actually returns a current transaction if one exists already).

Important:

Our solution was infect a little more complex because we wanted other modules that are in the transaction to be able to get the updated value from the cache even if the transaction wasn't committed yet:

using (var t = OpenTransaction())
{
    SaveMessageToDb(message);
    
    t.AfterCommit = (sender,e) => 
                    {
                        foreach(var user in message.Recipients)
                        {
                            Cache[user.Code] = message.SendDate;
                        }
                    }
                    
    DoSomthingThatUsesCache();
    
    t.Commit();
}

So we created a class which wraps the cache, and contains a local dictionary which contains updated values, and access them when needed. If a value is updated in a transaction then wrapper registered to the event and updates the real cache when the transaction is committed. We called the class TransactiveCache:

using (var t = OpenTransaction())
{
    SaveMessageToDb(message);
    
    foreach(var user in message.Recipients)
    {
        TransactiveCache[user.Code] = message.SendDate;
    }    
                    
    DoSomthingThatUsesCache();
    
    t.Commit();
}

In our app, we needed to create a selection list for an input field. The obvious solution is to use a ListBox. But we wanted the ListBox to be horizontal, like this:

image

The solution:

<ListBox Grid.Row="0" ItemsSource="{Binding Types}" SelectedItem="{Binding SelectedType,Mode=TwoWay}" ItemTemplate="{StaticResource MyTemplate}">
    <ListBox.ItemsPanel>
        <ItemsPanelTemplate>
            <StackPanel Orientation="Horizontal"/>
        </ItemsPanelTemplate>
    </ListBox.ItemsPanel>
</ListBox>

ItemsPanel is the panel in which the items are rendered. When you set it's template to a StackPanel with horizontal orientation the items are rendered according to the layout of the StackPanel container instead of the default ListBox layout.

In order to change the design of the items I used a simple DataTemplate and set it to the ItemTemplate property of the list.

But how to change the color of the selected item? that's on the next post…

with 3 comment(s)
תגים:,

My computer is set to use automatic updates from Windows Update. So when SP1 for Windows 7 came out, I didn't even think about installing it… Windows Update will take care of it for me. But sadly I was mistaking.

After two months I realized that the service pack had not been installed. So I downloaded the service pack from Microsoft Download Center, and tried to install it. But I got an error: "the update is not applicable to your computer".

Googling around, I found that I needed some updates I needed before installing the service pack. I checked Windows Update and indeed the updates were missing. When I checked for updates Windows Update stated that my computer is up to date. Weird. But I didn't gave up… Found the updates from the download center and ran them – but with the same error.

In the event viewer under Setup log I found this error: "Windows update  could not be installed because of error 2149842967". Googling it results to nothing. in the System log I found this error: "The TrustedInstaller service failed to start due to the following error: The system cannot find the file specified.". The weirdness keep on going…

TrustedInstaller is infect a service called "Windows Modules Installer" which is responsible for various processes in the operating system. One of them is Windows Update installations and Windows features installations. Checking the services I so that the WMI service has gone missing. I also tried to open the Windows Features (turn Windows Features on or off in Programs or Features from the Control Panel), but it came out empty. I also checked if the TrustedInstaller.exe exists in c:\windows\servicing folder, but the file wasn't there.

I searched how to recover the service, but the best answer I found was to format and reinstall windows. Eventually I found a similar problem in the Windows Vista forums which offered this solution:

  1. Take the TrustedInstaller.exe from another computer. WATCH OUT: if you have 64 bit version make sure you take the file from a computer with the same version and vice versa. It is not possible to copy the file directly to the c:\windows\servicing folder due to security issues, but it is possible using an installation disk of your Windows 7
  2. Put the file in a temporary folder on your computer
  3. Boot the computer with your Windows 7 installation disk
  4. Click Next in the language selection screen
  5. DO NOT click Install now. Click on repair installation
  6. Select the installation and click next
  7. Select the Command Prompt option
  8. copy the TrustedInstaller.exe to c:\windows\servicing
  9. Exit and restart the computer normally
  10. Run Command Prompt as Administrator (type cmd in the start menu –> right click on cmd.exe –> Run as administrator –> Ok)
  11. type: cd\windows\servicing
  12. type: TrustedInstaller.exe
  13. After it finish running go to the services screen (type services.msc and enter)
  14. Find a service called "Windows Modules Installer"
  15. Right click –> Start
  16. From the command prompt type: SFC /scannow
  17. If no issues are found, restart and check for updates in Windows Update

After I did all that I found out that I had about 50 updates to install before installing Service Pack 1. I installed all of them and the service pack.

The lesson: Everybody lies – even Windows Update

A couple of months ago, I needed to use a laptop of one of my co-workers. When I opened the computer I was baffled by the behavior of the mouse pad. Apparently the mouse direction were inverted – when you go up, the cursor moved down. When you go left the cursor moved right. When I asked him what happened he said there is a malfunction in the pad and he doesn't have time to fix, so instead of fixing it he just got used to it…

How many times you heard a programmer in your team cries out to the havens about some ugly UI/code/design? What happens usually? Nothing! the code/UI/design stays the same and the next programmer who bumps this will again cry out, complain and do nothing.

Complaining is actually dropping the blame/responsibility to fix it to someone else, which makes you feel good to forget about it. It is used as venting for the developer so he can move on.

This is a bad habit in any team – When something seams wrong – it should be fixed. When these things are not fixed, no one wants to touch them, and the circle continues until there is someone brave enough to break the chain.

This type of behavior also manifests when doing manual testing of the app the team develops. Because of the fear to find bugs or to see things that aren't working, team members treat the application very gently.

My former team leader, noticing this behavior, made a list in our team portal call "annoying things to fix". He told us to enter anything we think needs to be fixed so we can map these kind of things and fix them one sprint at a time. After a couple of sprints we actually ran out of thing to fix including some big design issues. Other thing simply entered the dev cycle as a User Story to be fixed later.

On my team I encourage the developers from the training stage to look on every mission, every line of code, every design decision critically. To fix these thing or at least report them, insert the fix as a task or a user story for the next sprint. When they are supporting user trouble, to look at the system, and don't assume that everything works. To try to find the underlying problem and not accept that it happens.

I want the developer at a system, to map what's wrong and try to fix it. This raises the developers to a whole new level in which they do not complain anymore, they are not afraid to maintain legacy code. They can analyze a feature and tell you what needs to be done to fix it.

When the developers learn to change the ignoring instinct within him, the atmosphere in team is better – atmosphere that encourage healthy criticism, cleaner code and clean air without complaints. 

Last week I was passing in the hallways and I heard an annoying scratching sound. I followed that noise into the office of my department head. I saw him there with another team leader trying to draw a sketch of some sort with a white board marker that barely working. I walked back to my office, took a marker,  returned to my department head, gave him the marker, took the old one and throw it to the trash. On my way out I said to him: "don't adopt the symptom".

Today I'm hosting a post from Leeran Yarhi, one of the developers in my team:

Hi guys,

I’m Leeran Yarhi, a developer in Yossi’s team.

Recently we had a problem while mapping one of our domain entities with Fluent NHibernate. We upgraded our app to use NHibernate 3 in conjunction with Fluent NHibernate 1.2. When we did that, some of our tests failed.

For example, let’s have a look at this entity:

public class User
{
    public virtual int Id { get; set; }
    public virtual string FirstName { get; set; }
    public virtual string LastName { get; set; }
    public virtual string FullName { get; private set; }
}

And it’s mapping:

public class UserMap : ClassMap<User>
{
   public UserMap()
   {
       Id(x => x.Id);
       Map(x => x.FirstName);
       Map(x => x.LastName);
       Map(x => x.FullName).Formula("first_name || ' ' || last_name");
   }
}
 

As you can see, User has a property named FullName, which is actually a concatenation of FirstName and LastName. Of course I don’t really want to map this property to our Database. This is why I’m defining it a Formula, so that my Users table won’t really have a column for FullName

All good, but the problem starts when I try to use this PropertyConvention :

public class PropertyUnderscoreConvention : IPropertyConvention
{
    public void Apply(IPropertyInstance instance)
    {
        instance.Column(Inflector.Underscore(instance.Property.Name));
    }
}

NHibernate will throw an exception because it’s trying to give a name to a column that doesn’t exist. The solution for this problem is to somehow define to my convention when it should apply, or in other words – Acceptance Criteria.

Fluent NHibernate gives us an API for defining the criteria that a mapping must satisfy for a convention to be applied to it. Exactly what I need.

The Convention class will now implement another interface: IAcceptanceCriteria<TInspector> , which contains the method Accept. This method defines the above criteria.

Let’s see some code, this is how my new convention looks like:

public interface IPropertyConventionAcceptance : IConventionAcceptance<IPropertyInspector>    
{
}     
 
public class PropertyConvention : IPropertyConvention, IPropertyConventionAcceptance
{
    public void Apply(IPropertyInstance instance)
    {
        instance.Column(Inflector.Underscore(instance.Property.Name));
    }
 
    public void Accept(IAcceptanceCriteria<IPropertyInspector> criteria)
    {
        criteria.Expect(x => x.Formula == null);
    }
}
Now, my criteria will be applied only on properties that doesn’t have Formula, and all the mapping will work fine.

My team is working on a Silverlight project for the last three months. One of the first issues we encountered was unit testing for the Silverlight libraries.

Unfortunately, this issue is not trivial. Current dev tools, including the VSTS do not support running tests in the traditional way. In order for a Silverlight test to run, it needed to be hosted inside a web page. This is quite problematic when trying to practice TDD and even running the tests on your CI server.

Let's start at the beginning:

The Silverlight Sdk (aka Silverlight tools), contains a project type for Silverlight tests. Simply click New –> Project –> Silverlight and select Silverlight Unit testing Application:

image

As I mentioned before, Silverlight unit tests can only be run under a host web site, so after creating the project, Visual Studio will ask you to create a web site to host the tests.

In the unit testing project, a class will be created with the familiar VSTS test class:

[TestClass]
public class Tests
{
    [TestMethod]
    public void TestMethod1()
    {
        var c = new Class1();
 
        var result = c.Test();
 
        Assert.IsTrue(result);
    }
}

To run the tests, simply run the default page in the web site that was created. A browser will be opened with a Silverlight page which runs the tests in the test project:

image

If you look closely at the Silverlight test project, you will see that this is a simple Silverlight app project. The output of the project is a xap file which contains all the test classes. The project contains a App.xaml file. In the startup event you can see the following code:

private void Application_Startup(object sender, StartupEventArgs e)
{ 
    RootVisual = UnitTestSystem.CreateTestPage();
}

This is actually the creation of the page which runs the tests and displays the results.

Although this is very nice implementation, it doesn't helps us when we are trying to develop in TDD. In order to do that we would like a tool which runs the the inside VS.

AgUnit is a very cool tools which enables us to run tests with Resharper test runner. In order to install it, simply extract the files from the download into C:\Program Files (x86)\JetBrains\ReSharper\v5.0\Bin\Plugins, and you can run the tests with Resharper:

image

This plugin simply simulates a web page and hosts inside the runner process of Resharper the xap file from the test project and runs it's tests. So, at this stage, you can delete the web site you created…

Tip: notice the prerequisites of the tool. In short, you need to add reference to System.Xml.Linq.

The next step, is to run the tests in the build server. For this we will need to find a tool which can host a Silverlight app. One tool that can do this is StatLight (why didn't they call it StarLight?). This is a command line tool which can be used to run a Silverlight testing project on the dev machine and in a TeamCity build server or using MSBuild:

image

This tool also allows you to TDD, using the –c option. This option will run the tests in the command line and listen to the build of the xap file of the test project. If the xap file will be rebuilt, then it will run the tests again. This is pretty useful and efficient when doing Tdd.

 

After we dealt with CI, lets make our programming experience more familiar. What if we want to use NUnit? mocking?

Well, Rhino.Mocks has a version compiled for Silverlight (from 3.5 version). Just reference the dll and mock away.

NUnit also has a version for Silverlight. But in order to use it, you'll need to change the App.xaml to use NUnit for the runner. Remember the Application_Start event? This is the initialization of the runner. Microsoft is using a provider model to this framework which enables third party unit testing frameworks to inject there own runner. Add references to all three dlls from the NUnit site, and then simply add this code in the event:

private void Application_Startup(object sender, StartupEventArgs e)
{
    UnitTestSystem.RegisterUnitTestProvider(new Microsoft.Silverlight.Testing.UnitTesting.Metadata.NUnit.NUnitProvider() );
 
    RootVisual = UnitTestSystem.CreateTestPage();
}

Change the test code to the standard NUnit syntax:

[TestFixture]
public class Tests
{
    [Test]
    public void TestMethod1()
    {
        var c = new Class1();
 
        var result = c.Test();
 
        Assert.IsTrue(result);
    }
}
And run the tests

 

That's about all I could find… Do you have more tips on doing testing in Silverlight?

I'm using live writer since it's beta releases. I currently write in two blogs – technical blog – in English, and a cooking blog in Hebrew. One of the biggest pains in WLW was that the spell check dictionary was installed according to the installed language of Windows Live Essentials. That means that if you downloaded the English version of WLW, you had only the English dictionary. A problem for someone that writes in different languages.

Today I found the solution to this problem, which was ridiculously simple:

  • Go to the control panel and click "Clock, Languages, and Region":

image

  • If you installed one of the Windows Live Essentials apps you can see "Windows Live Language Settings":

image

  • Next, you will see the installed language of WLE:

image

  • You can change the language to the one you want to install. An internet connection is needed to download the settings. This will add the dictionaries but also change the UI to the selected language. So if you want to change the UI back, after the installation is complete simply return the setting back to the desired language. Don't worry… the dictionaries will not be erased.

image

 

  • In WLW go to options –> Spelling, and change the dictionary to the desired one.

image

 

That's about it.

Notice that unfortunately for now, you can not have two dictionaries working simultaneous, so you need to switch the dictionary manually when you need it.

Lately I notice that every time I insert a DoK or a disk, the AutoPlay/autorun doesn't appear. I also notice that when I click on the disk drive in My Computer window, I will get directed to the explorer view of the disk and the autorun doesn't engaged. It is especially annoying when I insert a disk for some installation and I have to search for the setup.exe file…

After googling for a while I found this article:

Fix Windows 7 AutoPlay Dialog Box Missing or Not Appear, Display and Pop Up

Apparently, some programs you install decides to disable the autoplay option. VMWare was the cause in my computer.

After running all the steps described in the article, all came back to normal…

About two months ago, we upgraded our projects to Visual Studio 2010. Since then the developers started to complain that the performance of the IDE has degraded in comparison to VS2008. From build times that doubled to stalling in the editor when you code. Other teams in our department started to complain as well.

So we started to find the problem. We investigated three direction:

  • Solution maintenance
  • Visual studio
  • Hardware

 Solution maintenance:

This is a key issue. In my previous experience we found that solutions that are not maintained properly are doomed to cause trouble.

This relates mostly to build time, but it can also effect the IDE because, as you know, visual studio and add-ins like resharper are constantly compiling your new code in the background.

I started by changing the build output verbosity:

image

 

. I also found that the resolving references stage is quite long and I have to many projects with unneeded references. So the conclusions are:

  • Minimize the number of projects in the solution: I found that each project builds in about 2-4 seconds (Silverlight project takes about 9 seconds), but the transition between the projects takes a lot of time. When you have a large number of projects, this has a drastic effect on the build time. So try to merge projects. For example: projects that have a few classes and use folders and namespaces. Merge all the integration tests into one projects (also make it easy to manage the integration tests in the CI server).
  • Remove redundant references from projects: I also found that the resolving references stage is quite long and I have to many projects with unneeded references. I used resharper in order to find dependent code in a project and deleted the references which didn’t have dependent code.
  • Do not build setup/deploy projects in debug mode: Setup projects and web deployment projects takes a long time to build. Make sure that in debug build configuration (Build –> Build Configurations) setup and web deployment projects are not marked for build.

Visual Studio:

I recommend to all of you to subscribe to the Visual Studio blog or to Scott Guthrie’s blog for the latest’s updates to visual studio.

  • Windows Automation UI: Another important issue is Window Automation UI. Microsoft recommend to install it if you are running on windows xp. You also could notice the visual studio icon that appears on your system tray, which shows this recommendation. In short, when installed it is suppose to make visual studio to run faster
  • Diagnostics:  Our contact in Microsoft support, recommended us to install the Visual Studio Diagnostics Tool. This tool is used for collecting trace information on visual studio performance. This logs can be analyzed independently or can be sent to Microsoft Support. I haven't had a chance to install it yet. I will update on this soon.
  • Add-ins and extensions: As you probably know, visual studio 2010 with the Visual Studio Gallery allows you to install a lot of add ins and extensions to visual studio. In lot of cases one or more of these can have drastic effect on performance. It is recommended to run Visual Studio in safe mode by running with with the safe mode switch:
   1: devenv /safemode

 

Then you can see any performance improvement. If so, try to activate the add ins and extensions one by one and diagnose which one causes the performance impact.

Hardware:

  • Defragmentation:  fragmented disk cause slower build times (which as mentioned can also effect IDE general performance). In my team, we found that the image which is used to install windows on the dev machines was seriously fragmented.  After defrag build time decreased by half!! It is a know windows performance issue, so every once in a while remember to do a scan disk and defrag your drives.
  • Maintain your machine: Cleanup your machine every once in a while. I use CCleaner to clean up the drives and registry and it works great.
  • DirectX: There are some articles on the web which indicates that visual studio doesn’t run well on machines without a graphic card that supports DirectX 9. This is due to the new UI which is build on WPF. Our dev machines doesn’t have graphic card slots so I couldn’t check it. If you have a chance, I recommend you try, and comment on your results. In my home computer which have a pretty massive graphic card Visual Studio works well, but I don’t have solutions with 30+ projects…
  • Hardware acceleration: Visual Studio uses hardware accelerations (as mentioned). You can try to disable it, for better performance:

image

Our machines doesn’t have graphic acceleration, so we tried this and performance got better, most of the times.

If you have any more tips and tricks about this issue, please share it with us.

Hope this helps

In Asp.Net 4 the request validation model has changed (Yet another breaking change). In short, request validation is a security feature of Asp.Net which meant to prevent a user from XSS or script injection attacks. In Asp.Net the behavior of request validation has changed.  Validation of the input is know performed in the BeginRequest stage in the life-cycle .

When we converted out web application to Asp.Net 4, we found out that one of our pages, which uses a control call FreeTextBox, threw a validation exception each time an input was typed and submitted in that control.

FreeTextBox control is used to allow users to create composite text which can be displayed in html – features like font sizes/types, bold, alignment etc… The control actually creates html from the user input and commands.

Asp.Net 4 interprets the generated input from the control as a XSS attack and prevents the page from running.

Doron posted on this subject, but in Asp.Net 4 there is no page directive for the mode of the request validation.

The immediate solution was to change the request validation model to run in Asp.Net 2.0 runtime. The change is quite simple. Simply add the following line to the web.config, under the system.web node:

   1: <httpRuntime requestValidationMode="2.0" />

If your page is in a folder you can create a web.config file their and put this line so the request validation in 2.0 mode will work only on the pages in that folder (so the other pages in the app can use the 4.0 mode).

In the long run we plan to upgrade the control (which is pretty old) to a newer version (impossible now due to an upgrade to the FreeTextBox site) or to replace it with RadEditor control from the RadControls suite, which from initial tests doesn’t have this problem.

More on that soon…

Last week I found out that one of our admin apps on the server was not installed currently. It is an app that is installed in ArcMap, and the reason it didn’t work is that ArcMap has been installed on “d:\programs files” instead of “c:\program files”. The msi depended on the location in c:\.

I opened the solution to try to fix the installer. I found out that when you install ArcDesktop it adds an environment variable named “ARCGISHOME”. I also found out it is impossible to take a dll from a primary output in an msi and order the msi to put it in another folder.

So I used a custom action in the install phase with a VBScript file.  In order to do that you need to:

  1. File –> New –> Text File
  2. Save the text file with .vbs suffix under the setup project folder in the file system
  3. Right click on the setup project is VS –> View –> Custom Actions
  4. Right click on Install –> Add Custom Action
  5. Select the vbs file
  6. OK

Open the vbs file and write the following script:

To copy the files I needed I used:

   1: Set wsShell = WScript.CreateObject("WScript.Shell")
   2:  
   3: Dim targetDir = Session.Property("CustomActionData")
   4:  
   5: RunScript = "xcopy """ + targetDir + "\somefiles"" ""%ARCGISHOME%bin"""
   6: wshell.run RunScript

In the vbs file properties under “Custom Action Data” enter “[TARGETDIR]” – This tells the msi to set the CustomActionData property the the folder in which the msi deploys it’s main files.

If you run this script under an msi you will see it does not work…

After of couple of frustrating  debug trials, I found out that under an msi host, a VBScript can not used environment variables. In order to use environment variables we can use the WScript method called ExpandEnvironmentStrings .

So know the script will be:

   1: Set wsShell = WScript.CreateObject("WScript.Shell")
   2: Dim targetDir = Session.Property("CustomActionData")
   3:  
   4: arcGisHomeDir = wsShell.ExpandEnvironmentStrings("%ARCGISHOME%")
   5:  
   6: RunScript = "xcopy """ + targetDir + "\somefiles"" """ + arcGisHomeDir + "bin"""
   7:  
   8: wshell.run RunScript

This one works perfectly.

Use it wisely

You’ve upgraded your project to Visual Studio 2010 and .Net framework 4. Good for you! But when you checked in the projects and the build in TeamCity starts to run – alas – Build failed!

In order to run an upgraded project in VS2010 follow these steps:

  1. Make sure your TeamCity server can run VS2010 solutions (version 5 and up of TC).
  2. Install Visual Studio 2010 and .Net framework 4 on your server.
  3. If your project is a web project which uses Web Deployment Project, install web deployment project for VS 2010 on the server.
  4. Now you need to configure TeamCity to run your project in VS2010:
    • Enter your TeamCity web access
    • Click “Administration” button
    • Click your project configuration in the list.
    • Click on “Runner” in the right menu (Can show as “Runner: Visual Studio (sln)”)
    • Change the value of “Visual Studio” property to “Visual Studio 2010”
    • If your using nUnit, change the value of “Framework” under the nUnit definitions to 4.0 (if that doesn’t appear select a different version of nUnit).
  5. Run the build of the project

Good luck!

More Posts Next page »