Démarrer une build à partir de l’environnement IDE
Les systèmes de projet personnalisés doivent utiliser IVsBuildManagerAccessor pour démarrer des builds. Cet article explique les raisons de cette exigence et décrit la procédure.
Builds et threads parallèles
Visual Studio autorise les builds parallèles, ce qui nécessite une médiation pour l’accès aux ressources communes. Les systèmes de projet peuvent exécuter des builds en mode asynchrone, mais ils ne doivent pas appeler de fonctions de génération à partir des rappels.
Si le système de projet modifie des variables d’environnement, il doit définir le NodeAffinity de la build sur OutOfProc. En raison de cette exigence, il n’est pas possible d’utiliser des objets hôtes, puisqu’ils exigent le nœud in-process.
Utiliser IVSBuildManagerAccessor
Le code ci-dessous présente une méthode qui peut être utilisée par un système de projet pour démarrer une build :
public bool Build(Project project, bool isDesignTimeBuild)
{
// Get the accessor from the IServiceProvider interface for the
// project system
IVsBuildManagerAccessor accessor =
serviceProvider.GetService(typeof(SVsBuildManagerAccessor)) as
IVsBuildManagerAccessor;
bool releaseUIThread = false;
try
{
if(accessor != null)
{
// Claim the UI thread under the following conditions:
// 1. The build must use a resource that uses the UI thread
// or,
// 2. The build requires the in-proc node AND waits on the
// UI thread for the build to complete
if(NeedsUIThread)
{
int result = accessor.ClaimUIThreadForBuild();
if(result != S_OK)
{
// Not allowed to claim the UI thread right now
return false;
}
releaseUIThread = true;
}
if(isDesignTimeBuild)
{
// Start the design time build
int result = accessor.BeginDesignTimeBuild();
if(result != S_OK)
{
// Not allowed to begin a design-time build at
// this time. Try again later.
return false;
}
}
}
bool buildSucceeded = false;
// perform project-system specific build set up tasks
// Create your BuildRequestData
// This assumes an IHostServices variable (hostServices) is set
// to your host services. If you don't use a project instance
// (you build from a file for example) then use another
// constructor.
BuildRequestData requestData = new
BuildRequestData(project.CreateProjectInstance(),
"myTarget", hostServices,
BuildRequestData.BuildRequestDataFlags.None);
// Mark your your submission as Pending
BuildSubmission submission =
BuildManager.DefaultBuildManager.
PendBuildRequest(requestData);
// Register the loggers in BuildLoggers
if (accessor != null)
{
foreach (ILogger logger in BuildLoggers)
{
accessor.RegisterLogger(submission.SubmissionId,
logger);
}
}
BuildResult buildResult = submission.Execute();
return buildResult;
}
// Clean up resources
finally
{
if(accessor != null)
{
// Unregister the loggers, if necessary.
accessor.UnregisterLoggers(submission.SubmissionId);
// Release the UI thread, if used
if(releaseUIThread)
{
accessor.ReleaseUIThreadForBuild();
}
// End the design time build, if used
if(isDesignTimeBuild)
{
accessor.EndDesignTimeBuild();
}
}
}
}