Get assemblyname of a project - c#

What I need
I want to obtain the assembly name of a Project in an Visual Studio Extension.
Since I know that you can see it when right clicking on a Project in the Solution Explorer and select Properties. It will show the Assemblyname in the tab Application.
Setup
I have a "Command" in my extension project which shows when you right click something in the solution explorer. As soon as someone clicks the command the following code will execute:
var dte = await GetDTE2Async();
await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
var selectedItem = GetSelectedItem(dte);
var props = selectedItem.ContainingProject.Properties;
//I just assumed that the `AssemblyName` could be somewhere in the `Properties` Property.
Where the GetSelectedItem method looks like this:
public static ProjectItem GetSelectedItem(DTE2 dte)
{
ThreadHelper.ThrowIfNotOnUIThread();
var items = (Array)dte.ToolWindows.SolutionExplorer.SelectedItems;
return items.Cast<UIHierarchyItem>().FirstOrDefault().Object as ProjectItem;
}

For anyone else who has the same issue, I actually was pretty close to my goal.
How I found it
It was just about guessing, in my case I assumed that the Properties is a bunch of Property items.
After that I just collected all the key pair values that the IEnumerable had. Then saw that there is acutally an Item called AssemblyName which indeed matches the correct value.
var items = selectedItem.ContainingProject.Properties.Cast<Property>()
var sb = new StringBuilder();
foreach (var item in items)
{
sb.Append($"Name : {item.Name} ");
try
{
sb.Append("Value : " + item.Value.ToString());
}
catch (Exception)
{
sb.Append("Value : NOT DEFINED (EXCEPTION)");
}
finally
{
sb.AppendLine();
}
}
var output = sb.ToString();
Solution
It is a fairly short part, but here we go:
var assemblyName = selectedItem.ContainingProject.Properties.Cast<Property>().FirstOrDefault(x=> x.Name == "AssemblyName").Value;
Basically I am just searching the first element which matches the name AssemblyName and get its value.

Maybe you can try:
System.Reflection.Assembly.GetAssembly(Property's Type).FullName

Related

MessageBox doesn't show Folder path when two keywords are searched, but it shows the folder path when one keyword is searched

try
{
string[] SetupFolderKeywords = {"Setup", "Installed"};
DirectoryInfo SearchedDirectory = new DirectoryInfo(Game.SelectedPath);
FileSystemInfo[] filesAndDirs = SearchedDirectory.GetFileSystemInfos($"*{SetupFolderKeywords[0]}*|*{SetupFolderKeywords[1]}*"); // <-- This doesn't work
// FileSystemInfo[] filesAndDirs = SearchedDirectory.GetFileSystemInfos("*" + SetupFolderKeywords[0] + "*"); <-- This Works
foreach (FileSystemInfo foundFile in filesAndDirs)
{
string FullName = foundFile.FullName;
MessageBox.Show(FullName);
}
}
catch (IOException ExpMoveFolder)
{
MessageBox.Show(Convert.ToString(ExpMoveFolder));
}
I'm trying to look for a folder that has either the keyword "Setup" or "Installed" inside the Game.SelectedPath directory. (I used a FolderBrowserDialog to select this folder) and make a MessageBox appear with its path.
When I try to search for a folder that matches one keyword, the MessageBox appears with the path of the folder. It works great, but when I try to search for keyword "Setup" or "Installed" MessageBox doesn't show at all.
No error messages or warnings appear in visual studio and no program exception occurs when I try to look for either one of the keywords instead of just one keyword.
You can't search for multiple patterns with a single call. Your attempt at a Boolean expression is just interpreted as a single pattern and, of course, there are no entries that match that pattern. If you want to match multiple patterns then you have to make multiple calls. One option might be like this:
var folder = new DirectoryInfo(Game.SelectedPath);
var entries = folder.EnumerateFileSystemInfos(patterns[0]);
for (var i = 1; i < patterns.Length; i++)
{
entries = entries.Concat(folder.EnumerateFileSystemInfos(patterns[i]));
}
foreach (var entry in entries)
{
// Use entry here.
}
EDIT:
I just created this folder:
I then executed this code:
var patterns = new[] { "123", "789" };
var folder = new DirectoryInfo(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "Test"));
var entries = folder.EnumerateFileSystemInfos($"*{patterns[0]}*");
for (var i = 1; i < patterns.Length; i++)
{
entries = entries.Concat(folder.EnumerateFileSystemInfos($"*{patterns[i]}*"));
}
foreach (var entry in entries)
{
Console.WriteLine(entry.Name);
}
That's basically exactly what I posted above except I added wildcards to the EnumerateFileSystemInfos calls where the original code would have required them to be in strings already. This is the output I got:
File123.txt
Folder123
File789.txt
Folder789
I then changed the filters to this:
var patterns = new[] { "456" };
and ran the code again and got this output:
File456.txt
Folder456
Clearly, the code works exactly as it is supposed to and, if what you did didn't work then you did it wrong. If you can't work out what you did wrong, I suggest that you update your question and add the new relevant information.

Unable to Print Anonymous type variable's values

I have iterated
foreach (var tmp_variable in all_subdirectories)
{
MessageBox.Show(tmp_variable["Name"]);
}
I want to print the Name inside tmp_variable .
In the Autos tab (While Debugging the variable value), the tmp_variable has the following values:
tmp_variable { Path = "D:\abc\folder1", Name = "folder1" }
But unable to use any of such things.
I have tried writing
MessageBox.Show(tmp_variable[Name]);
and,
MessageBox.Show(tmp_variable.Name);
But nothing works. Everything shows error.
I hope this helps.
var all_subdirectories = System.IO.Directory.GetDirectories(folderPath);
foreach (var tmp_variables in all_subdirectories)
{
// Get the directory name only from filepath
MessageBox.Show(System.IO.Path.GetFileName(tmp_variables));
}

replacing a variable text with other text in c#

I am using c# and sitecore to basically use tokens in certain places ( see: how to create a custom token in sitecore ). I think I have a solution, but am not sure as to why it is not working, even though I am getting no errors.
Item tokenItem = Sitecore.Context.Database.Items["/sitecore/content/Site Content/Tokens"];
if (tokenItem.HasChildren)
{
var sValue = args.FieldValue.ToString();
foreach (Item child in tokenItem.Children)
{
if (child.Template.Name == "Token")
{
string home = child.Fields["Title"].Value;
string hContent = child.Fields["Content"].Value;
if (sValue.Contains(home))
{
home.Replace(home, hContent);
}
}
}
}
home and hContent pull up the correct values of each container, but when the page loads, it still has the "home" value inputted (the ie: ##sales) in the content area instead of the new value, which is stored in hContent. The sValue contains everything (tables, divs, text) and I was trying to single out a value that equals to "home" and replace the "home" value with hContent. What am I missing?
If your code is implemented as a processor for the RenderField pipeline, you need to put the result of your work back into args. Try something like this:
Item tokenItem = Sitecore.Context.Database.Items["/sitecore/content/Site Content/Tokens"];
if (tokenItem.HasChildren)
{
var sValue = args.Result.FirstPart;
foreach (Item child in tokenItem.Children){
if (child.Template.Name == "Token") {
string home = child.Fields["Title"].Value;
string hContent = child.Fields["Content"].Value;
if (sValue.Contains(home)) {
sValue = sValue.Replace(home, hContent);
}
}
}
args.Result.FirstPart = sValue;
}
Note that you need to be sure to patch this processor into the pipeline after the GetFieldValue processor. That processor is responsible for pulling the field value into args.Result.FirstPart.
You code isn't really doing anything. You seem to be replacing the tokens on the token item field itself (child.Fields["Title"] and child.Fields["Content"]), not on the output content stream.
Try the following, you need to set the args to the replaced value, replacing both the FirstPart and LastPart properties: Replace Tokens in Rich Text Fields Using the Sitecore ASP.NET CMS (link to the code in the "untested prototype" link).
I would refactor your code to make it easier:
public void Process(RenderFieldArgs args)
{
args.Result.FirstPart = this.Replace(args.Result.FirstPart);
args.Result.LastPart = this.Replace(args.Result.LastPart);
}
protected string Replace(string input)
{
Item tokenItem = Sitecore.Context.Database.Items["/sitecore/content/Site Content/Tokens"];
if (tokenItem.HasChildren)
{
foreach (Item child in tokenItem.Children)
{
if (child.Template.Name == "Token")
{
string home = child.Fields["Title"].Value;
string hContent = child.Fields["Content"].Value;
if (input.Contains(home))
{
return input.Replace(home, hContent);
}
}
}
}
return input;
}
This is still not optimal, but gets you closer.
Well, Do you know what happens when you performs home.Replace(home, hContent);, it will create a new instance by replacing the content of the come with what is in hContent so what you need to do is, assign this instance to a new variable or to home itself. hence the snippet will be like the following:
if (sValue.Contains(home))
{
home = home.Replace(home, hContent);
}
Have you tried:
home = home.Replace(home,hContent);

Resharper - Go To Implementation listing reference twice

In one of my solutions, when I right click a symbol and choose "Go To Implementation" for an object defined in one of the other solution projects, it lists the reference twice and forces me to choose one.
Based on the icons, it appears that one of the items in the list represents the project, and the other represents a dll. It doesn't matter which one I click - it goes to the same source file.
I only have the library reference once in this particular project - it is referencing the project.
What would cause this to happen? Some sort of circular reference issue perhaps?
As far as I can tell, this can also happen if you have a solution with several projects, where a certain project is referenced as project and also as pure file by two other projects in the solution.
Another advice that I can give if something is broken with ReSharper, is to clear the cache.
I had this problem and I just fixed it.
First, try do a Clean Solution and then a Build.
In my case, one rogue Project in my solution was compiled using an older version of the .NET framework than the other Projects, so when Resharper added a reference to my other Projects for me, it must have added it as a dll reference instead of as a Project reference.
My fix was
Upgrade old Project to the same version of .NET framework as the other Projects
Remove references to other Projects from that old Project
Add references to the other Projects again (as Project references this time)
Clean solution
Build solution
Done.
I've found a couple different cases that cause this problem, and got so annoyed that I wrote a little console app to scan my solution and find the problems for me. Here it is for anyone who might find this useful. To run it pass it the path to your solution folder and it will print out the issues on the console. It's very "quick and dirty" but it found the issues for me.
class Program
{
static void Main(string[] args)
{
if (args != null && args.Any())
{
foreach (var s in args)
{
Console.WriteLine("Checking " + s);
DirectoryInfo dir = new DirectoryInfo(s);
var files = dir.GetFiles("*.csproj", SearchOption.AllDirectories);
var projects = files.Select(x => new Project(x)).ToList();
var grouped = projects.GroupBy(x => x.TargetFrameworkVersion);
if(grouped.Count()>1)
{
Console.WriteLine("Solution contains multiple versions of Target Frameworks, this may cause duplicate assemblies in R# cache");
foreach (var group in grouped)
{
Console.WriteLine(group.Key);
foreach (var project in group)
{
Console.WriteLine(project.AssemblyName);
}
}
}
//loop through for debugging
foreach (var project in projects)
{
foreach (var reference in project.References)
{
foreach (var checkProject in projects)
{
if (checkProject.AssemblyName == reference)
{
Console.WriteLine("Reference in" + project.FileName + " referencing " +
reference+" that should be a ProjectReference, this may cause duplicate entries in R# Cache");
}
}
}
}
}
Console.WriteLine("Complete");
Console.ReadLine();
}
else
{
Console.WriteLine("You must provide a path to scan for csproj files");
}
}
}
public class Project
{
public string FileName { get; set; }
public string AssemblyName { get; set; }
public string ProjectGuid { get; set; }
public string TargetFrameworkVersion { get; set; }
public IList<string> References { get; set; }
private FileInfo _file;
private XmlDocument _document;
private XmlNamespaceManager _namespaceManager;
public Project(FileInfo file)
{
_file = file;
FileName = _file.FullName;
_document = new XmlDocument();
_document.Load(_file.FullName);
_namespaceManager = new XmlNamespaceManager(_document.NameTable);
_namespaceManager.AddNamespace("msbld", "http://schemas.microsoft.com/developer/msbuild/2003");
var projectGuidNode = _document.SelectSingleNode("//msbld:ProjectGuid", _namespaceManager);
ProjectGuid = projectGuidNode.InnerText;
var assemblyNameNode = _document.SelectSingleNode("//msbld:AssemblyName", _namespaceManager);
AssemblyName = assemblyNameNode.InnerText;
var targetFrameworkNode = _document.SelectSingleNode("//msbld:TargetFrameworkVersion", _namespaceManager);
TargetFrameworkVersion = targetFrameworkNode.InnerText;
References = new List<string>();
var referenceNodes = _document.SelectNodes("//msbld:Reference", _namespaceManager);
foreach (var node in referenceNodes)
{
var element = (XmlElement) node;
//file references
if (element.HasChildNodes)
{
foreach (var child in element.ChildNodes)
{
var childElement = (XmlElement)child;
if (childElement.Name == "HintPath")
{
var value = childElement.InnerText;
value = value.Substring(value.LastIndexOf("\\") + 1);
value = value.Replace(".dll", "");
References.Add(value);
}
}
}
//gac references
else
{
foreach (var attr in element.Attributes)
{
var attribute = (XmlAttribute)attr;
if (attribute.Name == "Include")
{
var value = attribute.Value;
string reference = value;
if (value.Contains(','))
{
reference = value.Substring(0, value.IndexOf(','));
}
References.Add(reference);
break;
}
}
}
}
}
}

IEnumerable not enumerating in foreach

I'm encountering a problem with one of my IEnumerable's that I haven't seen before.
I have a collection:
IEnumerable<IDependency> dependencies;
that's being used in a foreach loop.
foreach (var dependency in dependencies)
For some reason this foreach doesn't iterate over my IEnumerable and simply skips to the end.
If I change my foreach to loop through a a list however it seems to work fine:
foreach (var dependency in dependencies.ToList())
What could I be doing that's causing this behaviour? I haven't experienced this with IEnumerable before.
Update:
Here's the entire code of my foreach that's running in my method GenerateDotString:
foreach (var dependency in dependencies)
{
var dependentResource = dependency.Resource;
var lineColor = (dependency.Type == DependencyTypeEnum.DependencyType.Hard) ? "blue" : "red";
output += labelFormat.FormatWith(dependentResource.Name.MakeDotsafeString(), dependentResource.Name, dependentResource.ResourceType);
output += relationshipFormat.FormatWith(dependentResource.Name.MakeDotsafeString(), currentName, lineColor);
if (dependentResource.DependentResources != null)
{
output += GenerateDotString(dependentResource, dependentResource.DependentResources, searchDirection);
}
}
return output;
Update 2:
Here's the signature of the method containing this foreach (incase it helps).
private static string GenerateDotString(IResource resource, IEnumerable<IDependency> dependencies, SearchEnums.SearchDirection searchDirection)
Update 3:
Here's the method GetAllRelatedResourcesByParentGuidWithoutCacheCheck:
private IEnumerable<IDependency> GetAllRelatedResourcesByParentGuidWithoutCacheCheck(Guid parentCiGuid, Func<Guid, IEnumerable<IDependency>> getResources)
{
if (!_itemsCheckedForRelations.Contains(parentCiGuid)) // Have we already got related resources for this CI?;
{
var relatedResources = getResources(parentCiGuid);
_itemsCheckedForRelations.Add(parentCiGuid);
if (relatedResources.Count() > 0)
{
foreach (var relatedResource in relatedResources)
{
relatedResource.Resource.DependentResources = GetAllRelatedResourcesByParentGuidWithoutCacheCheck(relatedResource.Resource.Id, getResources);
yield return relatedResource;
}
}
}
}
Update 4:
I'm adding the methods in the chain here to be clear on how we're getting the collection of dependencies.
The above method GetAllRelatedResourcesByParentGuidWithoutCacheCheck accepts a delegate which in this case is:
private IEnumerable<IDependency> GetAllSupportsResources(Guid resourceId)
{
var hardDependents = GetSupportsHardByParentGuid(resourceId);
var softDependents = GetSupportsSoftByParentGuid(resourceId);
var allresources = hardDependents.Union(softDependents);
return allresources;
}
which is calling:
private IEnumerable<IDependency> GetSupportsHardByParentGuid(Guid parentCiGuid)
{
XmlNode ciXmlNode = _reportManagementService.RunReportWithParameters(Res.SupportsHardReportGuid, Res.DependentCiReportCiParamName + "=" + parentCiGuid);
return GetResourcesFromXmlNode(ciXmlNode, DependencyTypeEnum.DependencyType.Hard);
}
and returns:
private IEnumerable<IDependency> GetResourcesFromXmlNode(XmlNode ciXmlNode, DependencyTypeEnum.DependencyType dependencyType)
{
var allResources = GetAllResources();
foreach (var nodeItem in ciXmlNode.SelectNodes(Res.WebServiceXmlRootNode).Cast<XmlNode>())
{
Guid resourceGuid;
var isValidGuid = Guid.TryParse(nodeItem.SelectSingleNode("ResourceGuid").InnerText, out resourceGuid);
var copyOfResource = allResources.Where(m => m.Id == resourceGuid).SingleOrDefault();
if (isValidGuid && copyOfResource != null)
{
yield return new Dependency
{
Resource = copyOfResource,
Type = dependencyType
};
}
}
}
which is where the concrete type is returned.
So it looks like the problem was to do with the dependencies collection infinately depending on itself.
It seems from my debugging that iterating the IEnumerable causes a timeout and so the foreach simply skips execution of its contents where as ToList() returns as much as it can before timing out.
I may not be correct about that but it's what seems to be the case as far as I can tell.
To give a bit of background as to how this all came about I'll explain the code changes I made yesterday.
The first thing the application does is build up a collection of all resources which are filtered by resource type. These are being brought in from our CMDB via a web service call.
What I was then doing is for each resource that was selected (via autocomplete in this case) I'd make a web service call and get the dependents for the resource based on its Guid. (recursively)
I changed this yesterday so that we didn't need to obtain the full resource information in this second web service call, rather, simply obtain a list of Guids in the web service call and grab the resources from our resources collection.
What I forgot was that the web service call for dependents wasn't filtered by type and so it was returning results that didn't exist in the original resources collection.
I need to look a bit further but it seems that at this point, the new collection of dependent resources was becoming dependent on itself and thus, causing the IEnumerable<IDependents> collection later on to timeout.
This is where I've got to today, if I find anything else I'll be sure to note it here.
To summarise this:
If infinite recursion occurs in an IEnumerable it'll simply timeout
when attempting to enumerate in a foreach.
Using ToList() on the IEnumerable seems to return as much data as it
can before timing out.

Categories

Resources