/// <summary> /// Called by Visual Studio when it needs to generate or /// regenerate the code file from your the custom tool /// input file. /// </summary> /// <param name="wszInputFilePath"></param> /// <param name="bstrInputFileContents"></param> /// <param name="wszDefaultNamespace"></param> /// <param name="rgbOutputFileContents"></param> /// <param name="pcbOutput"></param> /// <param name="pGenerateProgress"></param> /// <returns></returns> int IVsSingleFileGenerator.Generate(string wszInputFilePath, string bstrInputFileContents, string wszDefaultNamespace, IntPtr[] rgbOutputFileContents, out uint pcbOutput, IVsGeneratorProgress pGenerateProgress) { GenerationEventArgs gea = new GenerationEventArgs( bstrInputFileContents, wszInputFilePath, wszDefaultNamespace, new ServiceProvider(Site as Microsoft.VisualStudio.OLE.Interop.IServiceProvider) .GetService(typeof(ProjectItem)) as ProjectItem); if (OnGenerateCode != null) { OnGenerateCode(this, gea); } if (gea.OutputFileExtension.StartsWith(".")) { this.FileExtension = gea.OutputFileExtension; } else { this.FileExtension = "." + gea.OutputFileExtension; } GenerationProgressFacade progressFacade = new GenerationProgressFacade(pGenerateProgress); foreach (GenerationWarning warning in gea.Warnings) { progressFacade.GenerateWarning( warning.Message, warning.LineNumber, warning.ColumnNumber); } foreach (GenerationError error in gea.Errors) { progressFacade.GenerateError( error.Message, error.LineNumber, error.ColumnNumber); } byte[] bytes = gea.GetOutputCodeBytes(); int outputLength = bytes.Length; rgbOutputFileContents[0] = Marshal.AllocCoTaskMem(outputLength); Marshal.Copy(bytes, 0, rgbOutputFileContents[0], outputLength); pcbOutput = (uint)outputLength; if (gea.FailOnError && gea.Errors.Count > 0) { return VSConstants.E_FAIL; } else { return VSConstants.S_OK; } }
static void GenerateErrorWithPosition(string line, GenerationEventArgs e) { Match match = gccErrorFormat.Match(line); int row, col; if(match.Success && int.TryParse(match.Groups[1].Value, out row) && int.TryParse(match.Groups[2].Value, out col)) { e.GenerateError(line, row-1, col-1); // note offsets! } else { e.GenerateError(line); } }
public void GenerationHandler(object s, GenerationEventArgs e) { // Fail on any error e.FailOnError = true; string tmp = Path.GetTempFileName(); try { string[] args = GetProtoGenArgs(e.InputFilePath, tmp, e.OutputFileExtension, e.Namespace); bool writeWhatWeDid = true; string root = GetInstallPath(null), app = GetInstallPath("protogen.exe"); if (!File.Exists(app)) { e.GenerateError("Missing: " + app); return; } int result; ProcessStartInfo psi = new ProcessStartInfo(app); psi.CreateNoWindow = true; psi.WorkingDirectory = root; StringBuilder sb = new StringBuilder(); foreach (string arg in args) { sb.Append("\"" + arg + "\" "); } psi.Arguments = sb.ToString(); psi.WindowStyle = ProcessWindowStyle.Hidden; using (Process proc = Process.Start(psi)) { proc.WaitForExit(); result = proc.ExitCode; } /*AppDomain ad = AppDomain.CreateDomain("protogen", null, root, "", false); try { result = ad.ExecuteAssembly(app, null, args); writeWhatWeDid = result != 0; } finally { AppDomain.Unload(ad); }*/ if (writeWhatWeDid) { #if DEBUG2 e.GenerateWarning(app); foreach (string arg in args) e.GenerateWarning(arg); #endif } using(var lineReader = File.OpenText(tmp)) { string line; switch(result) { case 0: while((line = lineReader.ReadLine()) != null) { e.OutputCode.AppendLine(line); } break; default: bool hasErrorText = false; while((line = lineReader.ReadLine()) != null) { GenerateErrorWithPosition(line, e); hasErrorText = true; } if(!hasErrorText) { e.GenerateError("Code generation failed with exit-code " + result); } break; } } #region ensure protobuf-net.dll is in the project: try { VSProject project = (VSProject)e.ProjectItem.ContainingProject.Object; bool hasRef = project.References.Cast<Reference>() .Any(r => r != null && string.Equals(r.Name, "protobuf-net", StringComparison.InvariantCultureIgnoreCase)); if (!hasRef) { string toolPath = GetInstallPath(PBNETDLL); /* REMOVED: copy dll into local project string projectPath = Path.Combine( Path.GetDirectoryName(e.ProjectItem.ContainingProject.FullName), PBNETDLL); // copy it into the project if needed if(!File.Exists(projectPath)) { File.Copy(toolPath, projectPath); } */ // add the reference (from the install location) Reference dllRef = project.References.Add(toolPath); dllRef.CopyLocal = true; } } catch (Exception ex) { e.GenerateWarning("Failed to add reference to protobuf-net:" + ex.Message); } #endregion } finally { try { File.Delete(tmp); } catch (Exception ex) { e.GenerateWarning(ex.Message); } } }
public void GenerationHandler(object s, GenerationEventArgs e) { // Fail on any error e.FailOnError = true; string tmp = Path.GetTempFileName(); try { string[] args = GetProtoGenArgs(e.InputFilePath, tmp, e.OutputFileExtension, e.Namespace); bool writeWhatWeDid = true; string root = GetInstallPath(null), app = GetInstallPath("protogen.exe"); if (!File.Exists(app)) { e.GenerateError("Missing: " + app); return; } int result; ProcessStartInfo psi = new ProcessStartInfo(app); psi.CreateNoWindow = true; psi.WorkingDirectory = root; StringBuilder sb = new StringBuilder(); foreach (string arg in args) { sb.Append("\"" + arg + "\" "); } psi.Arguments = sb.ToString(); psi.WindowStyle = ProcessWindowStyle.Hidden; using (Process proc = Process.Start(psi)) { proc.WaitForExit(); result = proc.ExitCode; } /*AppDomain ad = AppDomain.CreateDomain("protogen", null, root, "", false); * * try * { * result = ad.ExecuteAssembly(app, null, args); * writeWhatWeDid = result != 0; * } * finally * { * AppDomain.Unload(ad); * }*/ if (writeWhatWeDid) { #if DEBUG2 e.GenerateWarning(app); foreach (string arg in args) { e.GenerateWarning(arg); } #endif } using (var lineReader = File.OpenText(tmp)) { string line; switch (result) { case 0: while ((line = lineReader.ReadLine()) != null) { e.OutputCode.AppendLine(line); } break; default: bool hasErrorText = false; while ((line = lineReader.ReadLine()) != null) { GenerateErrorWithPosition(line, e); hasErrorText = true; } if (!hasErrorText) { e.GenerateError("Code generation failed with exit-code " + result); } break; } } #region ensure protobuf-net.dll is in the project: try { VSProject project = (VSProject)e.ProjectItem.ContainingProject.Object; bool hasRef = project.References.Cast <Reference>() .Any(r => r != null && string.Equals(r.Name, "protobuf-net", StringComparison.InvariantCultureIgnoreCase)); if (!hasRef) { string toolPath = GetInstallPath(PBNETDLL); /* REMOVED: copy dll into local project * string projectPath = Path.Combine( * Path.GetDirectoryName(e.ProjectItem.ContainingProject.FullName), * PBNETDLL); * // copy it into the project if needed * if(!File.Exists(projectPath)) * { * File.Copy(toolPath, projectPath); * } */ // add the reference (from the install location) Reference dllRef = project.References.Add(toolPath); dllRef.CopyLocal = true; } } catch (Exception ex) { e.GenerateWarning("Failed to add reference to protobuf-net:" + ex.Message); } #endregion } finally { try { File.Delete(tmp); } catch (Exception ex) { e.GenerateWarning(ex.Message); } } }