예제 #1
0
        /// <summary>
        /// Generates the contents of the given file extension.
        /// If null is returned, it means to preserve the existing file instead
        /// of generating a new one.
        /// </summary>
        /// <param name="fileExtension">One of the file extensions from the <see cref="GetEnumerator()"/> method.</param>
        /// <returns>The generated content for the given file extension, or null.</returns>
        private byte[] GenerateAllContent(string fileExtension)
        {
            System.Diagnostics.Debugger.Log(0, "", String.Format("Called 'GenerateAllContent'; fileExtension={0} ", fileExtension));

            // For debugging purposes, it is better to be able to edit the .tt files without having to
            // recompile the solution to test changes. During release, use the embedded .tt files
            // instead.
            if (IsTextTemplateGenerator(fileExtension))
            {
                return(GenerateFromTextTemplate(fileExtension));
            }
            else if (fileExtension == "diagram")
            {
                return(null);
            }
            else
            {
                if (fileExtension == CodeFileExtension)
                {
                    // Shouldnt get here?
                    Diagnostics.DebugWrite("FG.GenerateAllContent >> fileExtension == CodeFileExtension ('{0}'). Returning null... ", fileExtension);
                    return(null);
                }
                else if (fileExtension == string.Format("{0}-gen", CodeFileExtension))
                {
                    System.Diagnostics.Debugger.Log(0, "", String.Format("Generating class file! fileExtension is of ?-gen. Running CodeFileGenerator.GenerateCode with InputFilePath={0}", InputFilePath));
                    return(CodeFileGenerator.GenerateCode(InputFilePath));
                }
                else
                {
                    throw new ApplicationException("Unhandled file content");
                }
            }
        }
예제 #2
0
 public VsMultipleFileGenerator()
 {
     Diagnostics.DebugWrite("VsMultipleFileGenerator() ctor");
     _oldFileNames = new List <string>();
     _newFileNames = new List <string>();
     // EnsureActiveProjectSet();
 }
        /// <summary>
        /// Looks through the <paramref name="project"/> and all subitems / subprojects to find the project hosting the active configuration section designer window.
        /// </summary>
        /// <param name="project">the parent project.</param>
        /// <param name="docPriority">Specifies the priority level of a document within a project.</param>
        /// <param name="configurationSectionModelFile">the project item represented by inputFilePath, if found (ex: MyProject\ConfigurationSection.csd).</param>
        /// <param name="inputFilePath">the file path of the project item.</param>
        /// <returns><c>true</c> if found; otherwise <c>false</c>.</returns>
        public static bool TryFindProjectItemWithFilePath(Project project, VSDOCUMENTPRIORITY[] docPriority, string inputFilePath, out ProjectItem configurationSectionModelFile)
        {
            Diagnostics.DebugWrite("VsHelper.TryFindProjectItemWithFilePath (VH.TFP).");
            bool projectFound = false;

            configurationSectionModelFile = null;

            // Nothing useful for this project. Process the next one.
            if (string.IsNullOrEmpty(project.FileName) || !File.Exists(project.FileName))
            {
                Diagnostics.DebugWrite("VH.TFP >> Nothing useful found in this current dte.Solution.Projects item. Continuing loop...");
                return(false);
            }

            // obtain a reference to the current project as an IVsProject type
            IVsProject vsProject = VsHelper.ToVsProject(project);

            Diagnostics.DebugWrite("VH.TFP >> IVsProject vsProject = VsHelper.ToVsProject( project='{0}' )", project.Name);

            int  iFound = 0;
            uint itemId = 0;

            // this locates, and returns a handle to our source file, as a ProjectItem
            vsProject.IsDocumentInProject(inputFilePath, out iFound, docPriority, out itemId);
            Diagnostics.DebugWrite("VH.TFP >> vsProject.IsDocumentInProject(inputFilePath, out iFound={0}, pdwPriority, out itemId={1}).", iFound, itemId);

            // TODO: [abm] Below here, project build failed! Error was "type is not of VsProject". This only occured on a brand new
            // project with brand new csd. After failed rebuild attempt of project, it all worked.
            // Find out why and fix (or create warning message) to guide future users! Not yet reproducible...

            // if this source file is found in this project
            if (iFound != 0 && itemId != 0)
            {
                Diagnostics.DebugWrite("VH.TFP >> (iFound != 0 && itemId != 0) == TRUE!!!");
                Microsoft.VisualStudio.OLE.Interop.IServiceProvider oleSp = null;
                vsProject.GetItemContext(itemId, out oleSp);
                if (oleSp != null)
                {
                    Diagnostics.DebugWrite("VH.TFP >> vsProject.GetItemContext( itemId, out oleSp ) >> oleSp != null! Getting ServiceProvider sp...");
                    ServiceProvider sp = new ServiceProvider(oleSp);
                    // convert our handle to a ProjectItem
                    configurationSectionModelFile = sp.GetService(typeof(ProjectItem)) as ProjectItem;

                    if (configurationSectionModelFile != null)
                    {
                        Diagnostics.DebugWrite("VH.TFP >>  configurationSectionModelFile = sp.GetService( typeof( ProjectItem ) ) as ProjectItem is NOT null! Setting this._project to the project we were working on...");
                        // We now have what we need. Stop looking.
                        projectFound = true;
                    }
                }
            }
            return(projectFound);
        }
예제 #4
0
        /// <summary>
        /// Recursively traverses the Solution hierarchy, starting at <paramref name="currentProjectItems"/>, looking for
        /// the project item designated by <paramref name="filePath"/>, and it's parent project.
        /// </summary>
        /// <remarks>
        /// The recursion in this method has gotten ugly and complex, but it appears to work. It may be nice to find a more elegant solution
        /// to the problem of locating these items in the future. [a.moore]
        /// </remarks>
        /// <param name="filePath">The path of the CSD file to locate.</param>
        /// <param name="currentProjectItems">Project item hiearchy we are traversing to find possible SubProjects (IE. in solution folder type)</param>
        /// <param name="parentProject">(out) the parent project of the file, if found.</param>
        /// <param name="fileProjectItem">(out) the project item representation of the CSD file, if found.</param>
        /// <returns><c>true</c> if found, otherwise <c>false</c></returns>
        private static bool _TryFindProjectItemAndParentProject(string filePath, ProjectItems currentProjectItems, out Project parentProject, out ProjectItem fileProjectItem)
        {
            // TODO: Would it be safe to only check subitems if current item is a solution folder? We are checking alot of items that would never have sub projects.
            Diagnostics.DebugWrite("VsHelper.TryFindProjectItemAndParentProject (ProjectItems Level) >> currentProjectItems.Count = '{0}'.", currentProjectItems.Count);
            parentProject   = null;
            fileProjectItem = null;

            // Already checked by calling method, but leaving null check for future use...
            if (currentProjectItems == null)
            {
                throw new ArgumentException("currentProjectItems cannot be null.");
            }

            foreach (ProjectItem projectItem in currentProjectItems)
            {
                Diagnostics.DebugWrite("VsHelper.TryFindProjectItemAndParentProject >> Current projectItem = '{0}', projectItem.ProjectItems.Count={1},", projectItem.Name, (projectItem.ProjectItems != null ? projectItem.ProjectItems.Count.ToString() : "0"));
                if (projectItem.SubProject != null) // Check SubProject.
                {
                    Diagnostics.DebugWrite("VsHelper.TryFindProjectItemAndParentProject >> projectItem.SubProject EXISTS.");

                    // If item was matched to file or recursive call returned true, exit.
                    if ((!string.IsNullOrEmpty(projectItem.SubProject.FullName) &&
                         TryFindProjectItemWithFilePath(projectItem.SubProject, filePath, out fileProjectItem)))
                    {
                        Diagnostics.DebugWrite("VsHelper.TryFindProjectItemAndParentProject >> PROJECT FOUND in SubProject!");
                        parentProject = projectItem.SubProject;
                        return(true);
                    }

                    // Look through the SubProject's project items.
                    if (projectItem.SubProject.ProjectItems != null &&
                        _TryFindProjectItemAndParentProject(filePath, projectItem.SubProject.ProjectItems, out parentProject, out fileProjectItem))
                    {
                        Diagnostics.DebugWrite("VsHelper.TryFindProjectItemAndParentProject >> PROJECT FOUND in SubProject.ProjectItems!");
                        return(true);
                    }
                }
                else if (
                    projectItem.ProjectItems != null &&
                    projectItem.ProjectItems.Count > 0 &&
                    _TryFindProjectItemAndParentProject(filePath, projectItem.ProjectItems, out parentProject, out fileProjectItem)
                    ) // Check project items.
                {
                    Diagnostics.DebugWrite("VsHelper.TryFindProjectItemAndParentProject >> PROJECT FOUND in projectItem!");
                    return(true);
                }
            }

            return(false);
        }
예제 #5
0
        /// <summary>
        /// Generates the contents of the given file extension.
        /// If null is returned, it means to preserve the existing file instead
        /// of generating a new one.
        /// </summary>
        /// <param name="fileExtension">One of the file extensions from the <see cref="GetEnumerator()"/> method.</param>
        /// <returns>The generated content for the given file extension, or null.</returns>
        private byte[] GenerateAllContent(string fileExtension)
        {
            System.Diagnostics.Debugger.Log(0, "", String.Format("Called 'GenerateAllContent'; fileExtension={0} ", fileExtension));

            string inputFileContent;

            // For debugging purposes, it is better to be able to edit the .tt files without having to
            // recompile the solution to test changes. During release, use the embedded .tt files
            // instead.
            switch (fileExtension)
            {
            case "config":
                Diagnostics.DebugWrite("GenerateAllContent >> ConfigurationSectionDesignerSample template file={0}", Path.Combine(TextTemplateFolder, "ConfigurationSectionDesignerSample.tt"));

                inputFileContent = File.ReadAllText(Path.Combine(TextTemplateFolder, "ConfigurationSectionDesignerSample.tt"));
                break;

            case "xsd":
                inputFileContent = File.ReadAllText(Path.Combine(TextTemplateFolder, "ConfigurationSectionDesignerSchema.tt"));
                break;

            // Preserve the diagram and cs files, don't write anything to them
            case "diagram":
                return(null);

            // Generate the code behind file!
            default:
                if (fileExtension == CodeFileExtension)
                {
                    return(null);
                }
                else if (fileExtension == string.Format("{0}-gen", CodeFileExtension))
                {
                    System.Diagnostics.Debugger.Log(0, "", String.Format("fileExtension is of ?-gen. Running CodeFileGenerator.GenerateCode with InputFilePath={0}", InputFilePath));

                    return(CodeFileGenerator.GenerateCode(InputFilePath));
                }
                else
                {
                    throw new ApplicationException("Unhandled file content");
                }
            }

            // Replace our input file name placeholder with the real input file name
            // so the text transformer knows which .csd file to work on.
            System.Diagnostics.Debugger.Log(0, "", String.Format("Replacing $inputFileName$ with real value before running TemplateGenerator.GenerateCode(InputFilePath={0},inputFileContent={1}); ", InputFilePath, "TOO LONG!"));

            inputFileContent = inputFileContent.Replace("$inputFileName$", InputFilePath);
            return(TemplateGenerator.GenerateCode(InputFilePath, inputFileContent));
        }
예제 #6
0
        private byte[] GenerateFromTextTemplate(string fileExtension)
        {
            string ttFilePath = "";

            if (fileExtension == "config")
            {
                ttFilePath = Path.Combine(TextTemplateFolder, "ConfigurationSectionDesignerSample.tt");
            }
            else if (fileExtension == "xsd")
            {
                ttFilePath = Path.Combine(TextTemplateFolder, "ConfigurationSectionDesignerSchema.tt");
            }
            Diagnostics.DebugWrite("GenerateAllContent >> Generating from template file '{0}'.", ttFilePath);

            string inputFileContent = File.ReadAllText(ttFilePath);

            // Replace our input file name placeholder with the real input file name
            // so the text transformer knows which .csd file to work on.
            System.Diagnostics.Debugger.Log(0, "", String.Format("Replacing $inputFileName$ with real value before running TemplateGenerator.GenerateCode(InputFilePath={0},inputFileContent.Length={1}); ", InputFilePath, inputFileContent.Length));
            inputFileContent = inputFileContent.Replace("$inputFileName$", InputFilePath);

            // TODO: CURRERROR: Templating service unavailable error at this point..
            // It fails because BaseTemplatedCodeGenerator.TextTemplating property returns null.

            /*
             * protected ITextTemplating TextTemplating
             * {
             *  get
             *  {
             *  ITextTemplating textTemplating = (ITextTemplating) null;
             *  IVsHierarchy vsHierarchy = this.GetService(typeof (IVsHierarchy)) as IVsHierarchy;
             *  if (vsHierarchy != null)
             *  {
             *      Microsoft.VisualStudio.OLE.Interop.IServiceProvider ppSP = (Microsoft.VisualStudio.OLE.Interop.IServiceProvider) null;
             *      if (!Microsoft.VisualStudio.TextTemplating.NativeMethods.Failed(vsHierarchy.GetSite(out ppSP)) && ppSP != null)
             *      {
             *      Guid guid = typeof (STextTemplating).GUID;
             *      IntPtr ppvObject = IntPtr.Zero;
             *      ErrorHandler.ThrowOnFailure(ppSP.QueryService(ref guid, ref guid, out ppvObject));
             *      if (ppvObject != IntPtr.Zero)
             *          textTemplating = Marshal.GetObjectForIUnknown(ppvObject) as ITextTemplating;
             *      }
             *  }
             *  return textTemplating;
             *  }
             * }*/
            return(TemplateGenerator.GenerateCode(InputFilePath, inputFileContent));
        }
        /// <summary>
        /// Recursively traverses the Solution hierarchy, starting at <paramref name="currentProjectItems"/>, looking for
        /// the project item designated by <paramref name="filePath"/>, and it's parent project.
        /// </summary>
        /// <remarks>
        /// The recursion in this method has gotten ugly and complex, but it appears to work. It may be nice to find a more elegant solution
        /// to the problem of locating these items in the future. [a.moore]
        /// </remarks>
        /// <param name="filePath">The path of the file to locate.</param>
        /// <param name="currentProjectItems"></param>
        /// <param name="parentProject">(out) the parent project of the file, if found.</param>
        /// <param name="fileProjectItem">(out) the project item of the file, if found.</param>
        /// <returns><c>true</c> if found, otherwise <c>false</c></returns>
        private static bool TryFindProjectItemAndParentProject(string filePath, ProjectItems currentProjectItems, out Project parentProject, out ProjectItem fileProjectItem)
        {
            Diagnostics.DebugWrite("VsHelper.TryFindProjectItemAndParentProject (ProjectItems Level) >> currentProjectItems.Count = '{0}'.", currentProjectItems.Count);
            parentProject   = null;
            fileProjectItem = null;

            // Already checked by calling method, but leaving null check for future use...
            if (currentProjectItems != null)
            {
                foreach (ProjectItem projectItem in currentProjectItems)
                {
                    Diagnostics.DebugWrite("VsHelper.TryFindProjectItemAndParentProject >> Current projectItem = '{0}', projectItem.ProjectItems.Count={1},", projectItem.Name, (projectItem.ProjectItems != null ? projectItem.ProjectItems.Count.ToString() : "0"));
                    if (projectItem.SubProject != null) // Check SubProject.
                    {
                        Diagnostics.DebugWrite("VsHelper.TryFindProjectItemAndParentProject >> projectItem.SubProject EXISTS.");

                        // If item was matched to file or recursive call returned true, exit.
                        if ((!string.IsNullOrEmpty(projectItem.SubProject.FullName) &&
                             TryFindProjectItemWithFilePath(projectItem.SubProject, filePath, out fileProjectItem)))
                        {
                            Diagnostics.DebugWrite("VsHelper.TryFindProjectItemAndParentProject >> PROJECT FOUND in SubProject!");
                            parentProject = projectItem.SubProject;
                            return(true);
                        }

                        // Look through the SubProject's project items.
                        if (projectItem.SubProject.ProjectItems != null &&
                            TryFindProjectItemAndParentProject(filePath, projectItem.SubProject.ProjectItems, out parentProject, out fileProjectItem))
                        {
                            Diagnostics.DebugWrite("VsHelper.TryFindProjectItemAndParentProject >> PROJECT FOUND in SubProject.ProjectItems!");
                            return(true);
                        }
                    }
                    else if (
                        projectItem.ProjectItems != null &&
                        projectItem.ProjectItems.Count > 0 &&
                        TryFindProjectItemAndParentProject(filePath, projectItem.ProjectItems, out parentProject, out fileProjectItem)
                        ) // Check project items.
                    {
                        Diagnostics.DebugWrite("VsHelper.TryFindProjectItemAndParentProject >> PROJECT FOUND in projectItem!");
                        return(true);
                    }
                }
            }
            return(false);
        }
예제 #8
0
        /// <summary>
        /// Recursively traverses the Solution hierarchy looking for the CSD document designated by <paramref name="filePath"/>, and
        /// the project it is found in.
        /// </summary>
        /// <remarks>
        /// The recursion in this method has gotten ugly and complex, but it appears to work. It may be nice to find a more elegant solution
        /// to the problem of locating these items in the future. [a.moore]
        /// </remarks>
        /// <param name="csdDocumentFilePath">The path of the CSD file to locate.</param>
        /// <param name="parentProject">(out) the parent project of the file, if found.</param>
        /// <param name="fileProjectItem">(out) the project item representation of the CSD file, if found.</param>
        /// <returns><c>true</c> if found, otherwise <c>false</c></returns>
        public static bool TryFindProjectItemAndParentProject(string csdDocumentFilePath, out Project parentProject, out ProjectItem fileProjectItem)
        {
            Diagnostics.DebugWrite("VsHelper.TryFindProjectItemAndParentProject (Sol Level) >> csdDocumentFilePath = '{0}'.", csdDocumentFilePath);
            parentProject   = null;
            fileProjectItem = null;
            DTE dte = (DTE)Package.GetGlobalService(typeof(DTE));

            foreach (Project project in dte.Solution.Projects)
            {
                Diagnostics.DebugWrite("VsHelper.TryFindProjectItemAndParentProject >> Current project = '{0}'.", project.Name ?? "<null>");
                if (project.ProjectItems != null && project.ProjectItems.Count > 0)
                {
                    Diagnostics.DebugWrite("VsHelper.TryFindProjectItemAndParentProject >> project.ProjectItems != null && Number of project items ({0}) > 0", project.ProjectItems.Count);
                    // First, look for the project at the solution level (No solution folders, subprojects, etc).
                    if (TryFindProjectItemWithFilePath(project, csdDocumentFilePath, out fileProjectItem))
                    {
                        // The project was found at the solution level.
                        parentProject = project;
                        Diagnostics.DebugWrite("VsHelper.TryFindProjectItemAndParentProject >> PROJECT FOUND! Name='{0}'", project.Name);
                        return(true);
                    }
                    else
                    {
                        // Project NOT found at the solution level. Start drilling down into sub project items...
                        Diagnostics.DebugWrite("VsHelper.TryFindProjectItemAndParentProject >> TryFindProjectItemWithFilePath(project, filePath, out fileProjectItem) == FALSE");
                        if (_TryFindProjectItemAndParentProject(csdDocumentFilePath, project.ProjectItems, out parentProject, out fileProjectItem))
                        {
                            // The project was found after drilling down.
                            Diagnostics.DebugWrite("VsHelper.TryFindProjectItemAndParentProject >> PROJECT FOUND! Name='{0}'", project.Name);
                            return(true);
                        }
                    }
                }
            }
            return(false);
        }
예제 #9
0
        /// <summary>
        /// Looks through the <paramref name="project"/> and all subitems / subprojects to find the project hosting the active configuration section designer window.
        /// </summary>
        /// <remarks>
        /// Checks if <paramref name="csdDocumentFilePath"/> is inside <paramref name="project"/>. If true, the id of
        /// <paramref name="csdDocumentFilePath"/> is located and used to return the CSD file as a ProjectItem object
        /// <paramref name="configurationSectionModelFile"/>.
        /// </remarks>
        /// <param name="project">the parent project.</param>
        /// <param name="docPriority">Specifies the priority level of a document within a project.</param>
        /// <param name="configurationSectionModelFile">(out) the project item represented by csdDocumentFilePath, if found (ex: MyProject\ConfigurationSection.csd).</param>
        /// <param name="csdDocumentFilePath">the file path of the CSD project item.</param>
        /// <returns><c>true</c> if found; otherwise <c>false</c>.</returns>
        public static bool TryFindProjectItemWithFilePath(Project project, VSDOCUMENTPRIORITY[] docPriority, string csdDocumentFilePath, out ProjectItem configurationSectionModelFile)
        {
            Diagnostics.DebugWrite("VsHelper.TryFindProjectItemWithFilePath (VH.TFP).");
            bool projectFound = false;

            configurationSectionModelFile = null;

            // Nothing useful for this project. Process the next one.
            if (string.IsNullOrEmpty(project.FileName) || !File.Exists(project.FileName))
            {
                Diagnostics.DebugWrite("VH.TFP >> Nothing useful found in this current dte.Solution.Projects item. Continuing loop...");
                return(false);
            }

            // obtain a reference to the current project as an IVsProject type
            IVsProject vsProject = VsHelper.ToVsProject(project); // ABM - Issue 10435: 2nd WindowsService project results in FAILURE here.

            Diagnostics.DebugWrite("VH.TFP >> IVsProject vsProject = VsHelper.ToVsProject( project='{0}' )", project.Name);

            int  iFound = 0;
            uint itemId = 0;

            // this locates, and returns a handle to our source file, as a ProjectItem
            int result = vsProject.IsDocumentInProject(csdDocumentFilePath, out iFound, docPriority, out itemId); // ABM - Issue 10435: WindowsService project results in iFound=0!!!

            // itemid: Pointer to the item identifier of the document within the project.
            // NOTE: itemId is either a specific id pointing to the file, or is one of VSITEMID enumeration.
            // VSITEMID represents Special items inside a VsHierarchy:

            /*
             * public enum VSITEMID
             * {
             * Selection = 4294967293, // all the currently selected items. // represents the currently selected item or items, which can include the root of the hierarchy.
             * Root = 4294967294,      // the hierarchy itself. // represents the root of a project hierarchy and is used to identify the entire hierarchy, as opposed to a single item.
             * Nil = 4294967295,       // no node.// represents the absence of a project item. This value is used when there is no current selection.
             * }
             * http://visual-studio.todaysummary.com/q_visual-studio_76086.html
             *
             * http://msdn.microsoft.com/en-us/subscriptions/downloads/microsoft.visualstudio.shell.interop.ivshierarchy(v=vs.100).aspx
             */


            if (result != VSConstants.S_OK)
            {
                throw new Exception("Unexpected error calling IVsProject.IsDocumentInProject.");
            }

            Diagnostics.DebugWrite("VH.TFP >> vsProject.IsDocumentInProject(inputFilePath, out iFound={0}, pdwPriority, out itemId={1}).", iFound, itemId);

            // TODO: [abm] Below here, project build failed! Error was "type is not of VsProject". This only occured on a brand new
            // project with brand new csd. After failed rebuild attempt of project, it all worked.
            // Find out why and fix (or create warning message) to guide future users! Not yet reproducible...

            // if this source file is found in this project
            if (iFound != 0 && itemId != 0)
            {
                Diagnostics.DebugWrite("VH.TFP >> (iFound != 0 && itemId != 0) == TRUE!!!");
                Microsoft.VisualStudio.OLE.Interop.IServiceProvider oleSp = null;
                vsProject.GetItemContext(itemId, out oleSp);
                if (oleSp != null)
                {
                    Diagnostics.DebugWrite("VH.TFP >> vsProject.GetItemContext( itemId, out oleSp ) >> oleSp != null! Getting ServiceProvider sp...");
                    ServiceProvider sp = new ServiceProvider(oleSp);
                    // convert our handle to a ProjectItem
                    configurationSectionModelFile = sp.GetService(typeof(ProjectItem)) as ProjectItem;

                    if (configurationSectionModelFile != null)
                    {
                        Diagnostics.DebugWrite("VH.TFP >>  configurationSectionModelFile = sp.GetService( typeof( ProjectItem ) ) as ProjectItem is NOT null! Setting this._project to the project we were working on...");
                        // We now have what we need. Stop looking.
                        projectFound = true;
                    }
                }
            }
            return(projectFound);
        }
        /// <summary>
        /// Implements the IVsSingleFileGenerator.Generate method.
        /// Executes the transformation and returns the newly generated output file, whenever a custom tool is loaded, or the input file is saved
        /// </summary>
        /// <param name="wszInputFilePath">The full path of the input file. May be a null reference (Nothing in Visual Basic) in future releases of Visual Studio, so generators should not rely on this value</param>
        /// <param name="bstrInputFileContents">The contents of the input file. This is either a UNICODE BSTR (if the input file is text) or a binary BSTR (if the input file is binary). If the input file is a text file, the project system automatically converts the BSTR to UNICODE</param>
        /// <param name="wszDefaultNamespace">This parameter is meaningful only for custom tools that generate code. It represents the namespace into which the generated code will be placed. If the parameter is not a null reference (Nothing in Visual Basic) and not empty, the custom tool can use the following syntax to enclose the generated code</param>
        /// <param name="rgbOutputFileContents">[out] Returns an array of bytes to be written to the generated file. You must include UNICODE or UTF-8 signature bytes in the returned byte array, as this is a raw stream. The memory for rgbOutputFileContents must be allocated using the .NET Framework call, System.Runtime.InteropServices.AllocCoTaskMem, or the equivalent Win32 system call, CoTaskMemAlloc. The project system is responsible for freeing this memory</param>
        /// <param name="pcbOutput">[out] Returns the count of bytes in the rgbOutputFileContent array</param>
        /// <param name="pGenerateProgress">A reference to the IVsGeneratorProgress interface through which the generator can report its progress to the project system</param>
        /// <returns>If the method succeeds, it returns S_OK. If it fails, it returns E_FAIL</returns>
        public int Generate(string wszInputFilePath, string bstrInputFileContents, string wszDefaultNamespace, IntPtr[] rgbOutputFileContents, out uint pcbOutput,
                            Microsoft.VisualStudio.Shell.Interop.IVsGeneratorProgress pGenerateProgress)
        {
            VsOutputWindowPaneManager.OutputWindowWriteLine(vsOutputWindowPaneName, "");
            VsOutputWindowPaneManager.OutputWindowWriteLine(vsOutputWindowPaneName, string.Format("------ CSD file generation started: Configuration document: {0} ------", InputFilePath));

            Diagnostics.DebugWrite("VsMultipleFileGenerator => VSMFG.");

            ProjectItem configurationSectionModelFile = null;

            _bstrInputFileContents = bstrInputFileContents;
            _wszInputFilePath      = wszInputFilePath;
            _generatorProgress     = pGenerateProgress;
            _newFileNames.Clear();

            // Look through all the projects in the solution
            DTE dte = (DTE)Package.GetGlobalService(typeof(DTE));

            Diagnostics.DebugWrite("VSMFG.Generate >> dte.Solution.Projects.Count = {0}.", dte.Solution.Projects.Count);

            VsOutputWindowPaneManager.OutputWindowWrite(vsOutputWindowPaneName, "* Searching for configuration project handle... ");
            // [7296] FILE = ~\ConfigurationSectionDesigner\Debugging\Sample.csd.
            if (!VsHelper.TryFindProjectItemAndParentProject(InputFilePath, out _project, out configurationSectionModelFile) || _project == null)
            {
                VsOutputWindowPaneManager.OutputWindowWriteLine(vsOutputWindowPaneName, "error: Unable to retrieve Visual Studio ProjectItem. File generation halted.");
                throw new ApplicationException("Unable to retrieve Visual Studio ProjectItem. Try running the tool again.");
            }
            VsOutputWindowPaneManager.OutputWindowWriteLine(vsOutputWindowPaneName, "found!");

            // now we can start our work, iterate across all the 'elements' in our source file
            foreach (TIterativeElement element in this)
            {
                try
                {
                    // obtain a name for this target file
                    string fileName = GetFileName(element);

                    Diagnostics.DebugWrite("VSMFG.Generate >> Filename for current element in loop is '{0}'", fileName);

                    // add it to the tracking cache
                    _newFileNames.Add(fileName);
                    // fully qualify the file on the filesystem
                    string strFile = Path.Combine(wszInputFilePath.Substring(0, wszInputFilePath.LastIndexOf(Path.DirectorySeparatorChar)), fileName);

                    FileStream fs = null;
                    try
                    {
                        // generate our target file content
                        byte[] data = GenerateContent(element);

                        // if data is null, it means to ignore the contents of the generated file
                        if (data == null)
                        {
                            continue;
                        }

                        if (File.Exists(strFile))
                        {
                            // If the file already exists, only save the data if the generated file is different than the existing file.
                            byte[] oldData = File.ReadAllBytes(strFile);
                            if (!Util.IsDataEqual(oldData, data))
                            {
                                Diagnostics.DebugWrite("VSMFG.Generate >> File data has not changed for file '{0}'. Re-using existing file...", strFile);
                                fs = File.Open(strFile, FileMode.Truncate);
                            }
                        }
                        else
                        {
                            // create the file
                            fs = File.Create(strFile);
                        }

                        if (fs != null)
                        {
                            // write it out to the stream
                            fs.Write(data, 0, data.Length);
                        }

                        // add the newly generated file to the solution, as a child of the source file
                        if (configurationSectionModelFile.ProjectItems.Cast <ProjectItem>()
                            .Where(pi => pi.Name == fileName).Count() == 0)
                        {
                            ProjectItem itm = configurationSectionModelFile.ProjectItems.AddFromFile(strFile);

                            /*
                             * Here you may wish to perform some addition logic such as, setting a custom tool for the target file if it
                             * is intented to perform its own generation process.
                             * Or, set the target file as an 'Embedded Resource' so that it is embedded into the final Assembly.
                             *
                             * EnvDTE.Property prop = itm.Properties.Item("CustomTool");
                             * //// set to embedded resource
                             * itm.Properties.Item("BuildAction").Value = 3;
                             * if (String.IsNullOrEmpty((string)prop.Value) || !String.Equals((string)prop.Value, typeof(AnotherCustomTool).Name))
                             * {
                             *  prop.Value = typeof(AnotherCustomTool).Name;
                             * }
                             */
                        }
                    }
                    catch (Exception e)
                    {
                        //GeneratorProgress.GeneratorError( false, 0, string.Format( "{0}\n{1}", e.Message, e.StackTrace ), -1, -1 );
                        GeneratorProgress.GeneratorError(0, 0, string.Format("{0}\n{1}", e.Message, e.StackTrace), 0, 0);
                        if (File.Exists(strFile))
                        {
                            File.WriteAllText(strFile, "An exception occured while running the CsdFileGenerator on this file. See the Error List for details. E=" + e);
                        }
                    }
                    finally
                    {
                        if (fs != null)
                        {
                            fs.Close();
                        }
                    }
                }
                catch (Exception ex)
                {
                    // This is here for debugging purposes, as setting a breakpoint here can be very helpful
                    Diagnostics.DebugWrite("VSMFG.Generate >> EXCEPTION: {0}", ex);
                    throw;
                }
            }

            // perform some clean-up, making sure we delete any old (stale) target-files
            VsOutputWindowPaneManager.OutputWindowWrite(vsOutputWindowPaneName, "* Cleaning up existing files... ");

            foreach (ProjectItem childItem in configurationSectionModelFile.ProjectItems)
            {
                string next;
                DefaultExtension(out next);

                if (!(childItem.Name.EndsWith(next) || _newFileNames.Contains(childItem.Name)))
                {
                    // then delete it
                    childItem.Delete();
                }
            }

            VsOutputWindowPaneManager.OutputWindowWriteLine(vsOutputWindowPaneName, "complete!");

            VsOutputWindowPaneManager.OutputWindowWrite(vsOutputWindowPaneName, "* Writing new files... ");
            // generate our default content for our 'single' file
            byte[] defaultData = null;
            try
            {
                defaultData = GenerateDefaultContent();
            }
            catch (Exception ex)
            {
                Diagnostics.DebugWrite("VSMFG.Generate >> EXCEPTION: {0}", ex);
                //GeneratorProgress.GeneratorError( false, 0, string.Format( "{0}\n{1}", ex.Message, ex.StackTrace ), -1, -1 );
                GeneratorProgress.GeneratorError(0, 0, string.Format("{0}\n{1}", ex.Message, ex.StackTrace), 0, 0);
            }
            VsOutputWindowPaneManager.OutputWindowWriteLine(vsOutputWindowPaneName, "complete!");

            if (defaultData == null)
            {
                defaultData = new byte[0];
            }

            // return our default data, so that Visual Studio may write it to disk.

            /*
             * You need to write the bytes of the generated file into this variable. However, you cannot
             * do it directly (hence the IntPtr[] type) – instead, you must use the System.Runtime.InteropServices.AllocCoTaskMem
             * allocator to create the memory and write type bytes in there.
             */
            rgbOutputFileContents[0] = Marshal.AllocCoTaskMem(defaultData.Length);

            Marshal.Copy(defaultData, 0, rgbOutputFileContents[0], defaultData.Length);

            // must be set to the number of bytes that we wrote to rgbOutputFileContents.
            pcbOutput = (uint)defaultData.Length;

            VsOutputWindowPaneManager.OutputWindowWriteLine(vsOutputWindowPaneName, "========== CSD file generation: complete! ==========");

            return(0);
        }
예제 #11
0
        /// <summary>
        /// Implements the IVsSingleFileGenerator.Generate method.
        /// Executes the transformation and returns the newly generated output file, whenever a custom tool is loaded, or the input file is saved
        /// </summary>
        /// <remarks>
        /// When this is called, the current generator enumerator consists of a list of file extentions that we are going to generate.
        /// </remarks>
        /// <param name="wszInputFilePath">The full path of the input file. May be a null reference (Nothing in Visual Basic) in future releases of Visual Studio, so generators should not rely on this value</param>
        /// <param name="bstrInputFileContents">The contents of the input file. This is either a UNICODE BSTR (if the input file is text) or a binary BSTR (if the input file is binary). If the input file is a text file, the project system automatically converts the BSTR to UNICODE</param>
        /// <param name="wszDefaultNamespace">This parameter is meaningful only for custom tools that generate code. It represents the namespace into which the generated code will be placed. If the parameter is not a null reference (Nothing in Visual Basic) and not empty, the custom tool can use the following syntax to enclose the generated code</param>
        /// <param name="rgbOutputFileContents">[out] Returns an array of bytes to be written to the generated file. You must include UNICODE or UTF-8 signature bytes in the returned byte array, as this is a raw stream. The memory for rgbOutputFileContents must be allocated using the .NET Framework call, System.Runtime.InteropServices.AllocCoTaskMem, or the equivalent Win32 system call, CoTaskMemAlloc. The project system is responsible for freeing this memory</param>
        /// <param name="pcbOutput">[out] Returns the count of bytes in the rgbOutputFileContent array</param>
        /// <param name="pGenerateProgress">A reference to the IVsGeneratorProgress interface through which the generator can report its progress to the project system</param>
        /// <returns>If the method succeeds, it returns S_OK. If it fails, it returns E_FAIL</returns>
        public int Generate(string wszInputFilePath, string bstrInputFileContents, string wszDefaultNamespace, IntPtr[] rgbOutputFileContents, out uint pcbOutput,
                            IVsGeneratorProgress pGenerateProgress)
        {
            // TODO: There are a number of nested try catch blocks that should be cleaned up.
            // Make sure exception handling is properly laid out. This function has high
            // complexity (probably too high with cycl over 30), which makes error handling important. What
            // exceptions escape (ie. not handled)? What halts file generation? etc...
            try
            {
                // EnsureActiveProjectSet();

                VsOutputWindowPaneManager.OutputWindowWriteLine(vsOutputWindowPaneName, "");
                VsOutputWindowPaneManager.OutputWindowWriteLine(vsOutputWindowPaneName, string.Format("------ CSD file generation started: Configuration document: {0} ------", InputFilePath));

                Diagnostics.DebugWrite("VsMultipleFileGenerator => VSMFG.");

                ProjectItem configurationSectionModelFile = null;

                _bstrInputFileContents = bstrInputFileContents;
                _wszInputFilePath      = wszInputFilePath;
                _generatorProgress     = pGenerateProgress;
                _oldFileNames.Clear();
                _newFileNames.Clear();

                // Look through all the projects in the solution
                // The _project holds DTE reference, so not needed here.
                //DTE dte = (DTE)Package.GetGlobalService(typeof(DTE));
                //Diagnostics.DebugWrite("VSMFG.Generate >> dte.Solution.Projects.Count = {0}.", dte.Solution.Projects.Count);

                VsOutputWindowPaneManager.OutputWindowWrite(vsOutputWindowPaneName, "* Searching for configuration project handle... ");

                Project     project     = null;
                ProjectItem projectItem = null;
                if (!VsHelper.FindProjectContainingFile(InputFilePath, out projectItem, out project))
                {
                    // TODO: Will this fail if NEW diagram is created but not saved? Confirm. I THINK empty diagram is always saved to disk upon creation.
                    throw new ApplicationException("Could not retrieve Visual Studio ProjectItem and/or parent project containing this CSD diagram. Has this diagram been saved yet after being created?");
                }
                _project = project;

                // obtain a reference to the current project as an IVsProject type
                IVsProject vsProject = VsHelper.ToVsProject(_project); // ABM - Issue 10435: 2nd WindowsService project results in FAILURE here.
                Diagnostics.DebugWrite("VH.TFP >> IVsProject vsProject = VsHelper.ToVsProject( project='{0}' )", _project.Name);

                int  iFound = 0;
                uint itemId = 0;

                // this locates, and returns a handle to our source file, as a ProjectItem
                // TODO: 20140908: Might not be needed due to the new way I locate projectitem and project.
                VSDOCUMENTPRIORITY[] prio = new VSDOCUMENTPRIORITY[(int)VSDOCUMENTPRIORITY.DP_Standard];
                int result = vsProject.IsDocumentInProject(InputFilePath, out iFound, prio, out itemId); // ABM - Issue 10435: WindowsService project results in iFound=0!!!

                #region VSITEMID Documentation
                // itemid: Pointer to the item identifier of the document within the project.
                // NOTE: itemId is either a specific id pointing to the file, or is one of VSITEMID enumeration.
                // VSITEMID represents Special items inside a VsHierarchy:

                /*
                 * public enum VSITEMID
                 * {
                 * Selection = 4294967293, // all the currently selected items. // represents the currently selected item or items, which can include the root of the hierarchy.
                 * Root = 4294967294,      // the hierarchy itself. // represents the root of a project hierarchy and is used to identify the entire hierarchy, as opposed to a single item.
                 * Nil = 4294967295,       // no node.// represents the absence of a project item. This value is used when there is no current selection.
                 * }
                 */
                /*
                 * http://visual-studio.todaysummary.com/q_visual-studio_76086.html
                 *
                 * http://msdn.microsoft.com/en-us/subscriptions/downloads/microsoft.visualstudio.shell.interop.ivshierarchy(v=vs.100).aspx
                 * The IVsHierarchy interface is a generic interface to a hierarchy of nodes. Each node, including the root node, can have arbitrary
                 * properties associated with it. Each node on the hierarchy object is identified using a cookie (VSITEMID), which indicates a particular
                 * node. This cookie is invisible to the consumer of IVsHierarchy, and is typically a pointer to some private data maintained by the
                 * hierarchy's implementation.
                 *
                 * A VSITEMID is a DWORD uniquely identifying a node within a hierarchy. Itemids from one IVsHierarchy may not be passed to another hierarchy. Also, note that itemids have a limited lifetime, as indicated by events fired by the hierarchy, so holding on to itemids for long durations will require either the sinking of these events, or the conversion of the itemid into a canonical, persistable form.
                 *
                 * An item in a hierarchy can be a leaf node, a container of other items, or a link into some other hierarchy using GetNestedHierarchy.
                 *
                 * The IVsHierarchy interface is not used only for project hierarchies. For example, the Server Explorer window implements the IVsHierarchy interface to display its hierarchy, which is not a project hierarchy.
                 *
                 * There are times when it is useful to query a hierarchy about various virtual nodes, such as the hierarchy itself or the selected nodes within the hierarchy. Where such virtual nodes are potentially of interest, one of the predefined VSITEMID values may be passed.
                 *
                 * The environment views a project as a hierarchy, that is, a tree of nodes in which the nodes are project items. Each node also has a set of associated properties, and provides hierarchy management for VSPackages that implement project hierarchies.
                 *
                 * Notes to Implementers
                 * Implemented by VSPackages that create their own project hierarchy.
                 *
                 * Notes to Callers
                 * Called by the environment to get and set hierarchy properties.*/

                #endregion

                if (result != VSConstants.S_OK)
                {
                    throw new Exception("Unexpected error calling IVsProject.IsDocumentInProject.");
                }

                Diagnostics.DebugWrite("VH.TFP >> vsProject.IsDocumentInProject(inputFilePath, out iFound={0}, pdwPriority, out itemId={1}).", iFound, itemId);

                // if this source file is found in this project
                if (iFound != 0 && itemId != 0)
                {
                    Diagnostics.DebugWrite("VH.TFP >> (iFound != 0 && itemId != 0) == TRUE!!!");
                    Microsoft.VisualStudio.OLE.Interop.IServiceProvider oleSp = null;
                    vsProject.GetItemContext(itemId, out oleSp);
                    if (oleSp != null)
                    {
                        Diagnostics.DebugWrite("VH.TFP >> vsProject.GetItemContext( itemId, out oleSp ) >> oleSp != null! Getting ServiceProvider sp...");
                        ServiceProvider sp = new ServiceProvider(oleSp);
                        // convert our handle to a ProjectItem
                        configurationSectionModelFile = sp.GetService(typeof(ProjectItem)) as ProjectItem;

                        if (configurationSectionModelFile != null)
                        {
                            Diagnostics.DebugWrite("VH.TFP >>  configurationSectionModelFile = sp.GetService( typeof( ProjectItem ) ) as ProjectItem is NOT null! Setting this._project to the project we were working on...");
                            // We now have what we need. Stop looking.
                        }
                    }
                    else
                    {
                        throw new ApplicationException("Unable to retrieve Visual Studio ProjectItem");
                    }
                }
                else
                {
                    VsOutputWindowPaneManager.OutputWindowWriteLine(vsOutputWindowPaneName, "error: Unable to retrieve Visual Studio ProjectItem. File generation halted.");
                    throw new ApplicationException("Unable to retrieve Visual Studio ProjectItem. Try running the tool again.");
                }

                // ABM: Code below was the complex and error prone way to find project/items. Interface exists to easily
                // locate these items. This interface is used to set current project as local variable instead of here.
                /**/
                // [7296] FILE = ~\ConfigurationSectionDesigner\Debugging\Sample.csd.
                if (!VsHelper.TryFindProjectItemAndParentProject(InputFilePath, out _project, out configurationSectionModelFile) || _project == null)
                {
                    VsOutputWindowPaneManager.OutputWindowWriteLine(vsOutputWindowPaneName, "error: Unable to retrieve Visual Studio ProjectItem. File generation halted.");
                    throw new ApplicationException("Unable to retrieve Visual Studio ProjectItem. Try running the tool again.");
                }
                /**/
                VsOutputWindowPaneManager.OutputWindowWriteLine(vsOutputWindowPaneName, "found!");

                // Check out this CSD file. DISABLED: Too much can go wrong the way this generator is currently structured.

                /*if (_project.DTE.SourceControl.IsItemUnderSCC(InputFilePath) && !_project.DTE.SourceControl.IsItemCheckedOut(InputFilePath))
                 * { _project.DTE.SourceControl.CheckOutItem(InputFilePath); } */

                // Check for source control integration for the CSD item and check it out of needed.
                //if (VsHelper.IsItemUnderSourceControl(dte, configurationSectionModelFile))
                if (_project.DTE.SourceControl.IsItemUnderSCC(InputFilePath) &&
                    !_project.DTE.SourceControl.IsItemCheckedOut(InputFilePath))
                {
                    // ABM: For simplicity, we checkout the CSD file and all subitems. All file operations later down the chain will not have a SC issue.
                    // REASON: This generator has a unique design where null generated content means "don't write to file at this step". For cs files,
                    //         the write to file occurs outside of the iteration later on. For diagram, it never happens. All of these conditions
                    //         make selective SC checkout more complicated than the possible performance improvement is worth. Opinions?

                    VsHelper.CheckoutItem(_project.DTE, configurationSectionModelFile);
                }

                #region new

                // Get names of all of the existing files under CSD.
                foreach (ProjectItem childItem in configurationSectionModelFile.ProjectItems)
                {
                    _oldFileNames.Add(childItem.Name);
                }
                #endregion

                // now we can start our work, iterate across all the 'elements' in our source file.
                // Each of these items is a file extension.
                foreach (TIterativeElement item in this)
                {
                    // This try catch only exists for debugging purposes.
                    try
                    {
                        // obtain a name for this target file
                        string fileName = GetFileName(item);
                        Diagnostics.DebugWrite("VSMFG.Generate >> Filename for current element in loop is '{0}'", fileName);

                        // add it to the tracking cache
                        _newFileNames.Add(fileName);

                        // fully qualify the file on the filesystem
                        //string strFile = Path.Combine(wszInputFilePath.Substring(0, wszInputFilePath.LastIndexOf(Path.DirectorySeparatorChar)), fileName);
                        string strFile = Path.Combine(Path.GetDirectoryName(wszInputFilePath), fileName);

                        bool isNewAdded = !_oldFileNames.Contains(fileName);

                        /*
                         * if (!isNewAdded)
                         * {
                         *  if (_project.DTE.SourceControl.IsItemUnderSCC(strFile) && !_project.DTE.SourceControl.IsItemCheckedOut(strFile))
                         *  {
                         *      Diagnostics.DebugWrite("VSMFG.Generate >> Checking file out from source control '{0}'", fileName);
                         *      _project.DTE.SourceControl.CheckOutItem(strFile);
                         *  }
                         * }*/

                        // create the file
                        FileStream fs = null;

                        try
                        {
                            // generate our target file content
                            byte[] data = GenerateContent(item); // NOTE: For .diagram and .cs, this will be null, so those will not be written.

                            // if data is null, it means to ignore the contents of the generated file (no write to file).
                            if (data == null)
                            {
                                continue;
                            }

                            fs = File.Create(strFile);

                            #region Replaced code: Remove later.

                            /*if (!isNewAdded)
                             * {
                             *  // If the (xsd or config) file already exists, only save the data if the generated file is different than the existing file.
                             *  if (!Util.IsDataEqual(File.ReadAllBytes(strFile), data))
                             *  {
                             *      // Check out this file.
                             *      if (_project.DTE.SourceControl.IsItemUnderSCC(strFile) &&
                             *          !_project.DTE.SourceControl.IsItemCheckedOut(strFile))
                             *      {
                             *          Diagnostics.DebugWrite("VSMFG.Generate >> Checking file out from source control '{0}'", fileName);
                             *          _project.DTE.SourceControl.CheckOutItem(strFile);
                             *      }
                             *
                             *      Diagnostics.DebugWrite("VSMFG.Generate >> File data has changed for file '{0}'. Re-using existing file...", strFile);
                             *      fs = File.Open(strFile, FileMode.Truncate);
                             *  }
                             * }
                             * else
                             * {
                             *  // create the file
                             *  fs = File.Create(strFile);
                             * }*/

                            //if (fs != null) // We only write if file is modified or new.
                            //{

                            #endregion

                            VsOutputWindowPaneManager.OutputWindowWrite(vsOutputWindowPaneName, "* Generating the " + item + " file...");

                            // write it out to the stream
                            fs.Write(data, 0, data.Length);
                            fs.Close();
                            OnFileGenerated(strFile, isNewAdded);

                            // add the newly generated file to the solution, as a child of the source file
                            //if (!configurationSectionModelFile.ProjectItems.Cast<ProjectItem>().Any(pi => pi.Name == fileName))
                            if (isNewAdded)
                            {
                                ProjectItem itm = configurationSectionModelFile.ProjectItems.AddFromFile(strFile);

                                /*
                                 * Here you may wish to perform some addition logic such as, setting a custom tool for the target file if it
                                 * is intented to perform its own generation process.
                                 * Or, set the target file as an 'Embedded Resource' so that it is embedded into the final Assembly.
                                 *
                                 * EnvDTE.Property prop = itm.Properties.Item("CustomTool");
                                 * //// set to embedded resource
                                 * itm.Properties.Item("BuildAction").Value = 3;
                                 * if (String.IsNullOrEmpty((string)prop.Value) || !String.Equals((string)prop.Value, typeof(AnotherCustomTool).Name))
                                 * {
                                 *  prop.Value = typeof(AnotherCustomTool).Name;
                                 * }
                                 */
                            }
                            //}
                        }
                        catch (Exception e)
                        {
                            //GeneratorProgress.GeneratorError( false, 0, string.Format( "{0}\n{1}", e.Message, e.StackTrace ), -1, -1 );
                            //GeneratorProgress.GeneratorError(0, 0, string.Format("{0}\n{1}", e.Message, e.StackTrace), 0, 0);

                            if (File.Exists(strFile))
                            {
                                // TODO: ABM - Should we write this error to the file (breaking the build), or just show error and keep old file?
                                File.WriteAllText(strFile, "An exception occured while running the CsdFileGenerator on this file. See the Error List for details. E=" + e);
                            }
                            throw;
                        }
                        finally
                        {
                            if (fs != null)
                            {
                                fs.Close();
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        // This is here for debugging purposes, as setting a breakpoint here can be very helpful
                        Diagnostics.DebugWrite("VSMFG.Generate >> EXCEPTION: {0}", ex);
                        throw;
                    }
                }

                // perform some clean-up, making sure we delete any old (stale) target-files
                VsOutputWindowPaneManager.OutputWindowWrite(vsOutputWindowPaneName, "* Cleaning up existing files... ");
                foreach (ProjectItem childItem in configurationSectionModelFile.ProjectItems)
                {
                    string next;
                    DefaultExtension(out next);

                    if (!(childItem.Name.EndsWith(next) || _newFileNames.Contains(childItem.Name)))
                    {
                        // then delete it
                        childItem.Delete();
                    }
                }
                VsOutputWindowPaneManager.OutputWindowWriteLine(vsOutputWindowPaneName, "complete!");

                VsOutputWindowPaneManager.OutputWindowWrite(vsOutputWindowPaneName, "* Generating the class file... ");

                // generate our default content for our 'single' file
                byte[] defaultData = null;
                try
                {
                    // This will call GenerateAllContent(string.Format("{0}-gen", [cs or vb]));
                    defaultData = GenerateDefaultContent();
                }
                catch (Exception ex)
                {
                    Diagnostics.DebugWrite("VSMFG.Generate >> EXCEPTION: {0}", ex);
                    throw;
                    //GeneratorProgress.GeneratorError( false, 0, string.Format( "{0}\n{1}", ex.Message, ex.StackTrace ), -1, -1 );
                    //GeneratorProgress.GeneratorError(0, 0, string.Format("{0}\n{1}", ex.Message, ex.StackTrace), 0, 0);
                }
                VsOutputWindowPaneManager.OutputWindowWriteLine(vsOutputWindowPaneName, "complete!");

                if (defaultData == null)
                {
                    defaultData = new byte[0];
                }
                // return our default data (code behind file), so that Visual Studio may write it to disk.

                /*
                 * You need to write the bytes of the generated file into this variable. However, you cannot
                 * do it directly (hence the IntPtr[] type) ?instead, you must use the System.Runtime.InteropServices.AllocCoTaskMem
                 * allocator to create the memory and write type bytes in there.
                 */
                rgbOutputFileContents[0] = Marshal.AllocCoTaskMem(defaultData.Length);

                Marshal.Copy(defaultData, 0, rgbOutputFileContents[0], defaultData.Length);

                // must be set to the number of bytes that we wrote to rgbOutputFileContents.
                pcbOutput = (uint)defaultData.Length;

                //string codefileName = GetFileName(CodeFileExtension);
                //OnFileGenerated(codefileName, isNewAdded);

                VsOutputWindowPaneManager.OutputWindowWriteLine(vsOutputWindowPaneName, "========== CSD file generation: complete! ==========");
            }
            catch (Exception ex)
            {
                // Currently, all exceptions are rethrown to be caught here.
                OnError(ex);

                LogException(ex);

                rgbOutputFileContents[0] = IntPtr.Zero;
                pcbOutput = 0;
            }

            return(0);
        }