Getting the selected file and using IVsSingleFileGenerator - c#

I am trying to add several new functions to a package I developed for our company. One of these functions is to create a new file based on the file selected in the solution explorer and the menu option selected. I have created my dynamic menu items that are on the solution explorer and it looks like I need to use IVsSingleFileGenerator as shown in this sample.
The trouble I am having is getting the file I have selected and either reading it or passing it into a single file generator.
I would rather generate the file from this context menu than from a custom tool action
Looks like this will get me the path of the file
UIHierarchy solutionExplorer = _applicationObject.ToolWindows.SolutionExplorer;
var items = solutionExplorer.SelectedItems as Array;
if (items == null || items.Length != 2)
{
return;
}
String strFile1 = String.Empty;
UIHierarchyItem item1 = items.GetValue(0) as UIHierarchyItem;
foreach (UIHierarchyItem hierarchyItem in items)
{
ProjectItem prjItem = hierarchyItem.Object as ProjectItem;
string prjPath = prjItem.Properties.Item("FullPath").Value.ToString();
}
which I can then use to pass into the generate function of the ivs single file generator.
Is this the best approach?

I also posted this question to the msdn forums at:
VSX getting the selected file and using IVsSingleFileGenerator
I ended up using the IPyIntegration sample to figure out what i needed to do.

Related

Sharepoint 2010 Programmatically Update List Item in Event Handler

Background
We have a custom developed installed .WSP on a SharePoint 2007 environment and have been in the process of upgrading to 2010. With the upgrade the custom event trigger no longer worked so trying to update and make it work in 2010. But I am running into one issue. Original developers no longer here and I've been the lucky one to have to figure this one out without much of a background with SP Dev.
Goal
When a new list item is created trigger event. Within event, create a shared folder using Item Name and return url, create a wiki-page using item name and include shared document link and return url to wiki page. Part three is update newly created list item with the New Folder url and Wiki Page URL.
Issue
I've gotten the first two parts working but so far have been unable to update the newly created list item with the new Links. I'm able to get the links. I've tried all the basic stuff for updating the list that I have been able to find online with no luck. Nothing to complicated(or so I think). But code is included below. VS is not installed on the server so unable to run debug mode, I don't have direct access to the server. When you create the item there are no client/user side error. Haven't been able to find a log file that has any, that is if it collects errors if the script were to fail out.
Initiation of the Event
public class CreateWikiAndFolder : Microsoft.SharePoint.SPItemEventReceiver
{
public override void ItemAdded(SPItemEventProperties properties)
{
try
{
//this.DisableEventFiring();
base.EventFiringEnabled = false;
string sUrlOfWikiPage = string.Empty;
string sUrlOfNewFolder = string.Empty;
string sSubsiteRUL = string.Empty;
string sCurrentItemTitle = properties.ListItem["Title"].ToString();
string sWikiListName = "TR Wikis";
string sDocLibName = "Shared Documents";
string sTRListID = "TR Status";
if (sTRListID.ToUpper().Equals(properties.ListTitle.ToString().ToUpper()))
{
//Create the Folder
sUrlOfNewFolder = CreateFolder(properties.ListItem.Web, sDocLibName, sCurrentItemTitle);
//Create the Wiki
string ItemDispFormUrl = String.Concat(properties.ListItem.Web.Url, "/", properties.ListItem.ParentList.Forms[PAGETYPE.PAGE_DISPLAYFORM].Url, "?ID=", properties.ListItem.ID.ToString());
sUrlOfWikiPage = CreateWiki(properties.ListItem.Web, sWikiListName, sCurrentItemTitle, ItemDispFormUrl, sUrlOfNewFolder);
//Update the current TR Item
//Have tried. properties.ListItem["WikiURL"] = sUrlOfWikiPage + ", " + "Wiki";
SPListItem myListItem = properties.ListItem;
SPFieldUrlValue shareFolderURLValue = new SPFieldUrlValue();
shareFolderURLValue.Description = "Shared Folder";
shareFolderURLValue.Url = sUrlOfNewFolder ;
myListItem["SharedFolder"] = shareFolderURLValue;
//I've tried each one separate and together to no luck
myListItem.UpdateOverwriteVersion();
myListItem.Update();
//properties.ListItem.UpdateOverwriteVersion();
}
base.EventFiringEnabled = true;
}
}
}
Note that this is the last thing needed to be figured out for our upgrade.
Got it working. I did both of these at the same time so I'm not sure if it was the combination of both or only one of the items. But one I removed the myListItem.UpdateOverwriteVersion(); line and surrounded the item updated with web.AllowUnsafeUpdates being set to true before and then back to false afterwards.
Also as a note to others, you need to save the properties.ListItem to its own SPListItem which you then update versus trying to manipulate the values at the properties.ListItem["Attribute"], and then update the properties.ListItem.Update. SharePoint doesn't allow the latter option so you have to save to an independent SPListItem, and then modify and update that one. This might not be the best SharePoint lingo, but that is what needs to be done.

Auto formatting a t4 created file

I'm currently creating many files using t4 templates in vs2015.
My code comes out all misaligned (it's worst in other spot of the generated code)
example -
public bool Add()
{
var returnValue = false;
using (var context = new ApmEntities())
{
context.Entry(this).State = EntityState.Added;
foreach (var item in this.MissionCriticalities)
{
context.Entry(item).State = EntityState.Modified;
}
var number = context.SaveChanges();
returnValue = number > 0;
}
return returnValue;
}
Is there a way to automatically run formatting (similar to doing Ctrl - K - D) on the file?
I'm creating the file with
fileManager.StartNewFile(entity.Name + "DbExtra" + ".cs");
and at the end of the file doing a
fileManager.Process();
(Similar to the t4 that generates objects when using database first entity framework)
Thanks
You can format it with "\t" or "\n" or normale spaces directly in your file creation. It depends on how your "CreationFile" looks like and how this is formated.
I don't think that you can format that in another way per code, because with your t4 script you will say how the file should look like.
But what you also can try is:
Use the CodeCleanup From Resharper, if you have, and write a macro which will save every "Save" action of a file:
How can I configure ReSharper's code cleanup on save?
I use that and its very great. Its formated the different files in that way which I want, sorted properties, usings and much more.
Try it :-)

Very basic usage of sitecore search

I am trying to setup a very basic search index, to index all items in a specific folder. I haven't really used much searching, but I'm trying to use out-of-the-box features, because its a very simple search. I just want to index all the fields. The sitecore documentation really doesn't provide much information - I've read a few blogs, and they all seem to suggest that I need the advanced database crawler (http://trac.sitecore.net/AdvancedDatabaseCrawler) - basically, something to the effect of 'it won't work without a custom crawler).
Is this right? I just want to create a simple index, and then start using it. What is the simplest way to do this, without any shared modules or otherwise? I went through the documentation on sitecore, but its not very clear (at least to me). It defines different elements of the index configuration in web.config, but doesn't really explain what they do, and what values are available. Maybe I'm not looking in the right place..
A simple way of creating new Lucene index in Sitecore with all the items below the specific node in just 3 steps:
1: Add the configuration below to the configuration/sitecore/search/configuration/indexes in Sitecore configuration:
<!-- id must be unique -->
<index id="my-custom-index" type="Sitecore.Search.Index, Sitecore.Kernel">
<!-- name - not sure if necessary but use id and forget about it -->
<param desc="name">$(id)</param>
<!-- folder - name of directory on the hard drive -->
<param desc="folder">__my-custom-index</param>
<!-- analyzer - reference to analyzer defined in Sitecore.config -->
<Analyzer ref="search/analyzer" />
<!-- list of locations to index - each of the with unique xml tag -->
<locations hint="list:AddCrawler">
<!-- first location (and the only one in this case) - specific folder from you question -->
<!-- type attribute is the crawler type - use default one in this scenario -->
<specificfolder type="Sitecore.Search.Crawlers.DatabaseCrawler,Sitecore.Kernel">
<!-- indexing itmes from master database -->
<Database>master</Database>
<!-- your folder path -->
<Root>/sitecore/content/home/my/specific/folder</Root>
</specificfolder>
</locations>
</index>
2: Rebuild the new index (only one time, all further changes will be detected automatically):
SearchManager.GetIndex("my-custom-index").Rebuild();
3: Use the new index:
// use id of from the index configuration
using (IndexSearchContext indexSearchContext = SearchManager.GetIndex("my-custom-index").CreateSearchContext())
{
// MatchAllDocsQuery will return everything. Use proper query from the link below
SearchHits hits = indexSearchContext.Search(new MatchAllDocsQuery(), int.MaxValue);
// Get Sitecore items from the results of the query
List<Item> items = hits.FetchResults(0, int.MaxValue).Select(result => result.GetObject<Item>()).Where(item => item != null).ToList();
}
Here is a pdf describing Sitecore Search and Indexing.
And here is a blog post about Troubleshooting Sitecore Lucene search and indexing.
Here is Lucene query syntax tutorial
and Introducing Lucene.Net
Sitecore Search Contrib (new name for advanced database crawler) is the best option, you just configure its config in the app config folder to tell it start path database etc.
You can then use its API to search within folders, by template type, where a certain field has a certain value. Here is a code example.
MultiFieldSearchParam parameters = new MultiFieldSearchParam();
parameters.Database = "web";
parameters.InnerCondition = QueryOccurance.Should;
parameters.FullTextQuery = searchTerm;
parameters.TemplateIds = array of pipe seperated ID's
var refinements = Filters.Select(item => new MultiFieldSearchParam.Refinement(item.Value, item.Key.ToString())).ToList();
parameters.Refinements = refinements;
//The actual Search
var returnItems = new List<Item>();
var runner = new QueryRunner(IndexName);
var skinnyItems = runner.GetItems(new[] {parameters});
skinnyItems.ForEach(x => returnItems.Add(Database.GetItem(new ItemUri(x.ItemID))));
return returnItems;
Otherwise you can just configure the web.config for standard lucene search and use this code to search. (Data base to use "web", start item etc)
public Item[] Search(string searchterms)
{
var children = new List<Item>();
var searchIndx = SearchManager.GetIndex(IndexName);
using (var searchContext = searchIndx.CreateSearchContext())
{
var ftQuery = new FullTextQuery(searchterms);
var hits = searchContext.Search(ftQuery);
var results = hits.FetchResults(0, hits.Length);
foreach (SearchResult result in results)
{
if (result.GetObject<Item>() != null)
{
//Regular sitecore item returned
var resultItem = result.GetObject<Item>();
if (ParentItem == null)
{
children.Add(resultItem);
}
else if (resultItem.Publishing.IsPublishable(DateTime.Now, false) &&
ItemUtilities.IsDecendantOfItem(ParentItem, resultItem))
{
children.Add(resultItem);
}
}
}
}
return children.ToArray();
}
Then you can download Lucene Index Viewer extension for Sitecore to view the index or you can download the Lucene Tool to view the indexes. See if you can populate the documents (files in your indexes). These are called 'Documents' in Lucene and technically these documents are content item present under the node that you specified.
Brian Pedersen has a nice post on it. You would start with a simple crawler. Need to download the Advanced Database Crawler and add the reference to your project after building it.
Then you have to create the config files which is mentioned in Brian's Blog and you have to copy as it is (except for the template id's n all). You get the point basically here.
Then you can download Lucene Index Viewer extension for Sitecore to view the index or you can download the Lucene Tool to view the indexes. See if you can populate the documents (files in your indexes). These are called 'Documents' in Lucene and technically these documents are content item present under the node that you specified.
Hope this helps!
Let me google that for you.

Adding File under label header or source Visual Studio add-in

With Following code I am able to add new files to visual studio project.
DTE dte = GetService(typeof(DTE)) as DTE;
System.Array theProjects = (System.Array)dte.ActiveSolutionProjects;
EnvDTE.Project theProject = null;
if (theProjects.Length > 0)
{
theProject = (EnvDTE.Project)(theProjects.GetValue(0));
EnvDTE.ProjectItem projItem = null;
projItem = theProject.ProjectItems.AddFromFile(#"E:\Avinash\test.cpp");
}
But if i have to add a header file, how do i add it under header label.
If I correctly understand what you are trying to do, I think you mean that you want to add your header files in the header folder. If it's already there you have to look for it among the items for your project. I.e. you have to loop looking for the ProjectItem with the name you are looking for. If it's not already there, you can add it using the AddFolder of ProjectItemsCollection, which returns the newly created ProjectItem. In either case you end up with a ProjectItem representing the headers folder. Now you can add your file to the ProjectItems of this object instead of the ProjectItems of the Project. Something like this:
theProject = (EnvDTE.Project)(theProjects.GetValue(0));
EnvDTE.ProjectItem projItem = null;
EnvDTE.ProjectItem hdrProjItem = theProject.ProjectItems.AddFolder("Header files", null);
projItem = hdrProjItem.ProjectItems.AddFromFile(#"E:\Avinash\test.cpp");
Anyway, I still think a template could avoid you much effort and pain

How do I find and open a file in a Visual Studio 2005 add-in?

I'm making an add-in with Visual Studio 2005 C# to help easily toggle between source and header files, as well as script files that all follow a similar naming structure. However, the directory structure has all of the files in different places, even though they are all in the same project.
I've got almost all the pieces in place, but I can't figure out how to find and open a file in the solution based only on the file name alone. So I know I'm coming from, say, c:\code\project\subproject\src\blah.cpp, and I want to open c:\code\project\subproject\inc\blah.h, but I don't necessarily know where blah.h is. I could hardcode different directory paths but then the utility isn't generic enough to be robust.
The solution has multiple projects, which seems to be a bit of a pain as well. I'm thinking at this point that I'll have to iterate through every project, and iterate through every project item, to see if the particular file is there, and then get a proper reference to it.
But it seems to me there must be an easier way of doing this.
To work generically for any user's file structure, you'll need to enumerate all the files in all the projects. This should get you started. And, well, pretty much finished :-)
internal static string GetSourceOrInclude(bool openAndActivate)
{
// Look in the project for a file of the same name with the opposing extension
ProjectItem thisItem = Commands.Application.ActiveDocument.ProjectItem;
string ext = Path.GetExtension(thisItem.Name);
string searchExt = string.Empty;
if (ext == ".cpp" || ext == ".c")
searchExt = ".h";
else if (ext == ".h" || ext == ".hpp")
searchExt = ".cpp";
else
return(string.Empty);
string searchItemName = thisItem.Name;
searchItemName = Path.ChangeExtension(searchItemName, searchExt);
Project proj = thisItem.ContainingProject;
foreach(ProjectItem item in proj.ProjectItems)
{
ProjectItem foundItem = FindChildProjectItem(item, searchItemName);
if (foundItem != null)
{
if (openAndActivate)
{
if (!foundItem.get_IsOpen(Constants.vsViewKindCode))
{
Window w = foundItem.Open(Constants.vsViewKindCode);
w.Visible = true;
w.Activate();
}
else
{
foundItem.Document.Activate();
}
}
return(foundItem.Document.FullName);
}
return(string.Empty);
}
Note that it is possible for a header to be in the include path without being added to the project, so if the above fails, you could potentially look in the include paths for the containing project too. I'll leave that as an exercise for the reader.

Categories

Resources