您如何在 Visual Studio 2017 年以编程方式 运行 静态代码分析?
How do you programmatically run Static Code Analysis in Visual Studio 2017?
我正在研究本地化遗留应用程序的解决方案。我已经使用 EnvDte 编写了一个 Visual studio 加载项,它自动将解决方案中每个表单的 "Localizable" 标志设置为 true,这是提取表单设计器资源的关键步骤。我现在正在尝试处理任何以编程方式设置的文本,即触发 Globalization (CA13##) 警告的文本。
designer.Visible = true;
var host = (IDesignerHost)designer.Object;
var provider = TypeDescriptor.GetProvider(host.RootComponent);
var typeDescriptor = provider.GetExtendedTypeDescriptor(host.RootComponent);
if (typeDescriptor == null)
continue;
var propCollection = typeDescriptor.GetProperties();
var propDesc = propCollection["Localizable"];
if (propDesc != null && host.RootComponent != null &&
(bool?)propDesc.GetValue(host.RootComponent) != true)
{
try
{
propDesc.SetValue(host.RootComponent, true);
}
catch (Exception ex)
{
// log the error
}
// save changes
}
我已经能够从菜单中手动 运行 它使用:分析 -> 运行 代码分析 -> 在解决方案 得到问题列表,但我想使用 运行s 的另一个加载项自动执行此步骤并提取结果。
是否有指向访问构建警告或代码分析结果的资源?
是否有已经使用 EnvDte 或 Roslyn 执行此操作的解决方案?
好的,我已经设法收集了足够的信息来组合加载项。简而言之,您使用 _dte.ExecuteCommand()
初始化命令:
// nothing to see here...
_package = package ?? throw new ArgumentNullException(nameof(package));
var commandService = ServiceProvider.GetService(typeof(IMenuCommandService)) as OleMenuCommandService;
if (commandService == null)
return;
_dte = (DTE2)ServiceProvider.GetService(typeof(DTE));
var menuCommandId = new CommandID(CommandSet, CommandId);
var menuItem = new MenuCommand(MenuItemCallback, menuCommandId);
commandService.AddCommand(menuItem);
_events = _dte.Events.BuildEvents;
// since static code analysis is a sort of build you need to hook into OnBuildDone
_events.OnBuildDone += OnBuildDone;
触发分析
private void MenuItemCallback(object sender, EventArgs e)
{
_dte.ExecuteCommand("Build.RunCodeAnalysisonSolution");
}
在 OnBuildDone 事件中提取错误
private void OnBuildDone(vsBuildScope scope, vsBuildAction action)
{
Dispatcher.CurrentDispatcher.InvokeAsync(new Action(() =>
{
_dte.ExecuteCommand("View.ErrorList", " ");
var errors = _dte.ToolWindows.ErrorList.ErrorItems;
for (int i = 1; i <= errors.Count; i++)
{
ErrorItem error = errors.Item(i);
var code = error.Collection.Item(1);
var item = new
{
error.Column,
error.Description,
error.ErrorLevel,
error.FileName,
error.Line,
error.Project
};
error.Navigate(); // you can navigate to the error if you wanted to.
}
});
}
我正在研究本地化遗留应用程序的解决方案。我已经使用 EnvDte 编写了一个 Visual studio 加载项,它自动将解决方案中每个表单的 "Localizable" 标志设置为 true,这是提取表单设计器资源的关键步骤。我现在正在尝试处理任何以编程方式设置的文本,即触发 Globalization (CA13##) 警告的文本。
designer.Visible = true;
var host = (IDesignerHost)designer.Object;
var provider = TypeDescriptor.GetProvider(host.RootComponent);
var typeDescriptor = provider.GetExtendedTypeDescriptor(host.RootComponent);
if (typeDescriptor == null)
continue;
var propCollection = typeDescriptor.GetProperties();
var propDesc = propCollection["Localizable"];
if (propDesc != null && host.RootComponent != null &&
(bool?)propDesc.GetValue(host.RootComponent) != true)
{
try
{
propDesc.SetValue(host.RootComponent, true);
}
catch (Exception ex)
{
// log the error
}
// save changes
}
我已经能够从菜单中手动 运行 它使用:分析 -> 运行 代码分析 -> 在解决方案 得到问题列表,但我想使用 运行s 的另一个加载项自动执行此步骤并提取结果。
是否有指向访问构建警告或代码分析结果的资源?
是否有已经使用 EnvDte 或 Roslyn 执行此操作的解决方案?
好的,我已经设法收集了足够的信息来组合加载项。简而言之,您使用 _dte.ExecuteCommand()
初始化命令:
// nothing to see here... _package = package ?? throw new ArgumentNullException(nameof(package)); var commandService = ServiceProvider.GetService(typeof(IMenuCommandService)) as OleMenuCommandService; if (commandService == null) return; _dte = (DTE2)ServiceProvider.GetService(typeof(DTE)); var menuCommandId = new CommandID(CommandSet, CommandId); var menuItem = new MenuCommand(MenuItemCallback, menuCommandId); commandService.AddCommand(menuItem); _events = _dte.Events.BuildEvents; // since static code analysis is a sort of build you need to hook into OnBuildDone _events.OnBuildDone += OnBuildDone;
触发分析
private void MenuItemCallback(object sender, EventArgs e) { _dte.ExecuteCommand("Build.RunCodeAnalysisonSolution"); }
在 OnBuildDone 事件中提取错误
private void OnBuildDone(vsBuildScope scope, vsBuildAction action) { Dispatcher.CurrentDispatcher.InvokeAsync(new Action(() => { _dte.ExecuteCommand("View.ErrorList", " "); var errors = _dte.ToolWindows.ErrorList.ErrorItems; for (int i = 1; i <= errors.Count; i++) { ErrorItem error = errors.Item(i); var code = error.Collection.Item(1); var item = new { error.Column, error.Description, error.ErrorLevel, error.FileName, error.Line, error.Project }; error.Navigate(); // you can navigate to the error if you wanted to. } }); }