I’m guessing that this post will be useful to a very small number of people if at all. However there might be a bigger lesson here for people writing their own collections and that is how not to code GetEnumerator method.
but first some background information.
when working with a visual studio add-in I needed find out weather a specific project is excluded from the build cycle.
the DTE provide interfaces and object to access this info and the code I ended up with looked like this:
1: foreach (SolutionContext context in
2: ApplicationObject.Solution.SolutionBuild.
3: ActiveConfiguration.SolutionContexts)
4: {
5: if (context.ProjectName.Contains(project.Name))
6: return !context.ShouldBuild;
7: }
However, this code resulted in an exception popping from time to time which took me a little while to understand.
the exception I got was :
System.ArgumentException
The parameter is incorrect. (Exception from HRESULT: 0x80070057 (E_INVALIDARG))
System.Collections.IEnumerator GetEnumerator()
at EnvDTE.SolutionContexts.GetEnumerator()
where the line number pointed to the foreach statement.
After some digging I found that this happens if in the solution you have an unloaded project as part of the solution. and the fix was quite simple jut replace the foreach with a simple for resulting in something like:
1: var contexts = ApplicationObject.Solution.
2: SolutionBuild.ActiveConfiguration.
3: SolutionContexts;
4:
5: for (int i = 0; i < contexts.Count; i++)
6: {
7: try
8: {
9: var context = contexts.Item(i + 1);
10: if (context.ProjectName.Contains(project.Name))
11: return !context.ShouldBuild;
12: }
13: catch (ArgumentException)
14: {
15: //this is thrown when a project is unloaded
16: }
17: }
18: return false;
I think this is a mistake, in general if a piece of the information is missing don’t fail the entire operation just exclude that piece from the result. that way you will enable the user to decide what to do with the info he does have.
what do you think?
9 comments:
Ha! Thanks buddy, I am on of those very few people that you actually helped!
And I thought this was way to esoteric to actually help someone.
thank you
Thanks a lot, I just found this, didn't think to use "for" and "Item()" as a workaround
Glad to know this helps people.
it is really a nasty behavior
Add one more to the count of esoteric people you helped out. :)
Also FWIW this appears to be fixed in VS2012 RC.
good to know.
thank you for sharing
Hey, thanks man! Just received a log from our customer having E_INVALIDARG in SolutionContexts.GetEnumerator() and found your post.
Worked like a charm.
I can tell you that you saved my day. I've been on this one for two days with vs 2010.
Also thanks for the SolutionContexts.Item(i + 1). Documentation doesn't tell you that index is NOT zero based.
Thanks again.
Post a Comment