Need help with MSFProj

Jan 20, 2014 at 6:50 AM
Hello,

I am trying to create a new project template that could allow me to do the following:

1- Totally new project type (not under C#, VB, C++ or anything like that)
2- It would have its own items. For instance, when creating a project and right click over it and select “Add->New Item” I don’t want to see other files like .cs or .vb or anything like that. Just my files.
3- When I press “Build”, instead of using MSBuild, I use my own compiler/application
4- If possible, disable/remove all menu/toolbar items that don’t make sense for us (i.e. debug)


Is this possible? If yes, then how :)?


Thank you so much,
Mu
Developer
Jan 20, 2014 at 9:56 AM
Hi Mu,
  1. This about how to create a new custom project type - Walkthrough: Part 1 - Creating a Basic Project System and Walkthrough: Part 2 - Creating a Basic Project System
  2. See the walkthroughs above. All stuff you see in Add new dialog is apper from Project and Item templates (aka 'vstemplate'). NOte that in addution to custom project type (for all stuff related to Soolution Explorer and project things management) you will need to create custom language service (for syntax highlighting, associating yout custom file types with your new Language, which is linked to your vstemplates. etc.., Tools -> Options -> Language settings, etc..). Search for Microsoft.VisualStudio.Package.LanguageService to start
  3. You will need to create your custom msbuild targets file (xml + dll with custom commands running your compiler) and refer this .targets file in yout custom project file template (to make it visible for your custom project type). So you will develop custom tasks for Build, Clean, etc.. All of them will be inherited from MsBuild class ToolTask. And you will need to prepare custom XML file YourProject.targets which override starndard MSBuild commans like Compile - <Target Name="Compile" DependsOnTargets=""> and <Target Name="ReBuild" DependsOnTargets="Clean;Build"> and <Target Name="Clean"> etc..
  4. To Run your application (your custom 'code' files by F5 in Visual Studio) you need to have CustomProjectConfig : ProjectConfig (inherited from base MPF ProjectConfig class, which you provide an instance in CustomConfigProvider : ConfigProvider ). So F5 will call this method in your CustomProjectConfig "public override int DebugLaunch(uint flags) {...}"
A bit more details about for enabling/disabling the standard commands. In your class CustomProjectNode : ProjectNode you can control what commands to enable / disable and how to handle them. As a starting point use these method names to search the relevant documentation:
  • public override int QueryStatusCommand(uint itemId, ref Guid guidCmdGroup, uint cCmds, OLECMD[] cmds, IntPtr pCmdText)
  • protected override QueryStatusResult QueryStatusSelectionOnNodes(IList<HierarchyNode> selectedNodes,
  • protected override int ExecCommandIndependentOfSelection(Guid guidCmdGroup, uint cmdId, uint cmdExecOpt, IntPtr vaIn, IntPtr vaOut, CommandOrigin commandOrigin, out bool handled)
  • protected override int ExecCommandThatDependsOnSelectedNodes(Guid guidCmdGroup,
Hope you got you have enough information for further investigation.
Marked as answer by DmitryPavlov on 1/20/2014 at 6:25 AM
Jan 20, 2014 at 12:15 PM
I would definitely check that out. Thank you so much :)


Jan 21, 2014 at 3:47 AM
Hey, I looked at that but still not able to understand how can I add my own files? I don't want to create a new language service, I just want to be able to add specific file types to my new project type.

For instance, when I right click on the project and choose Add->New Item, I only get the files types I designed (i.e. ".myfile" file type)
Jan 21, 2014 at 3:52 AM
Also the created project produces exe and it uses MSBuild. How can I change that:

<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
__<OutputType>Exe</OutputType>__
<AssemblyName>MyAssemblyName</AssemblyName>
<EnableUnmanagedDebugging>false</EnableUnmanagedDebugging>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\Debug\</OutputPath>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<DebugSymbols>false</DebugSymbols>
<OutputPath>bin\Release\</OutputPath>
</PropertyGroup>
<ItemGroup>
<Reference Include="mscorlib" />
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="AssemblyInfo.cs">
  <SubType>Code</SubType>
</Compile>
<Compile Include="Program.cs">
  <SubType>Code</SubType>
</Compile>
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
</Project>
Developer
Jan 21, 2014 at 5:05 AM
As for adding file types - you have to add Item Template for every type you wish to support. For instance, for text file you should add a vs template (as well as __TemplateIcon.ico and TextFile.txt file) like this:
<VSTemplate Version="2.0.0" Type="Item" xmlns="http://schemas.microsoft.com/developer/vstemplate/2005">
  <TemplateData>
    <DefaultName>TextFile.txt</DefaultName>
    <Name>Text File</Name>
    <Description>An empty text file</Description>
    <Icon>__TemplateIcon.ico</Icon>
    <ProjectType>[string which is your project type from ProvideProjectFactory attribute]</ProjectType>
    <SortOrder>50</SortOrder>
  </TemplateData>
  <TemplateContent>
    <ProjectItem>TextFile.txt</ProjectItem>
  </TemplateContent>
</VSTemplate>
In your custom ProjectNode class you create items and folders via these overridden methods:
        protected internal override FolderNode CreateFolderNode(string path, ProjectElement item)
        {
            if (item == null)
            {
                throw new ArgumentNullException("item");
            }

            return new CustomFolderNode(this, path, item);
        }

        public override FileNode CreateFileNode(ProjectElement item)
        {
            if (item == null)
            {
                throw new ArgumentNullException("item");
            }

            return new CustomFileNode(this, item);
        }
Marked as answer by mmeshref on 1/21/2014 at 10:21 PM
Jan 21, 2014 at 5:09 AM
How to register that VSTemplate with my project?
Also I faced another problem when I was working with the tutorial, the resulted package doesn't replace the tokens (i.e. $guid1$) and as a result, the project failed to be created because the value of $guid1$ failed to be replaced with a real guid value
Developer
Jan 21, 2014 at 5:15 AM
Regarding
__<OutputType>custom_application</OutputType>__
you could use any string to identify what kind of output you wish. Or.. just handle EXE as shown below in switch.

In your CutomProjectConfig class you can override:
        public override int DebugLaunch(uint flags)
        {
            // This is actually should be used for debugging purposes in the future
            try
            {
                string outputType = GetConfigurationProperty("OutputType", true);
                switch(outputType)
                {
                    case "custom_library":
                        ShowRunWarning();
                        break;
                    case "custom_application":
                        RunApplication();
                        break;
                    default:
                        Debug.Assert(false, "This should not be called.");
                        break;
                }
            }
            catch(Exception e)
            {
                _logger.Error("Error in DebugLaunch.", e);
                return Marshal.GetHRForException(e);
            }

            return VSConstants.S_OK;
        }
VSX/MPF has a lot of places where you can adjust the standard flow. My advice would be to reuse as much as possible the standard scenario as it will cause less efforts to adjust. Most of the things you might want to adjust are provided as virtual methods in MPF base classes. So check them first for suitable methods to override. Override and set a breakpoint to ensure you are getting the expected data to handle.
Marked as answer by mmeshref on 1/21/2014 at 10:21 PM
Developer
Jan 21, 2014 at 5:30 AM
Check the Part 2 link I provided initially http://msdn.microsoft.com/en-us/library/cc826178.aspx

Templates should be placed to the right place (see below) and when you register your package IDe gets the template information from attribute:
    [ProvideProjectFactory(
        typeof(SimpleProjectFactory),
        null,
        "Simple Project Files (*.zzproj);*.zzproj",
        "zzproj", "zzproj",
        ".\\NullPath",
        LanguageVsTemplate = "SimpleProject")]
from walkthrough: Add an XML file named SimpleProject.vstemplate to the \Templates\Projects__SimpleProject__\ folder.


The right place to put your vs templates would be - under IDE location folder with running them command
devenv.exe /InstallVSTemplates
you have no need to run this command if you run
devenv.exe /setup 
as /setup includes templates installing
Marked as answer by mmeshref on 1/21/2014 at 10:21 PM
Jan 21, 2014 at 5:33 AM
Right now I am facing two main problems with the links above:

1- the resulted package doesn't replace the tokens (i.e. $guid1$) and as a result, the project failed to be created because the value of $guid1$ failed to be replaced with a real guid value
2- None of the functions inside "public class ProjectConfig" and "public class BuildableProjectConfig" are being called and hence I can't do anything with them (I placed message boxes there and they were never called)
Developer
Jan 21, 2014 at 5:46 AM
1 - <ProjectGuid>$guid1$</ProjectGuid> is a GUID of your custom project instance (not the project type GUID). So it should be unique for every new custom project you create.

2 - As for your custom ProjectConfig and BuildableProjectConfig classes. Maybe you just did not create their instances? Note that for adding your CustomProjectConfig class (inherited from MPF class ProjectConfig) you need:
  • create CustomConfigProvider : ConfigProvider see the code below
  • create CustomConfigProvider instance from your custom project node class
        protected override ConfigProvider CreateConfigProvider()
        {
            return new CustomConfigProvider(this);
        }
    [ComVisible(true)]
    [CLSCompliant(false)]
    public class CustomConfigProvider : ConfigProvider
    {
        
        public CustomConfigProvider(ProjectNode manager)
            : base(manager)
        {}

        protected override ProjectConfig CreateProjectConfiguration(string configName)
        {
            // if we already created it, return the cached one
            if (configurationsList.ContainsKey(configName))
            {
                return configurationsList[configName];
            }

            CustomProjectConfig requestedConfiguration = new CustomProjectConfig (ProjectMgr, configName);
            configurationsList.Add(configName, requestedConfiguration);

            return requestedConfiguration;
        }

        public override int GetPlatformNames(uint celt, string[] names, uint[] actual)
        {
            if (names != null)
            {
                names[0] = "Any CPU";
            }

            if (actual != null)
            {
                actual[0] = 1;
            }

            return VSConstants.S_OK;
        }

        public override int GetSupportedPlatformNames(uint celt, string[] names, uint[] actual)
        {
            if (names != null)
            {
                names[0] = "Any CPU";
            }

            if (actual != null)
            {
                actual[0] = 1;
            }

            return VSConstants.S_OK;
        }

    }
Marked as answer by mmeshref on 1/21/2014 at 10:22 PM
Jan 21, 2014 at 5:48 AM
Can I send you a copy of my sample? When you run it you would know what I meant by #1. I can't try #2 yes because of #1
Developer
Jan 21, 2014 at 5:50 AM
I think this forum will be very useful MSDN Visual Studio Extensibility (VSX) Forum as I remember that when I was investigating VSX/MPF we discussed a lot of questions there and VSX team from Microsoft regularly helped me and other VSX developers.
Marked as answer by mmeshref on 1/21/2014 at 10:22 PM
Developer
Jan 21, 2014 at 5:52 AM
Unfortunately I can't check you sources at the moment as I have no suitable environment configured. Please post it to VSX forum. This way you will get the answers you need and also help other guys to solve similar issues. Okay?
Marked as answer by mmeshref on 1/21/2014 at 10:22 PM
Jan 22, 2014 at 5:23 AM
Edited Jan 22, 2014 at 5:26 AM
Did that already. thank you so much for help :)

Another question, I tried to add the items template as you suggested above (creating 3 files, icon, text and vstemplate). I marked the build action as VSTemplate but I still do not see that item in the items list when I try to add a new item to a project?