June 2006 - Posts
I decided to build a MCE PC for home (replacing a £200 DigiFusion PVR), I thought how hard can it be, it is just XP and a TV card.
I don't intend to go into the gory details of the build, suffice it to say one blown motherboard and a true understanding that this is an OEM product (for dedicated hardware) not for the home builder, but I can provide a few pointers:
- My PC specification seems reasonable, an AMD Sempron 3100+, 1Gb memory, large IDE disk and an ATI Radeon 9600 AGP card. It averages out at about 20% utilisation, so little more than tickover
- Firstly the MCE setup video failed to play, this turned out to be the wrong ATI drivers, make sure whichever card you are using you have MCE specific drivers, even if they are a bit old.
- Initially I had jumpy playback on live TV and recordings, I was using a Hauppauge DVB card and the NVidia decoder. After much playing with drivers I fix this by, believe it or not, moving the PCI TV card to a slot as far from the AGP video card as possible.
- On some digital TV channels on the MCE it was still jumpy, my Phillips integrated digital TV was better (but not perfect), a cheap TV ariel amplifier fixed the problems. Note that this is even though both the TV and MCE said the TV signal strength was excellent!
- I had built the PC using an old case, but wanted to get something that was quiet and could be put in the lounge not a machine room. I fancied a totally passively cooled unit, but decided that spending more on the a metal box, PSU and heat sinks than on the actual TV could not be justified, so I ended up with a D-Vine D5 Case with PSU and a Zalman CNPS7000B Series Super Flower Cooler. The CPU cooler is really quiet, but the case PSU could be quieter, but it is certainly much quieter than a standard PC. The worst item for noise was the fan on the ATI card, I looked at passive heatskins, but as the card did not seem to be running hot I just disconnected the fan (all seems OK after a week, it is not even hot to touch!). I may experiment inside the main PSU to see what can be done there with disconnections.
So has it all been worth the effort? I would say yes - MCE is a nice interface, the TV guide is excellent. If you buy a custom built system, or are a keen, experienced system builder and want a project it is perfect. However if you want an quick easy way to record digitial TV look at a PVR from Humax or DigiFusion.
I had a great time at the Office Developer Conference in Hammersmith last week. It covered Infopath 12, SharePoint V3 and Workflow, some of my hot topics at the moment.
It was great to put faces to names (and bloggers) like Dave Gristwood, and to see a few others speak again (like Mike Ormond). I also enjoyed Jessica Gruber's sessions, and will be reading her blog from now on too.
Were you there?
L.
I have just finished moving a large Embedded Visual Studio 4 (MFC) project to Visual Studio 2005. It was somewhat a painful experienece which I would not want others to have to endure.
I am sure anybody else will have different problems but the solutions that helped me were
1. build a new Visual Studio 2005 MFC application
2. migrate the old app by opening it in VIsual Studio 2005 ( save the app )
3. delete all the code in the new application exept Stdafx.h
4. compare and merge your old stdafx.h and the new one ( really this should mean replacing your stfafx.h )
5 fix remaining build errors, the new compilers are great and will find enough embarrassing errors to make the exercise worth while. you will most likely have a few problems with SEH and sh* functions but they do drop out.
Doing the above will save you a lot of time, the changes in stdafx are quite extensive.
If you are running IE 7 before the steps above you will need to edit your registry
To add a new entry to
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Ext\PreApproved
called
{D245F352-3F45-4516-B1E6-04608DA126CC}
This will allow the mobile wizard to use the IE 7 html control
The end results are an application which is approx 10-20% faster and we have intellisense woo hoo.
b.
Addendum:
// ::CommandBar_Show(m_pWndEmptyCB->m_hWnd, FALSE);// 2005 port
HWND cmdBar=::SHFindMenuBar(this->GetSafeHwnd());
::ShowWindow(cmdBar,SW_HIDE);
I had to have a new motherboard in my Dell 5150 laptop, one of the memory slots failed on the old one. Since the repair my laptop seems to have been running hot. Also when using Virtual PC 2004 SP1 the sessions seems to pause for a second or two from time to time.
I have tried the hotfix for VPC 2004 and this seemed to help the speed a bit (but not as much as I would have hoped), but my PC still seemed a lot hotter than it used to be.
I installed the excellent I8KFanGUI to get an idea of what was going on, and found that I seems to always be running at top CPU speed 3GHz, so no smartstepping slowing me down (oftan blamed for slow VPC performance), and the fans seems to be doing sensible things. However, my average CPU temp was about 55C with a max of 71C.
I read round a bit and found a number of people with CPU temp problems with the newer BIOS (A37/A38), so I downgraded to BIOS A35 (which I think my old motherboard had) and low and behold my idling temp dropped by nearly 10 degrees to 47C. My max is about the same.
So at least I don't have to prop up my PC on a book to avoid thermal shutdown, I just need a better solution to the VPC speed problem, I suspect a networking polling issue.
A day or so ago our CruiseControl stopped working, I was seeing loads of problems in the Get source stage. Basically it was timing out, but it had work last week! OK I had been trying to get MsTest integrated but that should not have effected the source control.
After much fiddling including:
- Creating a new VSS DB (very small one)
- Moving the DB to a different server
- Trying VSS 6.0 and VSS 2005 clients
I pinned the problem down to a networking issue (the new small VSS DB worked OK if local on the same box as CCNet, but not across a 1Gb LAN to another 2003 Server).
More digging found the issue was our Mcafee VirusScan 8. My guess is that an automatic update last week caused the problem, it must have swiched something on, or change the load level it cause.
So in the end the simple fix was to switch off the Mcafee VirusScan On-Access Scanner's file reads checking the problems all go away.
I have been trying to get Visual Studio 2005 Team Developer style unit tests working within CruiseControl.
The documention says it should work, but is a little scant as to the detail of how to do it. So now I have it all going I thought an example of the working ccnet.config file with some comments might help other people trying to get this going.
So the background is I have a VS.NET 2005 solution (My Sample.sln) with some projects in it. One of these is a Test Project (TestProject.csproj). This contains some test which can be run via the Test menu option is VS.NET.
CCNET.CONFIG
<
project name="My Sample">
<!--Here you put any other project level settings-->
<!--the working directory is used for all relative file references-->
<workingDirectory>C:\projects\My Sample</workingDirectory>
<!--Normally you would have all your source control bits here-->
<tasks>
<!--We use the Visual Studio build model, you could also use the MSBUILD-->
<devenv>
<solutionfile>"C:\projects\My Sample\My Sample.sln"</solutionfile>
<configuration>Debug</configuration>
<buildtype>Build</buildtype>
<!--Comment out the project block so it build the whole solution-->
<!--<project>MyProject</project>-->
<executable>"C:\Program Files\Microsoft Visual Studio 8\Common7\IDE\devenv.com"</executable>
<buildTimeoutSeconds>90</buildTimeoutSeconds>
</devenv>
<exec>
<!--Call a batch file that contains del testResults.trx -->
<!--this is required as MsTest will not create the file if it exists-->
<!--this could be merged with the mstext action in a single batch file-->
<executable>deleteTestLog.bat</executable>
<baseDirectory>C:\projects\My Sample</baseDirectory>
<buildArgs></buildArgs>
<buildTimeoutSeconds>30</buildTimeoutSeconds>
</exec>
<exec>
<!--Call mstest to run the tests contained in the TestProject -->
<executable>C:\Program Files\Microsoft Visual Studio 8\Common7\IDE\mstest.exe</executable>
<baseDirectory>C:\projects\My Sample</baseDirectory>
<!--testcontainer: points to the DLL that contains the tests -->
<!--runconfig: points to solutions testrunconfig that is created by vs.net, list what test to run -->
<!--resultsfile: normally the test run log is written to the uniquely named testresults directory -->
<!-- this option causes a fixed name copy of the file to be written as well -->
<buildArgs>/testcontainer:testproject\bin\debug\testproject.dll /runconfig:localtestrun.Testrunconfig /resultsfile:testResults.trx</buildArgs>
<buildTimeoutSeconds>30</buildTimeoutSeconds>
</exec>
</tasks>
<publishers>
<!--to get the test results in the dashboard we have to merge the results XML file -->
<!--the project working directory is used as the base path here -->
<merge>
<files>
<file>testResults.trx</file>
</files>
</merge>
<!--this is the line I missed for ages, without it you get strange missing publisher log errors -->
<xmllogger />
</publishers>
</project>
</cruisecontrol>
DASHBOARD.CONFIG
By default with CCNET build 1277 has the entry to display MSTest results in the summary. If you want the results on a separate menu item (like nUnit or FxCop) then the dashboard.config should contain the following bits
<
buildPlugins>
<buildReportBuildPlugin>
<xslFileNames>
<!--all these xsl entries are in the 1277 build -->
<xslFile>xsl\header.xsl</xslFile>
<xslFile>xsl\modifications.xsl</xslFile>
<xslFile>xsl\compile.xsl</xslFile>
<xslFile>xsl\unittests.xsl</xslFile>
<xslFile>xsl\MsTestSummary.xsl</xslFile>
<xslFile>xsl\fxcop-summary.xsl</xslFile>
<xslFile>xsl\NCoverSummary.xsl</xslFile>
<xslFile>xsl\SimianSummary.xsl</xslFile>
</xslFileNames>
</buildReportBuildPlugin>
<
buildLogBuildPlugin />
<xslReportBuildPlugin description="NUnit Details" actionName="NUnitDetailsBuildReport" xslFileName="xsl\tests.xsl" />
<xslReportBuildPlugin description="NUnit Timings" actionName="NUnitTimingsBuildReport" xslFileName="xsl\timing.xsl" />
<xslReportBuildPlugin description="NAnt Output" actionName="NAntOutputBuildReport" xslFileName="xsl\Nant.xsl" />
<xslReportBuildPlugin description="NAnt Timings" actionName="NAntTimingsBuildReport" xslFileName="xsl\NantTiming.xsl" />
<xslReportBuildPlugin description="FxCop Report" actionName="FxCopBuildReport" xslFileName="xsl\FxCopReport.xsl" />
<xslReportBuildPlugin description="NCover Report" actionName="NCoverBuildReport" xslFileName="xsl\NCover.xsl" />
<xslReportBuildPlugin description="Simian Report" actionName="SimianBuildReport" xslFileName="xsl\SimianReport.xsl"/>
<!--add the following line to add the extra menu item-->
<xslReportBuildPlugin description="MSTest Report" actionName="MSTESTReport" xslFileName="xsl\MsTestSummary.xsl"/>
</buildPlugins>
In my demo last week I extended a string class; I am pleased to say that after some ( quick ) investigation as predicted the calls to the class are identical.
To explain extensions we can use the following code
class Fred {
string MyStringMethod ( string s ) {
// do something
}
}
string x = Fred.MyStringMethod(x);
Using extensions we can change the definition of the method MyStringMethod to use this
string MyStringMethod ( this string s )
this allows us to call it in a more friendly manner
string x = x.MyStringMethod();
as if it were a member of string.
When looking at the code generated there is No difference in the invocation i.e., it always calls Fred.MyStringMethod. the only change to code is the attribute added to the MyStringMethod
[Extension] attribute which has been attend to the method which shows that it is an extension method.
All I can say is I think that the language designers at Microsoft have done another great seamless job on adding features.
I have not been able to add the attribute by hand at this point.
Boss.
Last Saturday I presented on LINQ at Developer Developer Developer. I stated that that much of LINQ was syntactic sugar ( very good low fat sugar) and in fact much of the work being done by the compiler effectively did repetetive work that we do day to day.
I see this as very solid reoccurring theme in Microsoft development tools, if the developer is doing the same thing again and again, visual studio will aim to help without being too prescriptive.
During the talk I confidently stated that the compiler really was generating much the same or possibly identical code, I suggested that the attendees could look at home but somehow I ended up offering to do the job so here are some rough notes.
taking the two snippets of code
for .Net 2.0
List<int> list = new List<int>();
list.Add(1);
list.Add(2);
list.Add(3);
list.Add(4);
List<int> evenNumbers = list.FindAll(delegate(int i) { return (i % 2) == 0; });
foreach (int evenNumber in evenNumbers)
{
Console.WriteLine(evenNumber);
}
and its LINQ equivalent
var list = new List<int>() { 1,2,3,4};
var evenNumbers = list.FindAll(i=>(i % 2) == 0);
foreach (var evenNumber in evenNumbers)
{
Console.WriteLine(evenNumber);
}
looking at the IL code that is generated for the anonymous delegate / lamda function we see that the code is identical for both
.method private hidebysig static bool <Main3>b__2(int32 i) cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor()
.maxstack 2
.locals init (
[0] bool flag1)
L_0000: nop
L_0001: ldarg.0
L_0002: ldc.i4.2
L_0003: rem
L_0004: ldc.i4.0
L_0005: ceq
L_0007: stloc.0
L_0008: br.s L_000a
L_000a: ldloc.0
L_000b: ret
}
which is the equivalent to
[CompilerGenerated]
private static bool <Main3>b__2(int i)
{
return ((i % 2) == 0);
}
Obviously the method name changes but that is the only change.
For the main block of code the only difference is the LINQ code generates a temporary List, populates it and then assigns it to the variable list. I can only assume that this is the implementation method of assignment, but I would hope it will come out in the wash, not that in the grand scheme it matters, but it would be a bit tidier.
I will be looking at other examples and posting my findings over the next week or so.
Boss.
WinFX 3.0 is now .Net Framework 3.0
With the aim of providing us with consistency Soma has announced that from now on WinFX consisting of Windows Presentation Framework (Avalon) , Windows Communications Framework (Indigo) , Windows Workflow Foundation (WinOE) and Cardspace ( the product formaly known as Infocard ) will be known as .Net Framework 3.0
It looks as though .NET 3.0 will be dependant on .NET 2.0 and should not download the runtime as well.
Soma previously has indicated a red/green model for classifying the .NET runtime and its supporting assemblies. Red assemblies include .NET itself and what was WinFX 3.0 , Red assemblys will be subject to a service pack style compatiblity and wherever possible backwards compatiblity. Green assemblys will be new and can be thought of as additions. One can only assume that over time Green assemblys will migrate to Red.
I can only assume that the LINQ addions will now come in .NET Framework 3.5.
I sorted a problem today that has been going on a while, how to load test data in unit tests without resorting to fixed paths.
We had an class library assembly and an associated test project in Visual Studio 2005 Team Developer Edition. The problem was the methods we needed to test (via a unit test) had to load some data from a file at run time.
In the 'real' application the file was loaded using the code
string filename = Application.StartupPath + \\datafile.dat";
This all worked fine, as the data file was included in the project and set to be 'contents' so copied with the assembly to the build directory. (It was not put in a resource bundle as the user many need to edit the file with other tools)
So I wrote my unit test for one of these methods, ran it and it failed (OK I know I should have written the test first to true TDD). The reason the test failed was because the Application.StartupPath was that of the running application's path, not the assembly under test i.e. Visual Studio in. C:\Program Files\Microsoft Visual Studio 8\Common7\IDE.
To fix this problem took two steps. The first was to alter the logic to load the data file to use the path of the assembly containing the function under test (not the path of the application that is calling the assembly)
string filepath = System.Reflection.Assembly.GetExecutingAssembly().Location;
filepath = filepath.Substring(0,filepath.LastIndexOf("\\"));
First I tested my 'real' application and it still worked, so I re- ran the test and it still failed. This for a while had me consfused until I realised that the way the tester instide Visual Studio works is that it copies the files to a special test directory, each test run will create a new directory.
I realised that the tester copies all the assemblies in the project - BUT NOT ANY OTHER CONTENTS FILES. The fix was to edit the test configuration file (found on the test menu, the the edit test run configuration file). On the deployment tab add the test data files. Once this is done the files will be copied with the assemblies and the test started to work.
Now to look to get the running of unit tests to be part of the build process.
I have been struggling for a while with sharing DLLs between web services and WinForm application. Many people have written on this. All the articles all tend to be deeply technical and hence fairly tough going. However I have found a quick easy solution from these various documents, this posting tries to given some background then the steps to get round the problem.
I am sure everyone else who has written on this thinks they have made the subject clearer, so my apologies now for any extra confusion I cause.
Background
In many cases good design calls for a shared DLL that contains common business objects. This shared DLL will be used by any number of applications. Historically a very common architecture; however, this design model hits some issues when we move to service orientated architecture (SOA) i.e. using web services.
The Four Tenets of Service Orientation state "Share Schema, Not Class", so if accessed via a web service our shared class should only be used as a schema. This means that any client application gets the data from the web service in the agreed schema, but none of the methods in the shared business object. For true SOA this should not be an issue, but think about this scenario………
You have a legacy application that you wish to use in a new SOA project. This application is written as a monolithic .NET WinForms application. The obvious route is to move the business logic to a shared DLL and write a new web service front end that other SOA applications to make use of.
However you can often find yourself in a position, due to the timescales or other restrictions, where you have to provide legacy support for an older front end. You can bet that there will be close binding of the business object into the GUI application that means you need to make use of the same type in the web service and the WinForm application.
This does not sound too much of a problem until you see the way that WSDL.EXE (or Visual Studio) creates proxies for the web services methods. An example will help......
The Example of the Problem
We have a class called
Class1 in a Class Library called
ClassLibrary1
namespace ClassLibrary1
{
public class Class1
{
public string FirstName;
public string Surname;
private DateTime DOB;
/// Empty constructor required for XML serialisation
public Class1() {}
/// A more useful constructor
public Class1(string f, string s, DateTime d)
{
FirstName = f;
Surname = s;
DOB = d;
}
/// Overloaded tostring, to prove we have a shared class
public override string ToString()
{
return FirstName + " " + Surname + " " + DOB.ToString("dd MMM yy");
}
}
}
We have a web service with the a web method that returns this class
Public Class Service : System.Web.Services.WebService
{
[WebMethod]
Public ClassLibrary1.Class1 Test1() {
Return New ClassLibrary1.Class1("Fred", "Bloggs", DateTime.Now)
}
}
We create a WinForms client and add a Web Reference to the web service. To call this web method we would write a code fragment like
localhost.Service ws = new WindowsApplication1.localhost.Service();
localhost.Service.Class1 c = ws.Test1();
You compile this and it works OK. As long as you access the members of the localhost.Service.Class1 class/schema e.g. FirstName, Surname and DOB.
The problems start if you wanted to access the overriden
ToString() method (or any other you created), it does not exist in schema based class in the WinForm application.
So you may think you do this, you add a reference to the
ClassLibrary1 in the WinForm application and edit web service call as below
localhost.Service ws = new WindowsApplication1.localhost.Service();
ClassLibrary1.Class1 c = ws.Test1();
When you compile the solution you get the error “
Cannot implicitly convert type 'WindowsApplication1.localhost.Class1' to 'ClassLibrary1.Class1'”.
And this is the stumbling block we have reached in the past.
Past Workarounds
To get round this I have previously written copy constructors in the shared DLL classes to allow a object to be create from the web service proxy class e.g.
Public Class1 (localhost.Service.Class1 c) {…}
I have also used reflection to copy data from one class to another by matching field/property names.
However neither of these felt right.
A new solution
When you read round the subject you find the
SchemaImporterExtension Technology Sample. This is a way to change how WSDL.EXE generates the proxy.; but this is not the way I am getting round the problem. I use a manual method.
After picking through all various postings there is a simple solution. Follow these steps:
- In the WinForm application add a reference to the shared DLL
- Add a web reference to the web service as you normally would In Visual Studio select new web reference
- At the top of the solution explorer panel you will should see a number of buttons, press the show all files one.
- You should not see files under the web reference Drill down until you find the reference.cs (or .vb) file and open it.
- Look for the proxy definition of the class in the shared DLL (in my example Class1), and comment it out (not in the real world there will probably be a number of classes to comment out)
- At the top of the reference.cs (or .vb) add a using statement for the shared DLL i.e. using ClassLibrary1 (or imports if VB.net)
- The solution should now compile
- The assignment ClassLibrary1.Class1 c = ws.Test1() should also work
- Remember you have to repeat this process each time you update the web reference.
So you now we have a means to alter the generated proxy, OK it is manual, but it is simple to do and simple to understand as to why it works.
If you want to automate the proxy generation then dig into the
SchemaImporterExtension and good luck.
The only major issue is that you still cannot passed collections across the web service boundary. However with generics in .NET 2.0 I don't see this as an issue. Use the following construct
///Internal collection
private List <ClassLibrary1.> jobs = new List<job<>();
///Access to the collection as a collection
///can be read only as this gives all require access
///As it is read only we know it will not be serialised
public List<ClassLibrary1.Job> JobsCollection
{
get
{
return jobs;
}
}
///The internal collection as a fixed length array
public ClassLibrary1.Job[] JobsArray
{
get { return jobs.ToArray(); }
set
{
jobs = new List<ClassLibrary1.Job>();
jobs.AddRange(value);
}
}
Summary
So what do we have? I think we have a fairly simple workround for a not uncommon real world architecture problem.
If you want to know more on the subject have a look at the following links, they helped me wrote this article.
SchemaImporterExtension Technology Sample
dotnetified - Using "Shared Types" assemblies with WebServices
http://www.microsoft.com/belux/msdn/nl/community/columns/jdruyts/wsproxy.mspx
Also I have attached a zip of my test project, so you can see it working
At DDD3 when I was demo'ing GUITester I said there was a problem with the tests that used multi-threading were failing. This used to work with .Net 1.1 but not with 2.0.
Due to the short notice of doing the session I did not have time to find the answer before the talk. However I have found it now. As I had guessed the issue was the increased security in .Net 2.0. I have done a quick dirty fix and this was to add the CheckForIllegalCrossThreadCalls line, as shown below
if
(_useThreading==true)
{
_obj =obj;
_mInfo = mInfo;
//when GUITester was updated from VS.Net 1.1 to 2.0 the following
//line had to be added as 2.0 stops CrossThreadCalls security checks
// this is not the best solution,
System.Windows.Forms.Form.CheckForIllegalCrossThreadCalls = false;
Thread worker = new Thread(new ThreadStart(ClickIt));
worker.Start();
Application.DoEvents();
} ......
to the DoTest() method in
ClickOpenFormTestBaseAttribute.cs.
This a dirty fix, I should really migrate to the new Backgroundworker class model
I have rebuilt the distribution file with this fix in it which can be found at http://www.blackmarble.co.uk/guitester/GUITesterSourceV2.1.zip
So I think the major gottas in this release are:
- the app.config file for an application under test is not read, there is a workround but this does involved a hard coded path in the sample application
- the integration with Visual Studio Team Developer edition runs all the GUITester tests in one VS Test. It stops at the first failing test
Well Developer Developer Developer Day 3 was interesting, a few months ago I had put in a proposal to speak at the event about GUITester, but it was not voted for, so I didn’t continue to work on the session.
So I arrived on Saturday expecting a relaxing day of sitting in the audience, and watching Robert pace up and down waiting to do his session on LINQ at the end of the day. However it did not work out like that.
On arriving I found that one of the speakers was sick, the one speaking on testing, so I was asked if I could do my session with a whole 5 minutes notice. OK I had been asked to bring along my presentation as a backup, but I hadn’t made any real effort to finished it; it was just around 15 slides of bullet points and an some source code.
Well I gave it a go seemed to go OK, but let us wait for the attendee feedback for the awful truth. However thanks you to everyone who said they enjoyed the session on the day.
Since getting back I have done some more work on the slide stack, got rid of the slides that said ‘put screen shot here’ and so hopefully made them a bit more useful based on the questions and conversations I had at DDD.
The stack can be found at http://www.blackmarble.co.uk/guitester/guitester overview.ppt and will be also available at the DDD site in the next few days.
I am speaking at Developer Developer Developer Day 3 at Microsoft in Reading tomorrow, on Linq.
I'll be providing an overview of up and coming features for CSharp 3.0, VB 9.0 and the .NET Language Integrated Query (LINQ). Covering features such as: anonymous types, lamda expressions, deep XML support, implicitly typed local variables and covering the general LINQ, DLinq and XLinq.
If you want to know more