Current type of the build action from Visual Studio - Microsoft.VisualStudio.Shell.Interop

6.9k views Asked by At

In some extension we implement the IVsUpdateSolutionEvents2 and IVsSolutionBuildManager2 used for registering caller with the AdviseUpdateSolutionEvents

For example, this called before any build actions have begun:

public int UpdateSolution_Begin(ref int pfCancelUpdate)
{
    ...
}

However, also need getting the status or type of the current build action, for example: build/rebuild/clean/deploy

Available & known variants:

BuildEvents

With the Events.BuildEvents i can subscribe to OnBuildBegin, for example:

_buildEvents.OnBuildBegin += new _dispBuildEvents_OnBuildBeginEventHandler((vsBuildScope Scope, vsBuildAction Action) => {
    buildType = (BuildType)Action;
});

and use the buildType in any places, because the vsBuildAction provides all the necessary information

but the UpdateSolution_Begin / UpdateSolution_StartUpdate called first as priority with advising method, and as result the buildType sets too late..

also we can use this OnBuildBegin instead of UpdateProjectCfg_Begin / UpdateSolution_StartUpdate, but our handling is also needed as soon as possible with priority caller

IVsUpdateSolutionEvents4

The IVsUpdateSolutionEvents4.UpdateSolution_BeginUpdateAction provides the dwAction and fired before every update action begins during solution build - before the first UpdateProjectCfg_Begin

it's exactly what i need! because dwAction i can check with the VSSOLNBUILDUPDATEFLAGS

However :( it appeared in VS2012, our extension supports the VS2010 and higher... so need also variant for 2010 version

UpdateProjectCfg_Begin

The IVsUpdateSolutionEvents2.UpdateProjectCfg_Begin also provides the dwAction (see also VSSOLNBUILDUPDATEFLAGS) and available for 2010 version, however it's the same as first BuildEvents variant - it's too late for handling (and not quite suitable for our task)

Question

I can't find documentation for this, however the VSSOLNBUILDUPDATEFLAGS available for VS2010, so i think should be variant for getting this as current state of the build action, e.g as with __VSHPROPID and GetProperty for IVsHierarchy etc...

is it possible ? or i can only with OnBuildBegin subscription o_O


upd1:

__VSHPROPID4

found with \VisualStudioIntegration\Common\Inc\vsshell100.h:

enum __VSHPROPID4
    {   VSHPROPID_TargetFrameworkMoniker    = -2102,
    VSHPROPID_ExternalItem  = -2103,
    VSHPROPID_SupportsAspNetIntegration = -2104,
    VSHPROPID_DesignTimeDependencies    = -2105,
    VSHPROPID_BuildDependencies = -2106,
    VSHPROPID_BuildAction   = -2107,
    VSHPROPID_DescriptiveName   = -2108,
    VSHPROPID_AlwaysBuildOnDebugLaunch  = -2109,
    VSHPROPID_FIRST4    = -2109
    } ;
typedef /* [public] */ DWORD VSHPROPID4;

so, looked doc. - BSTR __VSHPROPID4.VSHPROPID_BuildAction - retrieves the build action for an item

ok, good news, next step... try to get, for example:

object type;
hr.GetProperty((uint)VSConstants.VSITEMID.Root, (int)__VSHPROPID4.VSHPROPID_BuildAction, out type);

where hr is a, for example:

IVsSolutionBuildManager2 sbm = (IVsSolutionBuildManager2)ServiceProvider.GlobalProvider.GetService(typeof(SVsSolutionBuildManager));

IVsHierarchy hr = null;
sbm.get_StartupProject(out hr);

However, the type always is null... it may be problem with notifying(has not occurred), but also similar result if used the pHierProj from UpdateProjectCfg_Begin / UpdateProjectCfg_Done:

int UpdateProjectCfg_Begin(IVsHierarchy pHierProj, IVsCfg pCfgProj, IVsCfg pCfgSln, uint dwAction, ref int pfCancel)
int UpdateProjectCfg_Done(IVsHierarchy pHierProj, IVsCfg pCfgProj, IVsCfg pCfgSln, uint dwAction, int fSuccess, int fCancel)

which already provides the dwAction...

and., how to use VSHPROPID_BuildAction -_- problem with IVsHierarchy ?

1

There are 1 answers

0
Denis Kuzmin On BEST ANSWER

finished :)

Solution 1

CommandEvents

With the EnvDTE.CommandEvents, we can work before processing IVsUpdateSolutionEvents2 and listen all incoming commands, sample:

...

GUID: {5EFC7975-14BC-11CF-9B2B-00AA00573819} (ID: 882) :: Build.BuildSolution
GUID: {5EFC7975-14BC-11CF-9B2B-00AA00573819} (ID: 883) :: Build.RebuildSolution
GUID: {5EFC7975-14BC-11CF-9B2B-00AA00573819} (ID: 884) :: Build.DeploySolution
GUID: {5EFC7975-14BC-11CF-9B2B-00AA00573819} (ID: 885) :: Build.CleanSolution
GUID: {1496A755-94DE-11D0-8C3F-00C04FC2AAE2} (ID: 2005) :: Build.PublishSelection
GUID: {1496A755-94DE-11D0-8C3F-00C04FC2AAE2} (ID: 353) :: Build.Link    
...

for example:

_cmdEvents.BeforeExecute += new _dispCommandEvents_BeforeExecuteEventHandler((string guid, int id, object customIn, object customOut, ref bool cancelDefault) => {

        if(GuidList.VSStd97CmdID == guid || GuidList.VSStd2KCmdID == guid) {
            _c.updateContext((BuildType)id);
        }

});

Now we can work with type of action in UpdateSolution_Begin, for example:

if(evt.BuildType != BuildType.Common && evt.BuildType != buildType) {
    //...
}

...

if(buildType == BuildType.Clean || buildType == BuildType.LinkOnly){
   //...
}

etc.

full example you can see in sources (see comment where). Also, i think it’s not best variant, however it's variant for VS2010 and higher versions (also should work on very older 2005 & 2008, i think)…

For VS2012 and newer i recommend the IVsUpdateSolutionEvents4

So, my problem solved.

Other best variants ?