ProjectItem _FindItem(string path) { int iFound = 0; uint itemId = 0; EnvDTE.ProjectItem item; Microsoft.VisualStudio.Shell.Interop.VSDOCUMENTPRIORITY[] pdwPriority = new Microsoft.VisualStudio.Shell.Interop.VSDOCUMENTPRIORITY[1]; for (var i = 0; i < _projects.Length; i++) { Microsoft.VisualStudio.Shell.Interop.IVsProject vsProject = VSUtility.ToVsProject(_projects.GetValue(i) as EnvDTE.Project); vsProject.IsDocumentInProject(path, out iFound, pdwPriority, out itemId); if (iFound != 0 && itemId != 0) { Microsoft.VisualStudio.OLE.Interop.IServiceProvider oleSp = null; vsProject.GetItemContext(itemId, out oleSp); if (null != oleSp) { ServiceProvider sp = new ServiceProvider(oleSp); // convert our handle to a ProjectItem item = sp.GetService(typeof(EnvDTE.ProjectItem)) as EnvDTE.ProjectItem; return(item); } } } return(null); }
public int Generate(string wszInputFilePath, string bstrInputFileContents, string wszDefaultNamespace, IntPtr[] rgbOutputFileContents, out uint pcbOutput, IVsGeneratorProgress pGenerateProgress) { string outp = ""; string errp = ""; try { if (null == _site) { throw new InvalidOperationException("The Rolex custom tool can only be used in a design time environment. Consider using Rolex as a pre-build step instead."); } wszInputFilePath = Path.GetFullPath(wszInputFilePath); var item = _FindItem(wszInputFilePath); if (null == item) { throw new ApplicationException("Design time environment project item fetch failed."); } if (0 != string.Compare("cs", VSUtility.GetProjectLanguageFromItem(item), StringComparison.InvariantCultureIgnoreCase)) { throw new NotSupportedException("The Rolex generator only supports C# projects"); } var dir = Path.GetDirectoryName(wszInputFilePath); var scannerFile = Path.GetFileNameWithoutExtension(wszInputFilePath) + ".cs"; var proj = item.ContainingProject; var pil = new List <object>(proj.ProjectItems.Count); foreach (EnvDTE.ProjectItem pi in proj.ProjectItems) { if (pi != item) { pil.Add(pi); } } var genShared = !VSUtility.HasClassOrStruct(pil, wszDefaultNamespace, "Token"); pGenerateProgress.Progress(0, 2); ProcessStartInfo psi = new ProcessStartInfo(); psi.FileName = "rolex"; psi.CreateNoWindow = true; psi.UseShellExecute = false; psi.Arguments = "\"" + wszInputFilePath.Replace("\"", "\"\"") + "\""; psi.Arguments += " /output -";//\"" + Path.Combine(dir, scannerFile).Replace("\"", "\"\"") + "\""; psi.Arguments += " /namespace \"" + wszDefaultNamespace + "\""; if (!genShared) { psi.Arguments += " /noshared"; } psi.RedirectStandardOutput = true; psi.RedirectStandardError = true; var isSuccess = false; using (var proc = new Process()) { proc.StartInfo = psi; proc.Start(); outp = proc.StandardOutput.ReadToEnd().TrimEnd(); errp = proc.StandardError.ReadToEnd().TrimEnd(); if (!proc.HasExited) { proc.WaitForExit(); } isSuccess = 0 == proc.ExitCode; } var outputPath = Path.Combine(dir, scannerFile); pGenerateProgress.Progress(1, 2); if (!isSuccess) { _DumpErrors(errp, pGenerateProgress); //pGenerateProgress.GeneratorError(0, 0, "Rolex failed: " + errp, unchecked((uint)-1), unchecked((uint)-1)); } else { // have used streams here in the past to scale, but even for huge items, this is faster! // most likely due to the lack of extra copies (memory/array resizing) byte[] bytes = Encoding.UTF8.GetBytes(outp); int length = bytes.Length; rgbOutputFileContents[0] = Marshal.AllocCoTaskMem(length); Marshal.Copy(bytes, 0, rgbOutputFileContents[0], length); pcbOutput = (uint)length; return(VSConstants.S_OK); } } catch (Exception ex) { pGenerateProgress.GeneratorError(0, 0, "Rolex custom tool failed with: " + ex.Message, unchecked ((uint)-1), unchecked ((uint)-1)); errp += "Rolex custom tool failed with: " + ex.Message; } finally { try { pGenerateProgress.Progress(2, 2); } catch { } } // have used streams here in the past to scale, but even for huge items, this is faster! // most likely due to the lack of extra copies (memory/array resizing) pcbOutput = (uint)0; return(VSConstants.S_OK); }