Hello again After relative long time without major problems I've found one that I cannot deal with. Here is overview: I've created visual studio extension for language used in my company. It's based mostly on IronPython, and it almost works :) Ok, it works. But there is one small problem: I'd like to include feature that makes changes inside text file when user changes its name in solution explorer. For example: if user changes name of the file from "File1" to "File2", first method's name inside this file is being changed from File1 to File2. Please don't ask me why to do this... Anyway I've localised method "ParseSource" inside LanguageService package. Inside it there is object of type Source, called "source". It has method called SetText that, in theory ( http://msdn.microsoft.com/zh-cn/library/bb135763.aspx) can change text. Unfortunately there is small problem when I try to do this. There is COM exception thrown: So I have a question: is this only my problem? I mean: only I experience this? If so, is there a other way to achieve goal that I described above? If I'd find the way to set text, how to know when name of the file is changed? Is there any event or so? Thank you in advance Best regards Paul | | PaulTheMe Monday, October 05, 2009 8:43 AM | Hi Paul,
I did a quick check of the rename feature as implemented by C#. When the user attempts to rename a file via the solution explorer, the underlying project hierarchy's implementation of IVsUIHierarchy::SetProperty is invoked to set the VSHPROPID_EditLabel. When this in called the underlying project system renames the file and then uses the underlying CodeElement2::RenameSymbol to refactor the base class name.
If your project type is based on the MPF_Proj sources, I suspect you could add the refactoring capability at the end of the internal RenameDocument method on the FileNode class. That would probably be a logical place to start.
Sincerely, Ed Dore- Marked As Answer byChao KuoMSFT, ModeratorTuesday, October 13, 2009 6:07 AM
- Proposed As Answer byEd DoreMSFT, ModeratorMonday, October 12, 2009 9:03 PM
-
| | Ed Dore Monday, October 12, 2009 9:03 PM | Hi, Paul
For the exception, I would much appreciate you, if you could post your solution here. For your second question, the automation model has already provide you the event for the renaming of projectItem. For this you can reference this ProjectItemsEventsClass.ItemRenamed Event. Thanks Chao | | Chao Kuo Wednesday, October 07, 2009 3:12 AM | Good day Thank You for reply Chao. There are two things that I'd like to add. 1) Exception thing: I think that I've posted not clearly, and You took my question as an answer :) In my work I found this error(?) with Source object, and I cannot deal with it. COM exception is thrown, when I try to use method source.SetText("example"); I don't know why and how to fix it. 2)Event thing: great! But unfortunately don't work in my project :(. Here is how I use this. In my ProjectPackage I define new object:
public EnvDTE.ProjectItemsEventsClass eClass = new EnvDTE.ProjectItemsEventsClass();
Inside constructor I add: MyProjectPackage(){ eClass.ItemRenamed += new EnvDTE._dispProjectItemsEvents_ItemRenamedEventHandler(eClass_ItemRenamed); }
And inside class I
define new method:
public sealed class MyProjectPackage: ProjectPackage{ void eClass_ItemRenamed(EnvDTE.ProjectItem ProjectItem, string OldName){ throw new NotImplementedException(); } }
It compiles and when I try to run it, communication box pops up - something that ProjectPackage failed to load. I cannot open my custom project then. Please - give me a piece of advice: do I do it right? Maybe I shouldn't define these objects/methods in this way?
Thank You in advance
Paul | | PaulTheMe Wednesday, October 07, 2009 7:30 AM | Hi, Paul
To ProjectItemsEventsClass.ItemRenamed Event, you should get the DTE service first. Just like.
DTE dte = GetService(typeof(SDTE)) as DTE;
dte.Events.SolutionItemsEvents.ItemRenamed += new _dispProjectItemsEvents_ItemRenamedEventHandler(eClass_ItemRenamed);
If GetService is not available, you should try Package.GetGlobalService(SDTE) method. For the Com Exception, I am not able to diagnose your issue, for I don't know what do you write in your code. would you mind provide more details code here? Thanks Chao
| | Chao Kuo Wednesday, October 07, 2009 10:20 AM | Hello again
Just like You said: GetService() doesn't work, so I used:
public EnvDTE.DTE dte = PMLProjectPackage.GetGlobalService(typeof(SDTE)) as EnvDTE.DTE;
and, inside constructor:
dte.Events.SolutionItemsEvents.ItemRenamed += new EnvDTE._dispProjectItemsEvents_ItemRenamedEventHandler(SolutionItemsEvents_ItemRenamed);
Appropriate method does nothing (for now). But, unfortunately - it doesn't work again. I don't see how's that. On start dte is set, the same as event. I can see that during debugging. But when project is loaded, and I try to change name of file inside it, nothing happens. I set breakpoint in the method ItemRenamed, and it is never touched.
I don't know how it works. For me, it should be ok now, but event isn't fired or I can't catch it. Maybe You know what's going on?
About COM Exception, I'd like to provide more necessary details, but I don't know what do You want to know. In my LanguageService there is class:
public abstract class BabelLanguageService : Microsoft.VisualStudio.Package.LanguageService{
public override Microsoft.VisualStudio.Package.AuthoringScope ParseSource(ParseRequest req){ Source source = (Source)this.GetSource(req.FileName); (......REST OF THE CODE) } }
When I try to invoke source.SetText("example"), or other overloading of this method, COM exception is thrown: A null reference pointer was passed to the stub. (Exception from HRESULT: 0x800706F4)
I'd like to change text in this source for purposes of parsing and merging code. This metod would be perfect (I think that becouse description on MSDN claims that :) ), but I cannot use it.
Thank You again for help Best regards Paul
| | PaulTheMe Wednesday, October 07, 2009 1:41 PM | Hi Paul, The problem is that you are attempting to retrieve the DTE automation service before your package is properly sited. Additionally, it's entirely possible for your package to be sited before the DTE service is available. The following blog article details why this occurs and how to avoid it. Dr. eX: Why does GetService(typeof(EnvDTE.DTE)) return NULL?However, I believe the automation event is probably not the proper way to go about doing this. When a file is renamed, the DocData object associated with the project item gets a call to IVsPersistDocData.RenameDocData call. I suspect there are some other hooks like IVsRunningDocTableEvents. I need to do a little digging to find the right way to do this. I'll try to look this up and post back on this thread. Sincerely,
Ed Dore | | Ed Dore Friday, October 09, 2009 4:53 AM | Ed,
Thank You for your concern, I really approciate this, and I'm waiting with anxiety for Your next post. Additionally I'm reading blog You mentioned about :), there is so many things about VS that I feel dizzy... Best regards, Paul. | | PaulTheMe Friday, October 09, 2009 5:20 AM | Hi Paul,
I did a quick check of the rename feature as implemented by C#. When the user attempts to rename a file via the solution explorer, the underlying project hierarchy's implementation of IVsUIHierarchy::SetProperty is invoked to set the VSHPROPID_EditLabel. When this in called the underlying project system renames the file and then uses the underlying CodeElement2::RenameSymbol to refactor the base class name.
If your project type is based on the MPF_Proj sources, I suspect you could add the refactoring capability at the end of the internal RenameDocument method on the FileNode class. That would probably be a logical place to start.
Sincerely, Ed Dore- Marked As Answer byChao KuoMSFT, ModeratorTuesday, October 13, 2009 6:07 AM
- Proposed As Answer byEd DoreMSFT, ModeratorMonday, October 12, 2009 9:03 PM
-
| | Ed Dore Monday, October 12, 2009 9:03 PM | Hi again
Thank you Ed for yor time. You helped me a lot - I solved the problem with FileNode class, just like you said :) I mean - problem with renaming event. Problem with Source object still exists...
Right now I know when user renames file. So I'd like to change text in this file in order to changes in file name. Source object contains text from the file, so I'd like to change this text with method SetText(), but it returns exception, just like I explained above. BUT: maybe this is not a problem for me and there is other way to change text in renamed file?
I would create textreader/writer and change file outside VS Shell, but then annoying window with information about this pops up. This isn't proper way. So maybe something else? I have almost no experience in such projects, so forgive me if I ask about basics...
Best regards Paul | | PaulTheMe Wednesday, October 14, 2009 7:14 AM |
|