I'm very pleased to announce the .Net User Groups have started up a new mailling list for the discussion of all aspects of Team System - including Team Suite, Team Foundation Server, Team Build, Team Test, Reporting, Process Guidance, Portal, Licensing, etc etc etc. This list is intended to be used primarily for Kiwi's and local New Zealand issues but anyone is welcome to join.
Hopefully this forum will promote some lively discussions and provide some support for users new and old.
You can subscribe to the list here.
I've been playing with Testing in Team System this week (Wow! I want to be a tester! But that's another story for a later date). I am creating a sequence of manual tests for UAT (we don't have any UI Testing tools) and I want the testers/users to start with a clean build of the system and database with each test run.
Using RedGate SQL Packager I created a script to create the database with some sample starting data. I added a couple of tasks to my Team Build to create a database and execute the script on it. Using my custom ExecuteSQL task I added the following:
< TestDBServer>fred</TestDBServer> <TestDBName>$(BuildNumber)</TestDBName> <TestDBCreateConnectionString> data source=$(TestDBServer);integrated security=SSPI;Pooling=true </TestDBCreateConnectionString>
< Message Text="Creating test database " Importance="normal"/> <ExecuteSQL ConnectionString="$(TestDBCreateConnectionString)" Command="create database [$(BuildNumber)]" />
This created an empty database with a name of whatever the BuildNumber is. Note the [ and ] around the $(BuildNumber).
Next, I execute the script to create the database objects and populate it with sample data:
<Exec Command="isql.exe -E -S $(TestDBServer) -i $(BuildDirectoryPath)\SUMS3\SUMS3Debug\Sources\Airways.SUMS3\CreateTestDB.SQL -d [$(BuildNumber)]" />
The SQL script is checked in with the solution files, hence the funcky path to it. I could have had it in the Team Build project folder, but it's more visible in the solution.
So, now my Team Build produces completely isolated instances. Users can happily compare old versions with the latest and greatest version.
I just spotted something on MSDN about InfoCard and not knowing what the heck it was I searched and found a good description of it. Now I get an idea of what it is and it sounds like a good idea, but really, something that uses twelve-ish WS* standards seems way to much like something you'd get from IBM!
SOAP
WS-Addressing
WS-MetadataExchange
WS-Policy
WS-Security
WS-SecurityPolicy
WS-Transfer
WS-Trust
XML Signature
XML Encryption
SAML
WS-Federation (unclear)
Phew!
I have my Team Builds being published to a Sharepoint List and this works very well, but by default it's hard for the users to find the list. The default template for the project portal does not have a spare zone for me to drop the list into; instead, users have to navigate through the "Documents & Lists" page.
Thankfully, customising the project portal page is VERY easy thanks to the integration with Frontpage 2003. When you have this installed, you get an Edit option in IE. Clicking this will launch the site in Frontpage and you can add a Web Part Zone very easily.
I added a new zone to the top of the home page and them dropped my list in there, along with some instructions for users. Here's what it looks like:
Next? Well now it gets harder. It'd like to :
- Display a list of Work Items for the project and let users drill down to the details.
- Let user create new work items.
- Display a project summary WITHOUT using the icky reporting UI. This will probably include remaining work, velocity and issues in a composite report.
To do the above I need to delve into the TFS API and learn how to create Web Parts so this may take a while. Or not... we'll see.
There's a bug in Crystal for Visual Studio 2005 (surprise surprise!) when you have a stored procedure in your report WITH parameters AND you change the database connection at runtime. Basically, no matter what you do, it will tell you that the parameter has not been specified, when you know darn well that it has!
I found a discussion and the solution here. Wish I was using SQL Reporting :{
When my Team Build succeeds, it uses a custom task to publish a build so that users (testers) can execute the WinForms client. This is presented to users in a single page web app that looks like this:
I did this for my 2003/1.1 apps and it works well. Using it for the 2005/2.0 apps seems logical and easy. However, as Team System creates a SharePoint site for each project it seemed more logical to publish the deployed builds there. So, that's what I did. I need to document this more thoroughly but I wanted to get this down before it's spilled over the edge.
Windows SharePoint Services (WSS) Joy
Firstly, I created a new List in the SharePoint site and called this "Deployed Builds". It looks like this:
Next, I created a small prototype console app to test creating items in the SharePoint list. This was fun, NOT! I had a couple of issues and teething problems:
- You would think you need an SDK for doing WSS programming. When you look at the WSS Site you find a link to download the WSS SDK sure enough but you will also notice the "Sharepoint Products & Technologies SDK" which is a separate download.
- Both the SDK's are just help files - there is no libraries. To get Microsoft.SharePoint.dll - the .Net API - you need to download and install the Web Part Templates for Visual Studio.
- Depending on what you want to do, you probably don't need this either. You can use the web services directly, which is what I did.
- You will still need the WSSSDK though as it documents the web service API, CAML and related structures.
So, after a couple of hours of stuffing around, I had something that ran but produced the dreaded "Cannot complete action - Please Try Again" error. This is a catch-all for a lot of errors in WSS. After much reading and cursing and stomping of the keyboard, I found a blog entry that told me exactly what the problem was. When you insert a URL field, you need to format it correctly as "url, description".
MSBuild WSS Task
Now I had the prototype working, I converted this to a MSBuild Task. I wanted the task to be generic so I could use it to populate any SharePoint list. To use the task, you do something like this.
Firstly create a list of name/value pairs that match the SharePoint list:
<ItemGroup> <PortalListValues Include="URL"> <FieldName>URL</FieldName> <FieldValue>file://$(ClientDeployDest)\airways.sums.exe, SUMS III</FieldValue> </PortalListValues> <PortalListValues Include="Location"> <FieldName>Location</FieldName> <FieldValue>TPK</FieldValue> </PortalListValues> </ItemGroup>
In my case, I'm leaving the Note field blank and the Active field will default to "No". Notice that the URL is a file location and that the description is included.
Next, I call the task thus:
<UsingTask TaskName="Airways.Build.Tasks.WSS.AddListItem" AssemblyFile="Airways.Build.Tasks.dll"/>
...
<Target Name="AfterDropBuild">
ListName="Deployed Builds"
FieldValues="@(PortalListValues)" />
</Target>
Viewing the List
When an item is added to the WSS list the Active field defaults to "No". The default view in SharePoint excludes records that are not active. I have another personal view that I use to edit the records and activate them for users. This way I can build as often as I like and "release" when I'm ready.
I think this is a new feature, please tell me if it's not so I can kick myself.
When an exception occurs deep in some code, the reason is most likely at a much higher level, e.g.:
This exception occurred in DataSet code due to something wacky in the UI. The call stack shows how we got here:
It's very easy to navigate back through the call stack and examine variable values etc, but often you have to restart the app with a break point set in a suitable place - at least that's what I thought till I noticed this:
When you select this it unwinds the execution of your application back to the selected Frame in the call stack. How cool is that ? Very cool I think.
I've just added one more task to my Team Build and its done - for now. Here's how the whole thing works.
- I execute a Team Build manually.
- When the project builds successfully, it copies the client and server outputs to a publically visible path.
- The build configures the web service virtual directory.
- The build updates the client .config to point to the new web service vdir.
- The build writes a record to a SQL table.
- Team build sends me an email alert to tell me the build completed successfully.
- I manaually edit the log table to release the build and enter a note.
- The user accesses the launch page and views the build details.
- The user launches a build for testing via a link on the launch page.
- I go home happy.
The last custom task I added was a SQL Command executor which I use for logging the successfull deployment. The launch page uses this to display a menu of successful builds. The application is launched from a UNC path so users need to configure some machine security settings, for which I provide an MSI.
Now back to finishing the (never ending) project.
The next step of my project deployment via Team Build is to update the exe.config file for the newly created web service. To do this, I needed to create a task to edit an XML file. Once again I looked at the SDC tasks, but found that it was easier to write my own. I added the following to the build file. <PropertyGroup> ... <TestDataUrl>http://blah/SUMSWS $(BuildNumber)/SUMSDataasmx</TestDataUrl> <TestSecurityUrl>http://blah/SUMSWS $(BuildNumber)/SUMSSecurity.asmx</TestSecurityUrl> </PropertyGroup> <UsingTask TaskName="AirwaysBuild.Tasks.XMLFile.ModifyXMLNode" AssemblyFile="Airways.Build.Tasks.dll"/> <Target Name="AfterDropBuild"> ... <!-- update the app.config --> <ModifyXMLNode Filename="$(ClientDeployDest)\Airways.SUMS.exe.config" XPath="/configuration/applicationSettings/Airways.SUMS.Properties.Settings/setting[@name='WSDataURL']/value" NewValue="$(TestDataUrl)" /> <ModifyXMLNode Filename="$(ClientDeployDest)\Airways.SUMS.exe.config" XPath="/configuration/applicationSettings/Airways.SUMS.Properties.Settings/setting[@name='WSSecurityURL']/value" NewValue="$(TestSecurityUrl)" /> <ModifyXMLNode Filename="$(ClientDeployDest)\Airways.SUMS.exe.config" XPath="/configuration/applicationSettings/Airways.SUMS.Properties.Settings/setting[@name='BuildVersion']/value" NewValue="$(BuildNumber)" /> </Target>
The two new properties define the ASMX urls for the two services. In the AfterDropBuild target I use these to update the exe.config file. A third task updates a BuildVersion setting in the config which is displayed on the applications main window caption (so the user can clearly see which build they are running).
Each ModifyXMLNode task on the target defines the file name to modify, an XPath statement for the element or attribute and the new value to insert. The new values are treated as text / strings and I use these in the task code thus: XmlNode node = Document.DocumentElement.SelectSingleNode(XPath); if (node != null) { node.InnerText = NewValue; }
I'm not sure if I should use InnerXml instead of InnerText - what I have now works well enough.
Once again, if you'd like the code for this task, shoot me an email or use the contact link on this blog or post a comment. I'll probably be adding more tasks sooner or later. When I get a bigger library of useful tasks I'll post it for download somewhere.
I must say that creating tasks for MSBuild is a lot of fun. I'd be happy doing this all day every day. You get to play with lots of different stuff, you don't have to create fancy UI and it's really very easy to do. Back in NAnt days I never created a task - probably because there is already a vast library of free ones available, but also because I thought it was harder to do.
All my research and experimentation is starting to pay dividends. I've managed to extend my Team Build to copy the project outputs from the drop location to a new folder structure and create an IIS virtual directory for the web service.
So far, this is the steps I followed.
Edit the TFSBuild.proj file
I added the following to the build:
<PropertyGroup> <ClientDeploySource>$(DropLocation)\$(BuildNumber)\Debug</ClientDeploySource> <ServerDeploySource>$(DropLocation)\$(BuildNumber)\Debug\ PublishedWebsites\SUMSWS</ServerDeploySource> <ClientDeployDest>$(DropLocation)\test $(BuildNumber)</ClientDeployDest> <ServerDeployDest>$(DropLocation)\test $(BuildNumber)\SUMSWS</ServerDeployDest> <ServerLocalPath>D:\devweb\deployment\SUMS3\test $(BuildNumber)\SUMSWS</ServerLocalPath>
</PropertyGroup> <UsingTask TaskName="Airways.Build.Tasks.IIS.CreateVDir" AssemblyFile="Airways.Build.Tasks.dll"/> <Target Name="AfterDropBuild"> <CreateItem Include="$(ClientDeploySource)\*.dll"> <Output TaskParameter="Include" ItemName="ClientDLLs"/> </CreateItem> <CreateItem Include="$(ClientDeploySource)\*.exe"> <Output TaskParameter="Include" ItemName="ClientEXEs"/> </CreateItem> <CreateItem Include="$(ClientDeploySource)\*.exe.config"> <Output TaskParameter="Include" ItemName="ClientCONFIGs"/> </CreateItem> <CreateItem Include="$(ServerDeploySource)\**\*.*"> <Output TaskParameter="Include" ItemName="ServiceFiles"/> </CreateItem> <!-- copy the client filed --> <Copy SourceFiles="@(ClientDLLs)" DestinationFolder="$(ClientDeployDest)" /> <Copy SourceFiles="@(ClientEXEs)" DestinationFolder="$(ClientDeployDest)" /> <Copy SourceFiles="@(ClientCONFIGs)" DestinationFolder="$(ClientDeployDest)" /> <!-- copy the web service --> <Copy SourceFiles="@(ServiceFiles)" DestinationFiles="@(ServiceFiles->'$(ServerDeployDest)\%(RecursiveDir)%(Filename)%(Extension)')" /> <!-- make the virtual dir --> <CreateVDir Server="localhost" Site="BSDTesting" PhysicalPath="$(ServerLocalPath)" VirtualPath="SUMSWS $(BuildNumber)" /> <!-- create the test db ?? --> <!-- update the .config --> <!-- update the launcher XML file --> </Target>
The property group defines some source and destination folders. These are based on the DropLocation which is defined at the top of the build file. The destination folders for the client and server happen to be on the same machine to keep things simple, but these could (and probably should) be on another server.
Next, there is a new custom task I made for creating a virtual directory in IIS. I search for a while without luck to find a built in solution for this or someone else's solution but in the end it was very easy and fun to create my own task. My first attempt actually worked on the first execution! Its not a very complete task - you can't do everything you might want to do with a VDIR but for me it's adequate. If you want the code then shoot me an email or post a comment. I had a look at .NET Solution Build, Deployment, Process & Tools but I found this too confusing at the time and thought it was easier and more enjoyable to create my own task. Now I understand the process better I might take another look at this handy kit.
Next in the build file is a new Target. This overrides the default AfterDropBuild target. We need to use CreateItem as the items to be copied are produced by previous targets and don't exist when the build file is loaded. If I had specified all the actual files by name rather than wildcard then I could have used an ItemGroup, but that would be tedious and error prone. The rest of the target is pretty self explanatory.
Checkin the TFSBuild and Custom Task
Once I made the changes I checked in the TFSBuild file and added the custom task dll to the Team Build folder in Source Control. When the Team Build executes, these files extracted to the build server so it's not necessary to put the custom task in the build server GAC or any such horrid stuff.
I've still a few more steps to complete before I can have new builds automatically published to users/testers but hopefully this will be as easy and fun as the rest of this. I'll post an update when I've got the whole thing working.
I've been trying to figure out how to extend my Team Build. I need to package the binaries and other files as well as update .config files and deploy the outputs ready for user testing. I've done this before with NAnt and Draco .Net but I'm finding it a lot harder to do this with MSBuild and Team Build - probably because there's a lot of new stuff to learn.
Here's a list of resources I've found so far. Some of these are from other peoples blogs as I haven't found 1 single source that has everything. I'll update this post as I find more. (* = Team Build Specific)
Blogs
Sites
Lists
Stuff
People
If you have any more I'd LOVE to know.
A friend and fellow Kiwi .Netter, Brent Clark, is repeating his popular web cast tommorow. If you want to know more than your mother ever told you about building VB6 & VB.Net applications with lots of COM & VSSS then Brent is THE MAN! Go Brent!
From a Microsoft .NET Framework build perspective, consuming evolving Component Object Models (COM) is not a trivial matter. This webcast describes how SunGard in Christchurch, New Zealand has extended its automated build processes to be able to interact with NET and COM components. Learn how SunGard was able to compile .NET solutions from Microsoft Visual Source Safe with strong naming, version stamping, and copyright stamping. You will also learn how SunGard automatically produced interoperability files for the ever-changing COM components. This webcast also describes how SunGard produced publisher policy files that allow the company to patch the minimum number of files in a client installation.
Presenter: Brent Clark, Build Process Architect, SunGard
Brent Clark manages the build process for a large 10-year-old system produced and maintained by SunGard in Christchurch, New Zealand. This system is made up of approximately three million lines of code that are written mostly in Microsoft Visual Basic 6.0 but now extend into Microsoft Visual Basic .NET. Brent's responsibilities have included the automated analysis and compilation of Visual Basic 6.0 and .NET projects. He has also worked on deployment to internal clients and also branching and reintegrating separate subproject environments.
Microsoft and INeta are doing a big push with the launch of Visual Studio, SQL Server and BizTalk. They have sent us some goodies and training materials so Tim and I have decided to run a series of BYO PC Workshops.
This is a great way to learn the technology in a quiet, interruption free environment. We will give a brief overview the subject and then you get to spend 1 to 2 hours working on exercises. You get to do this on your own machine so you can take the materials away with you and play later.
We will also be giving away a copy of Visual Studio 2005 Standard and SQL Server 2005 Standard at each of the workshops to one lucky attendee.
We decided to run the workshops in the early morning (8am) so as to minimise the impact on your working day. If this does not suite enough people or there is sufficient demand for a different time we can probably re-run the events at a more civilised time.
Sadly, I'm finding a few issues with Visual Studio 2005 and Team System.
- The ToolStrip designer is less than stable. If a ToolStrip overflows to the drop down menu you can add new ToolStrip items but you cant move them or delete them.
- The WebDev.WebServer STILL drops connections which makes it useless for debugging. I logged this as a bug a while ago. I also managed to speak to the chap in Redmond who wrote this (or is at least responsible for it) while I was there for the summit. Sorry, can't remember his name now, but he knew nothing of the issue then. It may be just an issue on our systems (I've seen it on 2 machines) or with our project. Has anyone else seen this problem?
- Visual Studio locks up frequently. Actually, it's not dead, just not responding. The Task Manager shows about 50% cpu activity on devenv.exe but I have to kill the process. I'm not sure but I suspect this might be a Team System Source Control issue.
- Help is very slow to load.
- Visual Studio can be very slow to load.
- I had an issue with a solution yestuday that wouldn't let me open the projects in it or re-add them. I had to create a new SLN and add the projects back in. I think Team System Source Control is/was caching an incorrect path so even though I had a proejct file in C:\SomePath and I selected the project to add, it would look in a different path (where the project once was).
All of these things are a little annoying but certainly not show stoppers. I'll research these a little more and then log bugs for whatever I can nail down.
Microsoft has published a case system of our Team System implementation.
Something to change the subject. I ordered a solar water heating system for home yesturday. When I saw how much the Chief of Contact Energy got for a pay rise and how much our power bills have gone up in the last year I thought it was about time to get some money back.
We ordered the Sola 60 system. In our new house it's a very easy install. Sola 60 use our existing hot water cylinder where most of the other vendors replace this with a new one, so this helps keep the cost down. The placement of the panel and the pitch and position of our roof make it a very easy install.
It's costing us $NZ 5074 for a 4-5 person system. Our monthly power bill averages $300 in winter - we have 3 kids who like loooooonnnnnngggggg showers! The sales man from Sola 60 told us that the average power bill is 1/3 hot water and the new system will cover 75% of the electricity cost of this in winter and 100% in summer (this equates with other quotes and comments I've seen). My rough estimate is that it will save us an average of $90 a month - call it $1000 a year. So after 5 years we are in profit. Better yet, there's an interest free loan of $3000 for 3 years so the initial expense won't hit the mortgage. I wish we had done it when we built the house.
Now all I need is a system to generate hydrogen and a fuel cell car and I can give the single finger wave to the energy merchants!
Having spent most of the day mucking with VS 05 RTM & Team System Beta 3 Refresh - here after called TSB3R - these are my initial observations and comparisons with Beta 2 - no particular order.
- Source Control is wickedly fast! Ok, so my database is probably pretty empty but it's at least as fast as Vault - maybe even faster if that is possible.
- Creating a new Team Project is faster - ~30 seconds instead of 2 minutes.
- The Agile process template and process guidance are much improved.
- The default new tasks for an Agile project - only 14 of them for a new project - include useful details and references to the process guidance (but these are not hyperlinks unfortunately).
- Compiling a project does not check out the project file anymore.
- When I edit a checked in file, focus shifts to somewhere else when it does the check out and I have to click back in the code window. This may be because I have the tool windows undocked onto my 2nd monitor. I'll experiment with this and log a bug.
- There's a few new reports with interesting names, eg, "Unplanned Work", "Bugs found without corresponding tests", and "Regressions".
- The Team Build progress & results window is WAY nicer than B2.
- Code Analysis still slows down the build hugely - ~10 seconds without, ~120 seconds with.
- There is a new Task type of Risk for Agile projects.
- Test Controller and Agent setup is confusing - I think it's now part of the Team Suite install because there's nothing in the TFS install that looks relevant.
- You get little pad-locks on the tab pages in VS so you can see if the file is checked in or not.
- Refactor rename still tries to drill into code that it shouldn't. For example, renaming a private variable in a class library searches through web service code that in no way can ever see the var. It is quicker but could be a lot quicker if it didn't do this. Another bug to log.
- The command line tools for TFS are simpler and easier to find but there's no project delete tool - maybe this will be in the SDK?
- Despite my problems I think they have got the server install as simple as it can be. Installing SQL Server is the hardest part really and that take about 5 minutes - not enough time for a game of Spider :{
So, after day 1, I'm very impressed. I've got lots of coding to do over the next few weeks so will reserve final judgement :}
I downloaded the correct version of Team Foundation Server Beta 3 Refresh overnight and installed it in about 40 minutes this morning - client and server - and it seems to be working very sweetly so far. Here's what I've found to make the install go smoothly (after 7 unsmooth attempts!). This is for a single server install.
- Make sure you have the correct versions of everything - RTM SQL Standard, RTM VS Team Suite, Sharepoint with SP 2 and TFS Beta 3 REFRESH.
- Read through the TFS Install Guide as thoroughly as you can.
- Reformat your server, install Windows 2003 Server with SP1, IIS etc as per the TFS Install guide.
- Make sure your server is joined to the domain and the network configuration is correct (my Compaq DL 380 has dual Nic with separate IP's so I had to create a "Team" using the HP tool and set this as a fixed IP so that Windows Update would work (we block this normally)).
- Do all the windows updates you can - 18 critical updates for me.
- Create the 3 required accounts and add them to the machines Administrator group and add your own domain account to this group too (you can remove it later if you have to).
- Login to the server as TFS Setup.
- Install SQL, Sharepoint and TFS EXACTLY as the Install Guide says - don't trust your memory, read and follow the instructions a step at a time.
The only variation I made to the install was to change the data directories for SQL & Analysis Servers. Oh yeah, I also installed the SQL Workstation Tools so I could setup backup and so other maintenance (and play a little with SQL 2005).
I'm sure you can get this to work without having to reformat the server but it's a lot easier to start over when you know you can delete stuff without worry.
For the client, the first part is to get VS.Net working correctly. If you have had Beta 2 or RC on your workstation then you should make sure you uninstall this correctly. I didn't and had to do it the hard way. Read this! Once you have it working then install the Team Explorer from the TFS install. This is a separate install now rather than being included in Team Suite.
Because you added yourself to the servers admin group, you should be able to get into your system and configure security and groups, create projects etc.
For user permissions, I'm going to do everything in Active Directory. I'm creating a structure like this:
- OU: Our Team System
- OU: Service Accounts
- TFSService
- TFSSetup
- TFSReports
- Group: TS Administrators
- MyLogin
- MyBossesLogin
- OurITPeople Group
- Group: TS Users
- Group: All Developers Group
- OU: TS Projects
- OU: Some Big Project
- Group: Some Big Project Administrators
- MyLogin
- MyBossesLogin
- etc
- Group: Some Big Project Contributors
- Group: Some Big Project Readers
Well, that's the theory at this stage. We control our AD pretty tightly here so without IT delegating me some rights to manage the OU it's going to be a pain but hopefully they'll allow this.
Now on with exploring the changes...
I think the source of all the problems with my Team Foundation Server install stem from the fact that I was using Beta 3, not Beta 3 Refresh. I'm very red faced - but in my defence, I must say that the download option from TAP was not that obivous - it is now, but when I downloaded it the only clue was a folder called "vstf.b3.rtm". Anyways, I'm downloading the correct version now so by this time tommorow it should be working. .. (famous last words?).
On the up side, I'm getting very good at installing SQL Server!
Class designer won't load in Visual Studio
I spent last
week getting trained on Software Testing. The course was run by Software
Education and led by Don Mills. I haven't yet decided if I liked this
course or not. Don certainly knows the subject well - he has an
amazing memory for dates, names, authors, standards codes etc. I
picked up many useful techniques, tips and facts, e.g:
- Inspection provides
the biggest return of all other testing and QC techniques
- Decision Tables are a great tool for creating specifications
as well as tests.
- Test early, test
often
- If you don't know
how to test it then don't start building it
- 70% of software
faults are the result of poor specification - only 7% are genuine code
defects.
- Half of all
software project are delivered unfinished.
However, the course
syllabus is very centered around the standards and passing the qualification
exam and I would have preferred more practical examples.
The real problem
with testing is the lack of management commitment to doing it. My current
employer is much more aware of the need for this - they sent me on the course
after all - but previous employers have been unwilling or unaware of how
important proper testing is and my feeling is that this is a very common
situation for most New Zealand companies
doing software development. Given the clear cost savings that can be
made by engaging in proper testing practices and the appalling rate of failure
of software projects, this is a real concern for the future of software
development in New Zealand.
So what as
programmers can we do to make this situation
better?
If your an MSDN
Subscriber you can now download Visual Studio 2005 and SQL Server 2005
RTM.
Expect a
looooonnnnnnngggggg download!
|
Copyright © 2012 Peter G Jones. All rights reserved.
DasBlog 'Portal' theme by Johnny Hughes.
Pick a theme:
|
|