Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / Visual Studio.NET / Extensibility / May 2007

Tip: Looking for answers? Try searching our database.

Building assembly dynamically during build/rebuild

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Vin - 11 May 2007 17:49 GMT
Hi,

I am attempting to build an assembly from a C# project in such a way
that I build the assembly directly using codedom which relies on my
xml files that are in the project.

To put it more clearly.
1. My c# project (a classlibrary type) has say 10 xml files
2. Using these 10 xml files I dynamically want to generate C# classes
using codedom and build them in to a resulting assembly for this C#
project.
3. This should happen whenever the developers build/rebuild the
project. The bin/debug or bin/release wherever the assembly should go,
must have this dynamically generated assembly.

The part of generation of assembly separately using codedom has
already been done - which is a console app right now. I want to run
this whenever developers build/rebuild this project.

Please suggest directions/code/ideas, appreciated.
justncase80 - 11 May 2007 23:12 GMT
This could get a little tricky, depending on how fully integrated you
want this. I think the trick is essentially creating a custom MSBuild
task. You would put a call to that task in your .csproj file and when
you build the project it would pass in the paths to the various xml
files, then you could do whatever you wanted after that. In your case
build an assembly based on the xml files.

If you look in a .csproj file you'll see a chunk of xml for importing
"$(MSBuildBinPath)\Microsoft.CSharp.targets", which will probably
point to "C:\WINDOWS\Microsoft.NET\Framework
\v2.0.50727\Microsoft.CSharp.targets". If you pop that file open
you'll see a target with the name "CoreCompile" which takes in a
variety of paramters then calls "Csc". What you need to do is create
your own targets file that looks pretty much exactly the same except
instead of calling "Csc" it'll call "MyXmlGenerator" task which you'll
need to create yourself. Put the targets file in the correct place and
then change the .csproj file to import your custom targets file
instead of the "Microsoft.CSharp.targets". A good place to put all of
this is "C:\Program Files\MSBuild\MyXmlGenerator\". Put the targets
and all of your assemblies in there.

I have done something similar to this only more extensively with a
full on language service and project type (which hopefully you won't
have to do for now) and here is a link to an example (http://
www.codeplex.com/nbusiness) :

[The targets file]
http://www.codeplex.com/NBusiness/SourceControl/FileView.aspx?itemId=291876&chan
geSetId=22187


[The custom Task]
http://www.codeplex.com/NBusiness/SourceControl/FileView.aspx?itemId=291875&chan
geSetId=22187


[The custom .csproj]
http://www.codeplex.com/NBusiness/SourceControl/FileView.aspx?itemId=272443&chan
geSetId=22187


In my case it's "esproj" but you should be ok with just using csproj
files and changing the build target. This is the important line there:
<Import Project="$(MSBuildExtensionsPath)\NBusiness\ESharp
\2.0\ESharp.targets" />

Ok, good luck!

P.S. What are you generating with your XML files? I'd be interested in
knowing. Thanks!
Mirko Matytschak - 12 May 2007 11:58 GMT
Hi,

as far as I understand, you have yet a console app tool doing exactly what
you want and all you want to do is to do it automatically during a build.
Write an Add-in which handles the OnBuildProjConfigDone event or one of the
other events fired during the build process:

// Let BuildEventHandler be the class which actually handle the events
buildEventHandler = new BuildEventHandler(applicationObject);

Events events = applicationObject.Events;
BuildEvents buildEvents = events.BuildEvents;

buildEvents.OnBuildBegin += new
_dispBuildEvents_OnBuildBeginEventHandler(buildEventHandler.OnBuildBegin);

buildEvents.OnBuildDone += new
_dispBuildEvents_OnBuildDoneEventHandler(buildEventHandler.OnBuildDone);

buildEvents.OnBuildProjConfigBegin += new
_dispBuildEvents_OnBuildProjConfigBeginEventHandler(buildEventHandler.OnBuildProjConfigBegin);

buildEvents.OnBuildProjConfigDone += new
_dispBuildEvents_OnBuildProjConfigDoneEventHandler(buildEventHandler.OnBuildProjConfigDone);

Now you can use the Process class to launch the external program. See the
example below. Note, that if your launched process generates a certain
amount of output, you need to use a worker thread to read the stdout and
stderr, otherwise it
will block. This is demonstrated in the sample below. Derive you own class
from the
ConsoleProcess class for each program you want to launch.

Hope that helps.

Regards,
Mirko
www.netdataobjects.com

using System;
using System.Text;
using System.Globalization;
using System.IO;
using System.Threading;
using System.Diagnostics;

namespace ...
{

public class ConsoleProcess
{
StreamReader outReader;
StreamReader errReader;
string stdout = string.Empty;
bool verboseMode;

public string Stdout
{
   get { return stdout; }
}
string stderr = string.Empty;
public string Stderr
{
   get { return stderr; }
}
public ConsoleProcess(bool verboseMode)
{
   this.verboseMode = verboseMode;
}
public int Execute(string exeFileName, string parameters)
{
   return Execute(exeFileName, parameters, null);
}
public int Execute(string exeFileName, string parameters, string
workingDirectory)
{
if (this.verboseMode)
   Console.WriteLine("Execute: " + "\"" + exeFileName + "\" " +
parameters);
ProcessStartInfo psi = new ProcessStartInfo(exeFileName, parameters);
psi.CreateNoWindow = true;
psi.UseShellExecute = false;
if (workingDirectory != null)
psi.WorkingDirectory = workingDirectory;
psi.RedirectStandardOutput = true;
psi.RedirectStandardError = true;
psi.StandardErrorEncoding =
Encoding.GetEncoding(CultureInfo.CurrentCulture.TextInfo.OEMCodePage);
psi.StandardOutputEncoding =
Encoding.GetEncoding(CultureInfo.CurrentCulture.TextInfo.OEMCodePage);
System.Diagnostics.Process proc = System.Diagnostics.Process.Start( psi );
this.errReader = proc.StandardError;
this.outReader = proc.StandardOutput;
Thread threadOut = new Thread(new ThreadStart(ReadStdOut));
Thread threadErr = new Thread(new ThreadStart(ReadStdErr));
threadOut.Start();
threadErr.Start();
proc.WaitForExit();
while (threadOut.ThreadState != System.Threading.ThreadState.Stopped
|| threadErr.ThreadState != System.Threading.ThreadState.Stopped)
   Thread.Sleep(1);
return proc.ExitCode;
}

void ReadStdOut()
{
   stdout = outReader.ReadToEnd();
}
void ReadStdErr()
{
   stderr = errReader.ReadToEnd();
}

}
}

> Hi,
>
[quoted text clipped - 16 lines]
>
> Please suggest directions/code/ideas, appreciated.
Vin - 15 May 2007 19:18 GMT
Thanks you guys that helps a lot.

justncase80, I am most likely going to build my custom target file and
use it. Thanks for your suggestion, I almost forgot I could do this
way.
I am generating C# classes out of Xml and then producing a
classlibrary that has set of classes and properties which then
developers use to create applications playing with them with their own
logic. Sounds interesting. Isn't it?

Mirko thanks for your step-by-step instructions with code. Appreciate
it.

Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.