public static ProjectItem FindFileInProject(this Project project, string fileName) { int iFound = 0; uint itemId = 0; EnvDTE.ProjectItem item = null; Microsoft.VisualStudio.Shell.Interop.VSDOCUMENTPRIORITY[] pdwPriority = new Microsoft.VisualStudio.Shell.Interop.VSDOCUMENTPRIORITY[1]; // obtain a reference to the current project as an IVsProject type Microsoft.VisualStudio.Shell.Interop.IVsProject VsProject = VsHelper.ToVsProject(project); // this locates, and returns a handle to our source file, as a ProjectItem VsProject.IsDocumentInProject(fileName, out iFound, pdwPriority, out itemId); // if our source file was found in the project (which it should have been) if (iFound != 0 && itemId != 0) { Microsoft.VisualStudio.OLE.Interop.IServiceProvider oleSp = null; VsProject.GetItemContext(itemId, out oleSp); if (oleSp != null) { ServiceProvider sp = new ServiceProvider(oleSp); // convert our handle to a ProjectItem item = sp.GetService(typeof(EnvDTE.ProjectItem)) as EnvDTE.ProjectItem; } else { throw new ApplicationException("Unable to retrieve Visual Studio ProjectItem"); } } else { throw new ApplicationException("Unable to retrieve Visual Studio ProjectItem"); } return(item); }
public void Generate(string inputFilePath, string inputFileContents, string defaultNamespace, out IntPtr outputFileContents, out int output, IVsGeneratorProgress generateProgress) { try { if (cancelGenerating) { byte[] fileData = File.ReadAllBytes(Path.ChangeExtension(inputFilePath, GetDefaultExtension())); // Return our summary data, so that Visual Studio may write it to disk. outputFileContents = Marshal.AllocCoTaskMem(fileData.Length); Marshal.Copy(fileData, 0, outputFileContents, fileData.Length); output = fileData.Length; return; } this.inputFileContents = inputFileContents; this.inputFilePath = inputFilePath; this.defaultNamespace = defaultNamespace; int iFound = 0; uint itemId = 0; ProjectItem projectItem; Microsoft.VisualStudio.Shell.Interop.VSDOCUMENTPRIORITY[] pdwPriority = new Microsoft.VisualStudio.Shell.Interop.VSDOCUMENTPRIORITY[1]; // Obtain a reference to the current project as an IVsProject type Microsoft.VisualStudio.Shell.Interop.IVsProject VsProject = VsHelper.ToVsProject(project); // This locates, and returns a handle to our source file, as a ProjectItem VsProject.IsDocumentInProject(InputFilePath, out iFound, pdwPriority, out itemId); // If our source file was found in the project (which it should have been) if (iFound != 0 && itemId != 0) { Microsoft.VisualStudio.OLE.Interop.IServiceProvider oleSp = null; VsProject.GetItemContext(itemId, out oleSp); if (oleSp != null) { ServiceProvider sp = new ServiceProvider(oleSp); // Convert our handle to a ProjectItem projectItem = sp.GetService(typeof(ProjectItem)) as ProjectItem; } else { throw new ApplicationException("Unable to retrieve Visual Studio ProjectItem"); } } else { throw new ApplicationException("Unable to retrieve Visual Studio ProjectItem"); } oldFileNames.Clear(); newFileNames.Clear(); foreach (ProjectItem childItem in projectItem.ProjectItems) { oldFileNames.Add(childItem.Name); if (!childItem.Name.EndsWith(".cs")) { childItem.Properties.Item("BuildAction").Value = 0; } } // Now we can start our work, iterate across all the 'items' in our source file foreach (T item in this) { // Obtain a name for this target file string fileName = GetFileName(item); // Add it to the tracking cache newFileNames.Add(fileName); // Fully qualify the file on the filesystem string filePath = Path.Combine(Path.GetDirectoryName(inputFilePath), fileName); if (!(item as IChangable).IsChanged && File.Exists(filePath)) { continue; } try { bool isNewAdded = !oldFileNames.Contains(fileName); if (!isNewAdded) { // Check out this file. if (project.DTE.SourceControl.IsItemUnderSCC(filePath) && !project.DTE.SourceControl.IsItemCheckedOut(filePath)) { project.DTE.SourceControl.CheckOutItem(filePath); } } // Create the file FileStream fs = File.Create(filePath); try { // Generate our target file content byte[] data = GenerateContent(item); // Write it out to the stream fs.Write(data, 0, data.Length); fs.Close(); OnFileGenerated(filePath, isNewAdded); /* * 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"); * * if (String.IsNullOrEmpty((string)prop.Value) || !String.Equals((string)prop.Value, typeof(AnotherCustomTool).Name)) * { * prop.Value = typeof(AnotherCustomTool).Name; * } */ } catch (Exception ex) { fs.Close(); OnError(ex); LogException(ex); } } catch (Exception ex) { throw ex; } } // Perform some clean-up, making sure we delete any old (stale) target-files foreach (ProjectItem childItem in projectItem.ProjectItems) { if (!(childItem.Name.EndsWith(GetDefaultExtension()) || newFileNames.Contains(childItem.Name))) { // Then delete it childItem.Delete(); } } foreach (var newFileName in newFileNames) { if (!oldFileNames.Contains(newFileName)) { string fileName = Path.Combine(inputFilePath.Substring(0, inputFilePath.LastIndexOf(Path.DirectorySeparatorChar)), newFileName); // Add the newly generated file to the solution, as a child of the source file... ProjectItem itm = projectItem.ProjectItems.AddFromFile(fileName); // Set buildaction to none if (!newFileName.EndsWith(".cs")) { itm.Properties.Item("BuildAction").Value = 0; } } } // Generate our summary content for our 'single' file byte[] summaryData = GenerateSummaryContent(); if (summaryData == null) { outputFileContents = IntPtr.Zero; output = 0; } else { // Return our summary data, so that Visual Studio may write it to disk. outputFileContents = Marshal.AllocCoTaskMem(summaryData.Length); Marshal.Copy(summaryData, 0, outputFileContents, summaryData.Length); output = summaryData.Length; } } catch (Exception ex) { OnError(ex); LogException(ex); outputFileContents = IntPtr.Zero; output = 0; } }