Can MSBuild (via Microsoft.Build namespace) load a project from memory? - msbuild

I'm working on a service that will download a .NET solution from a repository and build it (not unlike a continuous-integration build service). What I want to know is, using MSBuild programmatically via the Microsoft.Build namespace classes, can I can load the solution and project(s) into memory and build it without first saving them to disk in a temporary folder?
I'm still learning MSBuild and trying things, but I figure someone on Stack Overflow has tried this and has some insight.

I can't speak to whether this is a good idea or not, but it's possible to do.
ProjectInstance has a constructor that accepts a ProjectRootElement, which can be constructed via the Create(XmlReader) method. And as you may know, XmlReader can be attached to various Streams including a MemoryStream.
Here's how something like this may look:
var xmlReader = XmlTextReader.Create([your existing memory stream]);
var project = ProjectRootElement.Create(xmlReader);
var buildParams = new BuildParameters();
var buildData = new BuildRequestData(new ProjectInstance(project),
new string[] { "Build", "Your Other Target Here" });
var buildResult = BuildManager.DefaultBuildManager.Build(buildParams, buildData);

After researching MSBuild and all the involved components, it appears as though it's necessary to have the entire project set up on the file system before being able to build it. Unfortunately, what I'm trying to do just can't be done with the provided toolset.

Related

How to configure cache folder for SourceDiskCache?

I understand from the documentation that the SourceDiskCache folder cannot be configured using the XML configuration file and is only available "through code installation". However I can't figure out how!
I need to configure a custom folder. I have tried a few different things, with different results (both in Application_Start):
This doesn't throw an error, but uses the default folder (/cache)
var sourceDiskCachePlugin = new SourceDiskCachePlugin {VirtualCacheDir = "~/App_Data/cache"};
Config.Current.Plugins.GetOrInstall(sourceDiskCachePlugin);
This (and most other variations I have tried) throws the error "SourceDiskCache settings may not be adjusted after it is started."
new SourceDiskCachePlugin().Install(Config.Current);
Config.Current.Plugins.Get<SourceDiskCachePlugin>().VirtualCacheDir = "~/App_Data/cache";
How can I configure this?
Also, the documentation states that SourceDiskCache is in beta - is this still the case, and will XML configuration ever be available?
This would be the normal way to configure and install it:
var plugin = new SourceDiskCachePlugin()
plugin.VirtualCacheDir = "~/App_Data/cache";
plugin.Install(Config.Current);
If your code is running more than once, use Config.Current.Plugins.GetOrInstall(plugin); It's best if you only install the plugin during Application_Start.
However, approach #1 from your question should work equally well, as long as you've set the right NTFS permissions on App_Data.

How to access a specific resw resource file

For a Windows 8 application in C#/XAML I need to access a specific ressource file. In WP7 I used resx file and now it seems that we need to use resw file. It's not a language resource file.
My file is called ConfigResources.resw, it just contains one key : "ConfigFile" and a value : a string.
How can I access it from my code? I tried this without any luck:
var storedConfigFile = Application.Current.Resources["ConfigResources"];
Then how can I edit the value of the key inside from my code?
Thank you
I created a project on CodePlex recently called ResW File Code Generator that simplifies using localized resources in code in windows store app project. It's a custom tool that automatically generates and updates a helper class similar to what ResX files used in the full version of .NET
According to here, you need to use the Windows.ApplicationModel.Resources.ResourceLoader and the Windows.ApplicationModel.Resources.Core namespace provide interaction with resw files.
It should look something like this:
var loader = new Windows.ApplicationModel.Resources.ResourceLoader();
var text = loader.GetString("Farewell");
Alternately, if you're creating a cross-platform library you could also do it using the System.Resources.ResourceManager:
Although the System.Resources.ResourceManager class is included in the
.NET for Windows Store apps, we do not recommend its use. Use
ResourceManager only in libraries that are developed as Portable Class
Library projects and that target multiple platforms.
Like this from here:
ResourceManager rm = new ResourceManager("Strings", typeof(Example).Assembly);
string timeString = rm.GetString("TimeHeader");
There is a sample that shows the different ways to read the resources in WinRT apps (i.e. from resw files).

Load App.Config at runtime

I am creating a test project using IBM's Rational Functional Tester(RFT) tool(we are using the VB version of it and it only supports till .net 3.5).In this project I am making all database queries using the entity framework.The problem is entity framework retrieves "Metadata", "Connection String" etc from the App.Config file,and RFT won't let me add a App.Config to the project(I guess it is designed that way -- I googled adding an App.Config file to an rft project and came up with nothing), and the Entity Framework requires you to have the app.config file at the entry point.I was building the string to pass to entity framework in code, but my boss really does not like that.
So looking at my options I think any of the below 2 solutions should suffice(or if you have a better solution please advise).
Is their any way to load an App.Config during run-time.
Is their any way to add an App.Config to an RFT project(should
really be my first question).
If you guys could help me with this it will be great.
Thanks in advance.
After a lot of research i found you can load the config file at runtime by using,
ExeConfigurationFileMap map = new ExeConfigurationFileMap();
map.ExeConfigFilename = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, Assembly.GetExecutingAssembly().ManifestModule.Name + ".config");
Configuration config = ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None);
var configValue = config.ConnectionStrings.ConnectionStrings["refrenceNameinConfigfile"].ConnectionString;
just make sure your App.config is within the folder where your exe file is running

Triggering EF migration at application startup by code

Using Entity Framework Migrations (Beta1), using Update-Database command is all good during development.
But when the application is running on some customer's server somewhere, I really want my application to automatically update it's database schema to the latest version when it's started.
Is this possible? Documentation is scarce.
They aren't providing a way to do this until RTM, at which point they have promised a command line app and a msdeploy provider.
Source: http://blogs.msdn.com/b/adonet/archive/2011/11/29/code-first-migrations-beta-1-released.aspx
Of course not being satisfied with that, the powershell command is stored in the packages directory and is plain text, it appears to just load up an assembly called EntityFramework.Migrations.Commands stored in the same directory.
Tracing through that assembly I came up with the following
public class MyContext : DbContext
{
static MyContext()
{
DbMigrationsConfiguration configuration = new DbMigrationsConfiguration() {
MigrationsAssembly = typeof(MyContext).Assembly,
ContextType = typeof(MyContext),
AutomaticMigrationsEnabled = true,
};
DbMigrator dbMigrator = new DbMigrator(configuration);
dbMigrator.Update(null);
}
}
UPDATE: after a bit of experimentation I figured out a few more things
Performing an update in the static constructor for your context is bad as it breaks the powershell commands, much better off adding the code to application startup another way (Global.asax, WebActivator or Main method)
The above code only works when using AutomaticMigrations, you need to set the MigrationsNamespace for it to pickup on manually created migrations
The configuration class I was creating should already exist in your project (added when you install the migration nuget package), so just instantiate that instead.
Which means the code is simplified to
DbMigrator dbMigrator = new DbMigrator(new NAMESPACE.TO.MIGRATIONS.Configuration());
dbMigrator.Update(null);
Another options for this issue is to add
Database.SetInitializer<MyContext>(new MigrateDatabaseToLatestVersion<MyContext, NAMESPACE.TO.MIGRATIONS.Configuration>());
line to your Global.asax Application_Start method.

CCNet API, docs?

I want to query my CCNet server to find out the status of the builds. I've heard rumor that there's a (ReST?) API of sorts, but I can't seem to find any documentation for it.
Is there any documentation for it, or do I need to download the CCNet source code and start reading?
EDIT: I found the endpoint /XmlStatusReport.aspx, which gives an XML overview of all projects. The same filename in any folder gives exactly the same response, though, so I'm afraid that might be the only API there is.
As an alternative to the XML you already mentioned yourself, you could use remoting as the CCTray app does. If you reference ThoughtWorks.CruiseControl.Remote.dll form the CruiseControl.NET\server folder you can instantiate CruiseServerRemotingClient and use it to retrieve information from the server.
The following snippet prints out the list of projects on the server and their build statuses:
CruiseServerRemotingClient client = new CruiseServerRemotingClient("tcp://ccnetserver:21234/CruiseManager.rem");
ProjectStatus[] statusList = client.GetProjectStatus();
foreach (ProjectStatus status in statusList)
{
Console.WriteLine("{0}: {1}", status.Name, status.BuildStatus);
}
You could also retrieve the log for the latest build in XML format as follows:
string buildName = client.GetLatestBuildName("Jasenje");
Console.WriteLine(client.GetLog("Jasenje", buildName));
I haven't managed to find any real documentation for the API but at least there are XML comments with brief descriptions of methods and parameters.