In C#, what and how to pass IServiceProvider in ErrorListProvider(IServiceProvider isp)?

543 Views Asked by At

I am creating a vsix project where I need to add some custom errors in Error List window. Now I am stuck in IServiceProvider. What it contains and why I need this and how I can get this? In my code, I need to initialize with a service provider. How can I do this? Following is code :

internal class ErrorListManager
{
    public static ErrorListProvider errorListProvider;

    public static void Initialize(IServiceProvider serviceProvider) 
    {
        errorListProvider = new ErrorListProvider(serviceProvider);

    }

    public static void AddError(string errorMsg) {
        AddTask(errorMsg, TaskErrorCategory.Error);
    }

    private static void AddTask(string errorMsg, TaskErrorCategory category)
    {
        errorListProvider.Tasks.Add(new ErrorTask
        {
            Category = TaskCategory.User,
            ErrorCategory = category,
            Text = errorMsg
        });
    }
}

Please help. I am a beginner for C# and VSIX. Thanks!

2

There are 2 best solutions below

7
Ionut Enache On BEST ANSWER

To write something in VS Error List you need to use ErrorListProvider. In my implementation, I inherit from ErrorListProvider and implement my own behavior for "ErrorWindowController". The code looks like this (read the code comments for more information):

public class ErrorWindowController : ErrorListProvider
{

#region Constructor

/// <summary>
/// Instance Constructor
/// </summary>
/// <param name="aServiceProvider"></param>
public ErrorWindowController(IServiceProvider aIServiceProvider) : base(aIServiceProvider)
{
}

#endregion


#region Public Methods

// Use this to add a collection of custom errors in VS Error List
public void AddErrors(IEnumerable<ErrorModel> aErrors)
{
    SuspendRefresh();

    foreach (ErrorModel error in aErrors)
    {
      ErrorTask errorTask = new ErrorTask
      {
        ErrorCategory = error.Category,
        Document = error.FilePath,
        Text = error.Description,
        Line = error.Line - 1,
        Column = error.Column,
        Category = TaskCategory.BuildCompile,
        Priority = TaskPriority.High,
        HierarchyItem = error.HierarchyItem
      };
      errorTask.Navigate += ErrorTaskNavigate;
      Tasks.Add(errorTask);
    }

    BringToFront();
    ResumeRefresh();
}

// Remove all the errors from Error List which are depending of a project and this specific project is closed
// Or remove all the errors from Error List when the VS solution is closed
public void RemoveErrors(IVsHierarchy aHierarchy)
{
    SuspendRefresh();

    for (int i = Tasks.Count - 1; i >= 0; --i)
    {
      var errorTask = Tasks[i] as ErrorTask;
      aHierarchy.GetCanonicalName(Microsoft.VisualStudio.VSConstants.VSITEMID_ROOT, out string nameInHierarchy);
      errorTask.HierarchyItem.GetCanonicalName(Microsoft.VisualStudio.VSConstants.VSITEMID_ROOT, out string nameErrorTaskHierarchy);
      if (nameInHierarchy == nameErrorTaskHierarchy)
      {
        errorTask.Navigate -= ErrorTaskNavigate;
        Tasks.Remove(errorTask);
      }
    }

    ResumeRefresh();
}

// Remove all the errors from the Error List
public void Clear()
{
    Tasks.Clear();
}


#endregion


#region Private Methods

// This is optional
// Add navigation for your errors. 
private void ErrorTaskNavigate(object sender, EventArgs e)
{
  ErrorTask objErrorTask = (ErrorTask)sender;
  objErrorTask.Line += 1;
  bool bResult = Navigate(objErrorTask, new Guid(EnvDTE.Constants.vsViewKindCode));
  objErrorTask.Line -= 1;
}


#endregion
}

The ErrorModel is very simple:

public class ErrorModel
{
  #region Properties

  public string FilePath { get; set; }

  public int Line { get; set; }

  public int Column { get; set; }

  public TaskErrorCategory Category { get; set; }

  public string Description { get; set; }

  public IVsHierarchy HierarchyItem { get; set; }

  #endregion

}

Happy Codding!

5
Carlos Quintero On

Your package is a service provider. Its base class AsyncPackage derives from the Package class which implements OLE.Interop.IServiceProvider and System.IServiceProvider (yes, VSX is confusing and there are two IServiceProvider interfaces). So, from your package class you would call ErrorListManager.Initialize(this).

That said, you may want to use the new API of VS 2015 and higher for the ErrorList. The old approach that you are using doesn't allow you to add values to columns such as "Code", etc. See samples here:

VSSDK-Extensibility-Samples/ErrorList: https://github.com/microsoft/VSSDK-Extensibility-Samples/tree/master/ErrorList

madskristensen/WebAccessibilityChecker: https://github.com/madskristensen/WebAccessibilityChecker/tree/master/src/ErrorList

madskristensen/TaskOutputListener: https://github.com/madskristensen/TaskOutputListener/blob/master/src/ErrorListProvider/ErrorListProvider.cs