3

I'm trying to write a visual studio extension that allows me to publish multiple web applications in a solution, similar to using the one-click publish feature on all the projects.

DTE2 service = (DTE2)this.GetService(typeof(DTE));
Projects projects = service.Solution.Projects;
SolutionBuild2 build = (SolutionBuild2)service.Solution.SolutionBuild;

foreach (Project project in projects)
{
   build.PublishProject("Release", project.UniqueName, true);
}

When I try to run this code, the only result in the output window is this:

Error: Object reference not set to an instance of an object.
========== Publish: 0 succeeded, 0 failed, 0 skipped ==========

... which doesn't tell me much. Is there a way to find out what's going wrong?

I also see there an interface IVsPublishableProjectCfg, but there doesn't seem to be any examples of how to use it.

Is there another way to programmatically publish web applications to a certain directory, similar to how the one-click publish feature works?

nivlam
  • 3,223
  • 4
  • 30
  • 39
  • It might help if you told us which line throws the exception – iandotkelly Aug 13 '11 at 23:44
  • have you tried stepping through using the debugger? – stack72 Aug 13 '11 at 23:45
  • It doesn't throw an exception. It just writes out that error message to the output window when I try to use the extension in the experimental Visual Studio. I can successfully step through all the lines without it throwing any kind of exception. – nivlam Aug 13 '11 at 23:46
  • and when you step through does it actually publish any of the projects? – stack72 Aug 13 '11 at 23:50
  • No, it doesn't. The output window in the experimental Visual Studio contains the error message and no projects have been published. – nivlam Aug 13 '11 at 23:51
  • @nivlam did you succeed eventually? – Norcino Jul 09 '20 at 16:26

3 Answers3

0

Use the msbuild.exe executable (which is how you're building anyway), pass your sln file as the project argument, and target the "Publish" target.

msbuild SlnFolders.sln /t:Publish

You can declare some properties in the command line or you can declare them statically using your own .targets file; reference this .targets file in your .csproj.

<Import Project="MyPublishCustomizations.targets" />

The contents of the .targets file might look like this:

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <Target Name="Publish">
    </Target>
    <!-- or .. -->
    <Target Name="CustomPublish" BeforeTargets="Publish">
    </Target>
</Project>

.. the <Target ..> XML could then have in it ..

<PropertyGroup>
    <MyCustomPath>\\our_server\our_share</MyCustomPath>
</PropertyGroup>
<Copy SourceFiles="$(OutDir)\*" DestinationFiles="$(MyCustomPath)" />

You can then define any other MSBuild tasks, even shell commands with <Exec ..>.

More generally on MSBuild here: https://msdn.microsoft.com/en-us/library/dd393573.aspx

Also if you insist on writing your publish logic in C#, you might consider the path described above and define a custom MSBuild task, i.e.

<ExecuteMyCustomTaskDefinedInCSharp ParameterA="Hello" ParameterB="World" />

Learn how here.

Jon Davis
  • 6,562
  • 5
  • 43
  • 60
0

Basically, it boils down to calling msbuild somehow like this:

msbuild.exe "MyProject.csproj" /p:PublishProfile="MyPublishProfile.pubxml" /p:DeployOnBuild=true /p:VisualStudioVersion="14.0"

I have written a PowerShell cmdlet for this, which I can call from the NuGet package manager console.

marsze
  • 15,079
  • 5
  • 45
  • 61
  • Could you give an example on how to run this command programmatically from C# using the cmdlet you specified? – Jacob Mar 20 '19 at 00:27
  • 1
    @Jacob As I mentioned, I created that cmdlet for calling msbuild from the *console*. If you want to call msbuild from C# it would probably be something like `Process.Start("msbuild.exe", "MyProject.csproj /p:PublishProfile=..."` – marsze Mar 20 '19 at 08:19
0

An alternate way to do this is to simulate clicking of the right-click "Publish" context menu item in Solution explorer, as in this similar question: DTE.ExecuteCommand and wait

Note that, as this is an asynchronous command, you will need to build in logic to tap into the post-publish events to iterate over your collection of projects (some detail on this is shown in one of the included answers).

Community
  • 1
  • 1
Dan Nolan
  • 4,733
  • 2
  • 25
  • 27