Why I think some people shouldn't use VSNET 2003.

Additional Note:
I've changed the title of this article. The title is a hint from Robert. While I think blogging is about ventilating personal opinions, I do not feel it's my duty to bring Scott and this site (because the blogs are in the main feed) in trouble.

I do however find it pretty weird that people complain about this article but do not complain directly to me, by email f.e. I know I choose titles and article topics sometimes on the 'edge' of what can be tolerated. I learned that when I was a newseditor. Bad habbits never die, they say. The comments on this blog showed there are some solutions but they're all not that easy (for the customer or for the developer).

As a final remark, for Microsoft: a developer has to make two choices: which .NET version to target and which IDE version to choose. With Visual Studio.NET I have one choice: the .NET target is also implying the IDE version. I can't force my customers to shell out money to upgrade to VS.NET 2003, just because I think it's nice to target .NET 1.1. These two things: platform and IDE, should be separated. I can still develop software for Windows98 in VS.NET 2003, and I can also develop win32 software for Windows2003 in VS.NET 2002. Let that kind of freedom also be a choice for .NET developers. Thanks.

This morning it hit me: upgrading to Visual Studio.NET 2003 for .NET development of class libraries and controls is a bad choice when you are going to sell those class libraries and controls. I'll try to describe what drove me to this conclusion.

Visual Studio.NET 2003 offers great new features, for me the best are the faster compiler and the great new intellisense features. It also has a big caveat: it will use .NET 1.1 when compiling your code. This means that any library or control you develop in Visual Studio.NET 2003 and which relies on even a single .NET assembly, f.e. System.Data, will target .NET 1.1. Visual Studio.NET 2002 targets .NET 1.0. If you compile your code with Visual Studio.NET 2002, your code is requesting the .NET 1.0 versions of the libraries you reference.

Because of the new features in Visual Studio.NET 2003 (and don't forget the huge amount of bugfixes, still not available for Visual Studio.NET 2002), developers who can, want to upgrade to this new Visual Studio.NET version a.s.a.p. Microsoft offers side-by-side installation of this new version with the 2002 version, so it is a no-brainer, right? No. It's a big mistake, and this article is ment to warn any software vendor who wants to release assemblies for developers of .NET applications: do NOT, I repeat, do NOT upgrade to Visual Studio.NET 2003, because it will seriously hurt your customer, if he can use your code at all. Only consider an upgrade if you are totally sure your customers use .NET 1.1 and / or you have to because you are using .NET 1.1 features.

Let's investigate a real-life situation:

The problem
Within a few months I hope to release a generator/framework which will generate code which targets the accompanying framework. This framework is written in C# and is pre-compiled, it comes in the form of a couple of assemblies. You can also pick a situation where a developer writes a control-library in C# or VB.NET and sells it to other developers for usage in their products, same problem.

When you, as an ISV, write your code in Visual Studio.NET 2002, it will be compiled with .NET 1.0 in mind. This means: your class library DLL will run on any system with .NET 1.0 installed, or .NET 1.1 installed: when both are installed, it will pick .NET 1.0, if .NET 1.0 is installed it will pick .NET 1.0 and when .NET 1.1 is installed, it will pick .NET 1.1. This also means that any developer can buy your library/framework: if they use Visual Studio.NET 2002 or 2003, it doesn't matter, the assembly will run OK.

The situation changes dramatically when you, as an ISV, switch to Visual Studio.NET 2003. Your class library DLL will from then on target .NET 1.1, even if you do not use .NET 1.1 features. This also means that customers who buy your library and who use Visual Studio.NET 2002 will run into problems, because their code is compiled against .NET 1.0 and will not run, simply because the bought assembly requires .NET 1.1 assemblies which are not available. Errors like this will appear at the customers machine:

H:\Temp\dotnet test>FrameworkTester.exe
Unhandled Exception: System.IO.FileNotFoundException: 
File or assembly name System.Data, or one of its dependencies, was not
found. File name: "System.Data" at SD.NorthwindTest.DaoClasses.CustomerDAO.FetchCustomer(String customerID) ... Fusion log follows: === Pre-bind state information === LOG: DisplayName = System.Data, Version=1.0.5000.0, Culture=neutral,
PublicKeyToken = b77a5c561934e089 (Fully-specified) LOG: Appbase = H:\Temp\dotnet test\ LOG: Initial PrivatePath = NULL Calling assembly : SD.NorthwindTest, Version=1.0.1235.22288,
Culture=neutral, PublicKeyToken=null. ...
FrameworkTester.exe is a testapplication compiled on a box with .NET 1.0. The error-causing method is in a library compiled on a box with .NET 1.1 (using Visual Studio.NET 2003) and referenced during the compile of the FrameworkTester testapplication. As the error shows, the assembly compiled with Visual Studio.NET 2003 requires System.Data v1.0.5000.0, which is .NET 1.1.

The customer who runs Visual Studio.NET 2002 has now a big problem with your software: he can't use the assembly, unless he adds a long list of cryptic assemblyBinding tags to the config file of his application, and this is a cumbersome job to say the least. These assemblyBinding tags are automatically added in Visual Studio.NET 2003, when you specify .NET 1.0 as a supported platform for your application. A user of Visual Studio.NET 2002 doesn't have this functionality.

There are no figures of how many developers are on .NET 1.1 / Visual Studio.NET 2003 at the moment. Fact is that a very large part of the current .NET developers have .NET 1.0 on their machines and are most likely compiling against this platform. If you want to sell your software to developers, thus the developers in this large group, you shouldn't upgrade to Visual Studio.NET 2003 to avoid the platform conflicts and the resulting support hell that follows this. ISV's should compile using .NET 1.0 to be sure their customers can use the software they bought with the IDE they currently have: be it Visual Studio.NET 2002 or 2003.

What's causing this mess anyway?
The reason people have to jump through these hoops is the hard-wiring of the target platform in the IDE used. You can't target .NET 1.1 assemblies in Visual Studio.NET 2002 and you can't target .NET 1.0 assemblies in Visual Studio.NET 2003. This means that the choice which editor (!) you want to use for the source-text (!) is automatically also the choice which platform you are going to target.

Is there a solution?
Well... it would be very nice if I could set the target platform for the compiler in Visual Studio.NET myself, so I can benefit from the editor enhancements plus target older platforms so I can be sure all customers of my library will be able to use it in their applications no matter which version of Visual Studio.NET they use. However, this is not possible nor will it be possible. Microsoft decided it would be nice if developers get scr*wed over when they buy Visual Studio.NET, so here we are. Then there is the phenomenon Publisher Policy File. Microsoft states in the MSDN that you should be careful with these files and only release them when your application requires them. And how to use them in this situation? It probably requires a policy file for the .NET framework so all assemblies are redirected to the .NET 1.0 versions when a .NET 1.1 assembly requests a 1.1 version. Does anyone know? I couldn't find any information about this matter related to the backwards compatibility issue.

The best workaround is to supply a list of assemblyBinding tags with your assembly which then have to be included in the app.config file of the exe file compiled with .NET 1.0. This then redirects any requests from your .NET 1.1 targeting assembly to the .NET 1.0 assemblies. Did you know this? I didn't for sure. Is Microsoft supplying information about this? Not at all. Only upwards compatibility issues and information about side-by-side execution which will not work. See this article.

Oh, before you think: "but then I'll keep both Visual Studio.NET versions side by side on my machine!"... you can't open your projects in Visual Studio.NET 2002 after you opened them in Visual Studio.NET 2003. They get converted and you can't convert them back (you can, but it's messy). So a simple recompile using another Visual Studio.NET version is not possible.

If someone has a solution for this which works, please post it in the comments. I've tested it on a machine with solely .NET 1.0 installed and the only way I could run a .NET 1.0 compiled .exe which uses .NET 1.1 assemblies (i.e. bought assemblies) on the .NET 1.0 machine was using the assemblyBinding tags in the .config file. (I copied them over from the Visual Studio.NET 2003 version of the config file which contained these tags generated by Visual Studio.NET 2003).

I'm seriously considering going back to Visual Studio.NET 2002. It sucks, but I have no choice.

23 Comments

  • Then please help me in this situation, since I can't think of any real solution. How am I going to FORCE versioning onto developers using visual studio.net 2002? I can only tell them to use the assemblyBinding tags in their own config files otherwise it WILL NOT WORK.





    If this visualstudio.net 2002 user is not developing an executable but also a library (based on your library), he TOO has to tell HIS customers to include the assemblyBinding tags otherwise the code will NOT WORK.





    All versioning is focussed on UPWARDS compatibility. However no-one is talking about .NET 1.1 assemblies which are used in .NET 1.0 environments.

  • *dang* wrong quote :)


    [quote]


    Adopter:





    This works both ways. If you’ve built a v1.1 component, there’s nothing to prevent a developer from referencing it from a v1.0 application. In this case, your v1.1 component finds itself running on the v1.0 Framework. This situation is more dangerous than the reverse, as there’s the potential that your component uses something that doesn’t even exist in v1.0. If this is the case, expect a “missing method” exception.


    [/quote]


    I tested this and this is not true (see error listed in the blog). My 1.1 assembly is not run against the .NET 1.0 install on the machine even though the .exe file is compiled on that same machine using csc v1.0.3705.288, thus .NET 1.0.

  • If you have both frameworks installed, can you compile using the command line in the 1.0 environment?

  • Yes you can, you can manually compile against whatever framework you want. An ISV can opt for that route as well, however this can be cumbersome also when the set of assemblies have dependencies etc so you have to write NAnt files to build manually. It's not an easy situation, and I think not a lot of ISV's have thought about this, I for one hadn't until I tested it this morning and discovered I made a mistake upgrading to VS.NET 2003, even if the editor is much better and very helpful.

  • In VS.NET 2003 IDE, you can choose which framework to compile against.





    Project Properties -> Build -> Supported Runtimes -> Change


  • [quote]


    In VS.NET 2003 IDE, you can choose which framework to compile against.





    Project Properties -> Build -> Supported Runtimes -> Change


    [/quote]


    Only for .exe projects, and also this adds assemblyBinding tags to the .config file of the .exe project. You can't set this information on f.e. C# class library projects. VS.NET is also not compiling with .NET 1.0 if you select it in that dialog, it will compile using .NET 1.1, it will only change your app.config file so the compiled .exe uses .NET 1.0 because all referenced system assemblies are redirected to .NET 1.0 versions. This works ok.





    THomas: thanks, can be a life saver in supporting multi-platform applications.

  • again, I'm missing something here. .NET 1.0 is to DirectX 8.0 as .NET 1.1 is to DirectX 9.0. Get the drift? Just make the change and people will follow and soon enough no one will care about .NET 1.0, as they will all WANT to have 1.1 installed and running (and this includes those developers 'stuck' in VS.NET 2002 land)...

  • Oh yeah, great selling argument: "You can use this software only with visual studio.net 2003. If you have still visual studio.net 2002, please upgrade.". :) I don't think that's gonna work.

  • Frans: What about using a third-party IDE, such as SharpDevelop or C# Builder, to compile your release build?

  • This is horendous advice. .NET fully supports Sxs versioning and assemblies. You need to figure out how to use it properly. See the Early & Adopter article, read about publisher policy files, etc but *don't* write riduclous stuff like "ISV'sL do NOT upgrate to Visual Studio .NET 2003!" Not only does it look bad for you but it looks bad for this site (of which many .NET people have been pointing out how much totally incorrect and bad advice is given out daily).

  • You can’t **compile** against either framework version, but that you can use the <supportedRuntime> and/or <bindingRedirect> elements to run in either environment, assuming you don’t have dependencies. When we say compile against X, what we are really saying is that the compiler stamps the X version in the assembly metadata for the referenced version, which is the one the CLR tries to load unless redirected in the config files. Any code compiled in 2003 will target by default 1.1, but can be redirected using the configuration files. If you want to redirect to 1.1 from 1.0, you use the <supportedRuntime> element. And, if you want to go from 1.1 to 1.0, you use a slew of <bindingRedirect> elements. All of the VS.NET 2003 UI (C# and VB) to target runtimes creates the config files, but still stamps 1.1 versions in the assembly metadata. So, if you want to target 1.0 with code you wrote in 1.1, just add a section to the app config file. If you're an ISV, you probably have a setup process. Why can't you write this into your setup? Seems to be no big deal to me. What other software platform let's you upgrade without recompiling in a cleaner way?

  • Sam: the early & adopter article is not mentioning class libraries. If you are selling class libraries, you are falling into this pitfall. It is NOT ridiculus advice, since I *AM* now in this situation and I *CANT* fix it, unless I go back to visual studio.net 2002 or compile the sourcecode by hand for 1.0, or supply the assemblyBinding tags and *HOPE* my customers are going to include it in their config files.





    Do you know a solution then? I don't. You can say "It's horendous advice", but what are my options? I'm delivering a set of class assemblies to customers, who can (and probably will) use Visual Studio.NET 2002. I *CANT* compile these with .NET 1.1 because these will give them serious errors, unless they include the assemblyBinding tags in their config files. I've tested this today. I lost a complete day to test what I can do, and didn't find a solution. Therefor I posted this article.





    If people are OFFENDED by this, I'm sorry, but it's the clear hard reality for SOME ISV's.





    I also do not see why it would look bad for me. I warn other people to think twice before they move to vs.net 2003.





    So Sam, as an invitation, please offer me a solution so I can fix this properly. I don't see one. Requiring customers to buy visual studio.NET 2003 is ridiculus in itself, and I can't do much more. A customer with solely visual studio.net 2002 is not focussed to include redirects for .net 1.0, because he never had to. *THATS* the issue. Who is paying the bill for all the supporthours my people have to give customers because they can't run the code they bought? Should I do something to my code to make this easier? If I can, please tell me. I don't know what.

  • when I said "this site", I meant "dotnetweblogs as exhibited by the main feed" fyi

  • Stephen: if I was selling solely a .exe, it wouldn't have been a problem. The problem is with the class libraries. I can't supply them with a .config file (I wish I could).





    It would have been really great if a class library compiled with vs.net 2003 and run by an application build with .net 1.0 would immediately use .net 1.0 assemblies. That would solve the problem. However this is NOT the case. Of course a customer can add the assemblyBinding tags, it's the solution that worked, however a customer has to add them. I didn't KNOW that. It's not mentioned anywhere that you have to add these tags to a .net 1.0 (!) application's .config file to make its class libraries (which are probably compiled with 1.1) use .NET 1.0 assemblies.





    Because this is extra support trouble, extra trouble in codebases, it's wiser to keep the code in vs.net 2002, because this will keep you out of the trouble. I predict this issue will cause trouble for some ISV's. Now everyone is selling 1.0 versions, but this will change.

  • I am not going to do this with you. While I appreciate your fustration, bloggers here need to learn *not* to make grand denouncements of something. You didn't say "some". You said "ISVS: do NOT upgrade." So all ISVs should not upgrade? Surely *most* ISVs are not exhibiting this problem. Having a blog that is public conveys a responsibility for being accurate as well as posting content free of rants or grand pro/denoucnements. You get the lecture today because there is just so much of this going on in general on this site, and prominent .NET people and bloggers are starting to complain. 'Nuff Said.

  • Last post from me on this. Apparently, you still don't get the difference on "some" versus "all" and "giving good advice" versus saysing "ISVS: Do NOT." Do I have to spell this out any more clearer? I checked every word of what I wrote with Scott, and spoke to him and he was fine with it. Complaints is refering to not just *this* site but the high number of incorrect .NET information that shows up on the *dotnetweblogs main* feed from a number of blogs on dotnetwegblogs. Scott and I recieve complaints on it. I gave you good advice on how you could have blogged it and how to make a blog successful. You chose to ignore everything I wrote. It's your choice. This is all I am going to say on this.

  • I have been stuck having to compile my NUnitAddin project with VS.NET 2002 to ensure compatablilty with both. Yes I might be able to add redirects to devenv.exe.config but I don't think users would be very impressed. I have heard it is possible to compile against the 1.0 assemblies in VS.NET 2003. It would just take a while to manually change them all. I've just written a snippit of code to change all assemblies in a solution to be the 1.0 versions. If you've got NUnitAddin installed you can use 'Test With... VS.NET' on the following method. Put this code in the solution you wish to convert...





    using System;


    using System.IO;


    using System.Reflection;


    using System.Diagnostics;


    using EnvDTE;


    using Microsoft.Office.Core;


    using VSLangProj;





    public class SolutionConvert


    {


    public static _DTE DTE


    {


    get { return (_DTE)AppDomain.CurrentDomain.GetData("DTE"); }


    }





    public void BuildWith_v1_0_3705()


    {


    foreach(Project project in DTE.Solution)


    {


    VSProject proj = project.Object as VSProject;


    foreach(Reference reference in proj.References)


    {


    string assemblyPath = reference.Path;


    string assemblyFileName = Path.GetFileName(assemblyPath);


    string frameworkDirectory = Path.GetDirectoryName(assemblyPath);


    string frameworkVersion = Path.GetFileName(frameworkDirectory);





    string newFrameworkVersion = "v1.0.3705";


    string newFrameworkDirectory = Path.Combine(Path.GetDirectoryName(frameworkDirectory), newFrameworkVersion);


    string newAssemblyPath = Path.Combine(newFrameworkDirectory, assemblyFileName);





    if(frameworkVersion != newFrameworkVersion && File.Exists(newAssemblyPath))


    {


    Debug.WriteLine(assemblyPath + " -> " + newAssemblyPath);


    reference.Remove();


    proj.

  • .References.Add(newAssemblyPath);


    }


    else


    {


    Debug.WriteLine(assemblyPath);


    }


    }


    }


    }


    }


  • First, it's pretty easy to create separate VS 2002 and VS 2003 project files that point at the same source. Then you can work in VS 2003, and do your final build in 2002 (or you can set up a batch/makefile to do a command line compile).





    Also, if you build an assembly from VS 2003, you can reference that assembly from a VS 2002 application just fine. You do not need binding redirects or policy files in this case. These come into play if you have a strong named component, and you want to replace it with a newer version (and you want everything redirected to the newer one).

  • Or, you can maintain 2 downloads and EDUCATE your developers on which one to use.....

  • Scott Swigart: did you try it? Of course you can reference it from vs.net 2002. It even compiles ok. It starts up even, but when you call a method in a class library build with vs.net 2003 from a .NET 1.0 application, AND that class library uses an assembly of .NET to do something (in short: something useful), it will crash with an exception that it can't load the right assembly (the 1.1 version) so your call will not succeed. I tried it, it fails.





    Robert: maintaining 2 versions is nice, but what if I upgrade my own class library? Then I have to maintain 4 versions. Perhaps even 6 after another upgrade. I'll look into this, it might be the only solution which will not be a burden for my customers, if I implement it right in my generator.

  • Frans, I think what you are saying essentially true, but only for Component vendors. If someone is writing a general app, then Visual Studio 2003 is preferable. I've posted some more details on my blog.

  • Mike: that's why I'm talking about libraries :). General app developers are also able to target 1.0 in vs.net 2003 by the .config generator in vs.net 2003 which adds redirect tags in the .config file, for .exe projects. :)

Comments have been disabled for this content.