PowerPoint Slides for my Code Camp Talk on Reactive Extensions
15 April 10 03:41 PM | jons | (Comments Off)   

See the attached file.  It is a zip file to keep my blogging server happy.  Source code was just posted in a post earlier today.

 

 

Attachment(s): CodeCamp2010Spring.zip
Source Code for Reactive Extensions Code Camp Talk
15 April 10 03:34 PM | jons | (Comments Off)   

I have attached the source code from my Code Camp talk as a zip file.  You will have to download and install the Reactive Extensions from the following web page:

http://msdn.microsoft.com/en-us/devlabs/ee794896.aspx

There are different versions based upon the version of .NET that you are using.  The code was developed against .NET 3.5 SP1. 

I will attach the PowerPoint slides in a subsequent post.

Technorati Tags: ,,
Attachment(s): ReleasedMaze.zip
How to get MSTest to Deploy a Subdirectory for Testing (Revised)
15 July 09 01:26 PM | jons | 1 Comments   

I am working on a project that uses MSTest for unit (and integration) testing.  In the main project (Win Forms) there is a subdirectory that holds some data files that are needed by the program and several of the unit tests.  Remember that MsTest creates a “shadow subdirectory” for each test run that contains everything that the test needs to run and reports that path as the base application path.  For our tests to run, we need to create a Data subdirectory that holds copies of these data files.  To make these data files available to the unit tests, we added some lines to the solution testrunconfig file:

   1: <Deployment>
   2:     <DeploymentItem filename="DeploymentMain\Data\File1.txt" outputDirectory="Data" />
   3: </Deployment>

The intent here was that File1.txt (plus several other similar files) would be copied to the Data subdirectory under the out directory for the test run.  It did not happen.  MsTest copied the file directly to the Out directory and did not create a Data subdirectory.  All of the unit tests that depended upon the existence of a fully stocked Data subdirectory failed. 

I looked for answers on the web with no luck.  To make a long morning’s work short, I created a small test solution and tried all of the variations that I would think of.  I finally stumbled on to the following "trick”: you cannot copy a file to a subdirectory but you can copy a subdirectory to a subdirectory.  The following deployment lines accomplish just that:

   1: <Deployment>
   2:   <DeploymentItem filename="DeploymentMain\Data\" outputDirectory="Data" />
   3: </Deployment>

Note that the back slash at the end of the file name attribute value is essential as is the “outputDirectory” attribute for this to work.

UPDATE: An additional point: it seems that the directory lines need to be first in the <Deployment> section.  I had a situation where the line was not first and it was as if the “outputDirectory” attribute was not there. 

And now you know.

Problems in Switching a Virtual Machine from VirtualPC to Hyper-V
15 June 09 10:55 AM | jons | (Comments Off)   

I do a lot of development using VirtualPC images.  It keeps my base laptop relatively clean and allows my VPC images to join client domains.  Recently, I rolled on to a project that had a very large VHD file.  The file was too large to host on my laptop, even after compressing the VHD.  Initially, I created a VPC with the VHD hosted on a USB external drive but the performance was simply not acceptable.  The project did have a spare machine running Windows Server 2008 R2 Enterprise, with the Hyper-V role installed.  Luckily, the VHD format is common to VPC and Hyper-V. 

I created a Hyper-V virtual machine based upon the VHD.  Everything worked except for the mouse.  After a lot of banging around, I came to the realization that the VPC extensions were not compatible with the Hyper-V setup.  In the end, I had to take the VHD image back to VPC, un-install the VPC extensions, return the VHD to Hyper-V, and install the Hyper-V extensions to get the mouse to work properly.  Now, everything is goodness.

Technorati Tags: ,,
Test Post after Update to Windows 7
08 June 09 04:52 PM | jons | (Comments Off)   

See above.

Spring 2009 Code Camp Software Solution
19 April 09 07:24 PM | jons | (Comments Off)   
More than a bit late but this has been a very busy time for me: this is the zip file containing the actual code as a VS2008 Solution.
Attachment(s): CodeCampSolution.zip
Spring 2009 Code Camp Presentation
19 April 09 07:15 PM | jons | (Comments Off)   

More than a bit late but this has been a very busy time for me: this is the zip file containing the presentation. 

 

More on the Virtual PC Install Issues
29 January 09 10:15 AM | jons | (Comments Off)   

Yesterday, I was able to install one of the packages that was trapped in an endless “disk resources” loop using the following sequence:

  1. Un-install Virtual Machine Additions.
  2. Install package 1.
  3. Re-install virtual Machine Additions.
  4. Realize that I forgot to install package 2.
  5. Slap forehead! 
  6. Install Package 2.

This would suggest that the issue with the Virtual Machine Additions is some how related to the usage of the additions.  In the above case, I was working with a fresh boot of the virtual machine and, as far as I can remember, did not go outside of of the virtual machine environment, meaning that I did not move my mouse to the physical machine to check email during this process.  (Email was running on the physical laptop during this entire time.)

Technorati Tags: ,,
Software Installation Problems on Virtual PC Running Windows Server 2008
28 January 09 11:36 AM | jons | (Comments Off)   

I am working at a client that requires the consultants to work on a PC that is a member of their domain.  I and the other consultants do not what to join our physical laptops to their domain.  Enter Virtual PC 2007 SP1.  Most of us have installed Windows Server 2008 on the Virtual PC image and then joined that virtual image to the clients domain.  This is a very workable solution, with one minor problem.

The problem comes in trying to install certain packages.  The installer gets to the point where it is ‘determining disk requirements”.  It puts up a dialog box with the message "Please wait while the installer finishes determining your disk space requirements."  In normal circumstances, this goes up and comes down in less than a blink of an eye.  In my situation (and several others), the dialog box comes up and stays, and stays for a very loooooooooooong time.

Searching the web found others with the same problem.  One suggestion was to run the install package using the follow command line:

msiexec /i filename.msi

That did not help me.  One of the packages that I was trying to install was the indispensible TestDriven.Net.  It is an exe file and it just hung on the “please wait” message.

OK, I have made you wait long enough for an answer.  I stumbled on this by accident.  I un-installed Virtual Machine Addins, tried the install of TestDriven.NET and it worked.  I re-installed the Addins and it failed in exactly the same way.  I do not know if this will solve the problem for every install but it does provide a ray of hope.

T4 Parameter Passing: Redemption, Sweet Redemption
03 November 08 09:54 AM | jons | (Comments Off)   

In the play and subsequent movie, A Streetcar Named Desire, the playwright Tennessee Williams has the character Blanche DuBois say, “I've always depended on the kindness of strangers.”  That is also quite applicable to the technical community.  I asked a question on the MSDN forums and Oleg V. Sych at http://www.olegsych.com/ provided the answer: 

----------------------------------------------------------------------------

Jon,
I think that changing your host class to inherit from MarshalByRefObject should resolve the serialization issue and allow you to access the host from a "hostspecific" template running in a new AppDomain.

 


Oleg

----------------------------------------------------------------------------

I tried it and it worked.  Thanks, Oleg.

This is kind of stupid on my part.  As soon as I read the above answer, I realized what was going on.  The error message kept saying that the T4 engine class was not serializable.   Intellectually, I knew that I must be doing something wrong but I kept thinking that Microsoft must have screwed up.  It turns out the the engine class was serializable but it was holding a reference to something, my custom host class, that was not capable of moving across the remoting boundary to the other (newly created) AppDomain.  In my defense, I have not done any serious remoting for several years.  Oleg’s answer brought a lot of that experience flooding back. 

What I have been doing is thrashing, trying to find an answer.  What I have to do now is to drop back into a unit testing mode to get all of the piece parts working.  I suppose that I should add one or more unit tests on the use of AppDomains.  This has been an interesting distraction, but still a distraction.

T4 Parameter Passing: Problem Isolation
01 November 08 07:03 PM | jons | (Comments Off)   

I have been tracking down why I could not get my custom host for T4 to work.  I now know the specific condition that causes the failure and that knowledge leads to a short-term work around.  This is the question that I posted on the MSDN forums on Visual Studio extensibility:

--------------------------------------------------------------------------------------

As I noted in an earlier post :Source Code for a Working Implementation of ITextTemplatingEngineHost, I am trying to build a custom host for T4.  The answer to my query about available source code for a working custom host lead to the code in the MSDN documentation.  That code worked.  Using that code as a baseline, I was able to isolate the cause of my problem.

 
My situation is that I want to expose the custom host in the template file.  Following the example in MSDN, I wrote the following code for the ProvideTemplatingAppDomain:

   1: public AppDomain ProvideTemplatingAppDomain(string content)
   2: {
   3:     // This host will provide a new application domain each time the 
   4:     // engine processes a text template.
   5:     // -------------------------------------------------------------
   6:     return AppDomain.CreateDomain("Generation App Domain");
   7: }

This works fine if I supply the current AppDomain and include the "hostspecific=true" parameter on the template directive.  It also works just fine if I supply a new Appdomain but do not include the "hostspecific=true" parameter.  It DOES NOT WORK if I supply a new AppDomain and also include the "hostspecific=true" parameter.  The issue is that the Engine class is not serializable.  Apparently, it must be serializable to move across the AppDomain boundary.


I have to specify the "hostspecific=true" parameter to make the functionality that I am trying to provide work.  In the short term, I can work around this by re-using the AppDomain, but I wonder how that will affect Visual Studio performance.  Am I right in thinking that the custom tool will run in a separate process space?  If it does, the AppDomains will only live for the duration of the code generation process; there would be no accumulation in memory.  But the author of the MSDN sample took some effort to mention that creating a searpate AppDomain was a good idea.  Is there a way to get a new AppDomain and "host specific" at the same time?


Jon Stonecash

--------------------------------------------------------------------------------------

I am going to proceed on the basis of re-using the current AppDomain, keeping an eye out for any performance hits.  Maybe someone will take notice of my question and provide a longer-term approach.

T4 Parameter Passing: Hacking Text Transformation
30 October 08 11:14 AM | jons | (Comments Off)   

In my last post, T4 Parameter Passing: You Can’t There from Here, I complained that the TextTransformation class did not have direct knowledge of the host.  I tried a couple of ways to get around this.  Before I do that, I need to list some definitions:

  • Grandparent class: This is the TextTransformation class in the .NET library class that all templates must inherit from.
  • Parent class: In this situation, this is the class that inherits from the Grandparent class and is the parent class to the templates that we intend to create.  This is the class that provides some standard services such as locating the control.xml file.
  • Child class: Again, in this situation, this is the class created by the custom tool.  This is the class that actually contains the statements to generate the application code from some kind of model data.  To make use of the services in parent class, this class must inherit from the parent class by specifying the “inherits” parameter with a value that is the full name of the parent class.  Note that the template must also contain an assembly directive that points to the assembly that contains the parent class and the project that contains the template must also contain a reference to that same assembly.

First, in the parent class, I added some code to hold the reference to the host.  This is a duplicate of the code that would have been added to the generated child class if the “host specific” parameter was added to the template directive.

   1: private Microsoft.VisualStudio.TextTemplating.ITextTemplatingEngineHost hostValue;
   2: public virtual Microsoft.VisualStudio.TextTemplating.ITextTemplatingEngineHost Host {
   3:     get {
   4:         return this.hostValue;
   5:     }
   6:     set {
   7:         this.hostValue = value;
   8:     }
   9: }

The hope here was that Visual Studio would somehow “see” the property and store the reference.  The problem is that it appears that Visual Studio does not store the reference unless the “host specific” parameter is present on the template directive and when that parameter is present, it adds a duplicate of the above code to the generated child class overriding the above code in the intermediate base class.  You can’t get there from here.  Alright, to be fair, I could not figure out a way to make this work.  Your mileage may vary, etc.

Second, Since I could not figure out how to store the host reference directly in the parent class, I decided to use reflection in the parent class to find the method in the generated child class:

   1: private ITextTemplatingEngineHost m_Host = null;
   2: private ITextTemplatingEngineHost GetHost()
   3: {
   4:     if (m_Host == null)
   5:     {
   6:         Type effectiveType = this.GetType();
   7:         PropertyInfo info = effectiveType.GetProperty("Host", typeof(ITextTemplatingEngineHost));
   8:         if (info == null)
   9:         {
  10:             throw new InvalidOperationException("Could not find Host property");
  11:         }
  12:         m_Host = info.GetValue(this, null) as ITextTemplatingEngineHost;
  13:         if (m_Host == null)
  14:         {
  15:             throw new ArgumentNullException("Host property does not have a value");
  16:         }
  17:     }
  18:     return m_Host;
  19: }

This actually works just fine.  This is a little weird, but I have done worse things.  This assumes that the template directive for the template has the “host specific” parameter set to true; if it is not set, the above code will throw an exception.  I also have some logic in the parent class to find the Control.XML file, given the reference to the host file.  In this case, it is finding the file in the same sub-directory that holds the template.  Obviously, I could make this logic more complicated and search up and down the file hierarchy, or look up a registry entry, or make a web service call, or yada yada yada.

I placed the DLL file holding the parent into the GAC but you could also use an absolute or relative path to get to the assembly.  I used the GAC because the sample code that I based my logic on did that, but in the interests of making the logic in the template as simple and un-coupled as possible I think that the GAC solution is the way to go.  Again, your mileage may vary.

T4 Parameter Passing: You Can’t There from Here
29 October 08 11:51 AM | jons | (Comments Off)   

The inheritance from TextTransformation is not going to work, at least not directly.  The TextTransformation class has no knowledge of the template location or the host.  I suppose that I could force the template to use the hostspecific="True" parameter on the template directive and pass the host up to the custom class that inherits from the TextTransformation class or use reflection to find the Host property in the derived child class created by the custom tool.  Ugly, ugly, ugly. 

T4 Parameter Passing: Withdrawal
29 October 08 11:14 AM | jons | (Comments Off)   

I found an article about T4: Extending the Generated Template Class by Mike Pagel.  I want to see if this works.  If it does, I can use this approach for the moment while I take a long-term poke at the custom “host” approach.

Technorati tags: Code Generation, T4

T4 Parameter Passing: Retrospective
29 October 08 10:41 AM | jons | (Comments Off)   

I have banged my nose on trying to build a custom tool that does the same thing as the TextTemplatingFileGenerator custom tool that drives the T4 code generation process but is smart about how to find the XML files that I am using to drive my code generation process.  The problem seems to be in the T4 “host” class that implements the ITextTemplatingEngineHost  interface.  I built a simple console application to invoke the T4 engine passing in the reference to the “host” class that I wrote.  That eliminates any of the custom tool logic.  The code throws an exception (listed below).  I could pursue the bug (and I may end doing just that) but I wanted to take a step back and reflect on what I want to accomplish.  (There is nothing less useful than dogged determination to do the wrong thing.) 

What I specifically want to accomplish is to use T4 templates to generate application code from a combination of a control file (that is application specific) and a model file (that might well span several applications).  Right now, I am using hard-coded references to the files in the templates.  That works for the initial application but does not promote re-usability.  I specifically want to eliminate any hard-coded references to the files.

There seem to be several ways that I could achieve this goal.  First, I could put the logic to find the XML files into worker templates that I could include in each of the code generation templates; the templates are really just an appreviated programming language that are transformed into executable packages that generate the final code (very Zen like).  Second, I could split each template into a thicker worker template that did the work based upon parameters passed to it and was ignorant of the file locations and a thinner controlling template that invoked the worker template, passing the locations of the source XML files as parameters.   Third, I could embed the file location logic into a class that inherits from TextTransformation class; I could define properties and methods in that class that the worker templates could invoke to get the model data.  Fourth, I could build a custom tool to replace the TextTemplatingFileGenerator custom tool that had all of the logic.

I went down the custom tool route because it seemed like this approach would be cleaner and would allow me to expand the logic into the MsBuild process or into a GUI-based tool.  I really like the way that the custom tool works in the stage of building the templates.  I could build an installer so that everyone on the team could have access to the custom tool.  Somewhat of a hassle but the hassle only occurs once per machine.  The custom tool would find the control file by convention: starting with “look for a file named “Control.XML” in the same directory as the template”.  The only problem is that I have not been able to get the custom host to work. 

I wrote the code based on the example code in the MSDN article about ITextTemplatingEngineHost) but it throws the exception listed below.  I do not entirely trust the source of the code because the code was clearly out of date with respect to the .NET 3.5 version of the interface, specifically it was missing a couple of methods.  I have put out feelers to see if there is source code for a working example.  The other step would be to pull up Reflector on the DSL console utility program.  Still another step would be to back away from this approach and go down the inheritance route.  I hate to give up on the custom tool.  That route seems like the one to follow (at least until Oslo comes along).  The only thing to do for the moment is to use Reflector while waiting for the feelers to be answered.

 

ErrorGeneratingOutput
C:\_Projects\Blog\CodeGeneration\CustomTemplateToolDriver\Test.tt(-1,-1) : error
: An Exception was thrown while running the transformation code. The process ca
nnot continue.  The following Exception was thrown:
System.Runtime.Serialization.SerializationException: Type 'Microsoft.VisualStudi
o.TextTemplating.Engine' in Assembly 'Microsoft.VisualStudio.TextTemplating, Ver
sion=9.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' is not marked as
serializable.

Server stack trace:
   at System.Runtime.Serialization.FormatterServices.InternalGetSerializableMemb
ers(RuntimeType type)
   at System.Runtime.Serialization.FormatterServices.GetSerializableMembers(Type
type, StreamingContext context)
   at System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitMemberI
nfo()
   at System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitSeriali
ze(Object obj, ISurrogateSelector surrogateSelector, StreamingContext context, S
erObjectInfoInit serObjectInfoInit, IFormatterConverter converter, ObjectWriter
objectWriter)
   at System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.Serialize(O
bject obj, ISurrogateSelector surrogateSelector, StreamingContext context, SerOb
jectInfoInit serObjectInfoInit, IFormatterConverter converter, ObjectWriter obje
ctWriter)
   at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Write(WriteObj
ectInfo objectInfo, NameInfo memberNameInfo, NameInfo typeNameInfo)
   at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Serialize(Obje
ct graph, Header[] inHeaders, __BinaryWriter serWriter, Boolean fCheck)
   at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(S
tream serializationStream, Object graph, Header[] headers, Boolean fCheck)
   at System.Runtime.Remoting.Channels.CrossAppDomainSerializer.SerializeMessage
Parts(ArrayList argsToSerialize)
   at System.Runtime.Remoting.Messaging.SmuggledMethodCallMessage..ctor(IMethodC
allMessage mcm)
   at System.Runtime.Remoting.Messaging.SmuggledMethodCallMessage.SmuggleIfPossi
ble(IMessage msg)
   at System.Runtime.Remoting.Channels.CrossAppDomainSink.SyncProcessMessage(IMe
ssage reqMsg)

Exception rethrown at [0]:
   at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage req
Msg, IMessage retMsg)
   at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgDa
ta, Int32 type)
   at Microsoft.VisualStudio.TextTemplating.TransformationRunner.RunTransformati
on(String fullClassName, String baseClassName, String[] importedNamespaces, Stri
ng[] references, String source, String inputFile, Boolean debug, SupportedLangua
ges language, IDictionary`2 languageOptions, IFormatProvider format, ITextTempla
tingEngineHost host, Boolean cacheAssemblies, String& result)
   at Microsoft.VisualStudio.TextTemplating.Engine.CompileAndRunCode(String gene
ratorCode, ITextTemplatingEngineHost host, TemplateProcessingSession session)

More Posts Next page »