Is it possible to relate/link to other project files within the comments of the source code (C# in this case) in Visual Studio?
I've found you can use file:// hyperlinks, but those need an absolute path (plus they won't open in the code editor)... there's also <see cref>, which works with R#, but that relates to a symbol that must be referenced by the current project, so that doesn't work in my case.
For my specific case, I'd like to somehow relate Entity Framework's entity POCOs to their mapping configuration class (which resides in other project file which is not referenced by the project where the POCOs are defined).
Absolute paths won't work since this project is being worked on several computers with different absolute paths.
There's also HyperAddin but doesn't seem to have been updated since VS 2008, I'm using 2015.
Any ideas, or add-ins you might have used?
You can automate it with Visual Commander. The simplest command (C#) that requires you to select the relative configuration class file path in the editor (like Project1\config.xml) before calling it:
EnvDTE.TextSelection ts = DTE.ActiveDocument.Selection as EnvDTE.TextSelection;
string relativePath = ts.Text;
string absolutePath = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(DTE.Solution.FileName), relativePath);
DTE.ItemOperations.OpenFile(absolutePath, null);
Related
We’re using Xunit for testing. We’re running our tests via the built-in Visual Studio 2013 Test Runner, using the Xunit plugin.
The issue is that some of the tests need to refer to files on the filesystem. It seems that Xunit (or the VS Test Runner—not sure which), copies the assembles, but not any supporting files in the bin directory, to another directory before executing the tests, hence our test files are not found. [The MS Testing framework specifies attributes for listing files to be copied, but Xunit does not.]
How to either disable this copying behaviour, or else programmatically determine the original bin/ directory location to fetch the files?
It seems that most proposed solutions (including on the Xunit bug-tracker site) suggest storing the files as embedded resources instead of ‘copy always’ files. However, this is not always practical, for example: testing file manipulation code, and (in one case) code which wants a Sqlite database file.
Okay, typical, just as soon as I post the question, I find the answer myself…
The gist is that the copying (Shadow Copying) of assemblies seems to be done by the .NET framework, not by Visual Studio or by Xunit.
We had been using Assembly.Location to locate the assembly file, and hence the test files. However, this was wrong, since it gave us the location of the Shadow-Copied assembles instead of the originals.
Instead you should use Assembly.CodeBase to fetch the base assembly code location. However, this is a (File) URL, so it’s necessary to extract the path from the URL. The new (C#) code looks like this:
var codeBaseUrl = new Uri(Assembly.GetExecutingAssembly().CodeBase);
var codeBasePath = Uri.UnescapeDataString(codeBaseUrl.AbsolutePath);
var dirPath = Path.GetDirectoryName(codeBasePath);
return Path.Combine(dirPath, relativePath);
…where relativePath is the path relative to the Bin\ directory.
After a bit of search I found the solution here: https://msdn.microsoft.com/en-us/library/ms182475.aspx.
Particularly, the first step has been enough for me:
If they are specific to one test project, include them as content files in the Visual Studio test project. Select them in Solution Explorer and set the Copy to Output property to Copy if Newer.
associated to the following code:
var filename = "./Resources/fake.pdf"
File.OpenRead(filename)
As of .NET5 (perhaps earlier), CodeBase no longer works, so the solution is now to copy all of your files to the bin directory first and use this as your known location.
What makes this OK now, which was always a total pain in the past, is that you can copy a directory to your bin folder easily from your csproj file.
<ItemGroup>
<None
Include="TestFiles\**"
CopyToOutputDirectory="PreserveNewest"
LinkBase="TestFiles\" />
</ItemGroup>
Where TestFiles is in the root of your project folder. Now you can access these files with the following helper method.
public static class TestUtils
{
public static string GetTestPath(string relativePath)
{
var codeBaseUrl = new Uri(Assembly.GetExecutingAssembly().Location);
var codeBasePath = Uri.UnescapeDataString(codeBaseUrl.AbsolutePath);
var dirPath = Path.GetDirectoryName(codeBasePath);
return Path.Combine(dirPath, "TestFiles", relativePath);
}
}
I am running .Net Core 1.0 on Mac. Assembly.GetExecutingAssembly is unavailable. I use the following code instead:
var location = typeof(YourClassName).GetTypeInfo().Assembly.Location;
var dirPath = Path.GetDirectoryName(location);
return Path.Combine(dirPath, relativePath);
relativePath is the path relative to the directory of your DLL.
After struggling with trying to identify directories and copy files (there seem to be multiple directories in play and it's hard to pin down the right one), I found that you can just turn off shadow copying; at that point the unit tests reference content in the bin/{configuration} folder again.
To do so, follow the directions here. It seems to be as simple as setting shadowCopy to false:
{
"shadowCopy": false
}
I'm unclear whether this setting has any adverse interactions with other settings (e.g. appDomain). If anyone knows, your comments would be welcome.
Specifically, I've installed the extensions:
EF 4.x DbContext Generator for C#
EF 4.x DbContext Generator for C# Web Sites
I am trying to find the location these were installed, because I would like to modify them for my own needs.
I have looked in the following locations:
[UserDir]\Documents\Visual Studio 2010\My Exported Templates
[VSDir]\Common7\IDE\ItemTemplates\CSharp\Code\1033
But they are not in either location.
More Background
What I have done is modify the T4 template that generates the POCO's to pull info about the Max Length of text fields, have it generate a constructor for all objects (the default only generates an explicit constructor if there are complex types/relations that need to be instantiated), and add a partial method call to the Constructor for further initialization in a partial class.
The code that I have added is going to be needed in basically every project I do, so I would like to have my own code generation template for my POCO's, instead of having to modify the default one each time.
So, I'm looking for where those templates are so I can modify them, to create new ones with my changes inserted.
MSDN:
During installation, Extension Manager uncompresses the .vsix file and puts its contents in %LocalAppData%\Microsoft\VisualStudio\10.0\Extensions\Company\Product\Version. Company, Product, and Version are specified in the extension.vsixmanifest file, and correspond to the namespace, project name, and version number that are set in the project properties.
But strange, I also cannot find. I tried to install DbContextCSharp.vsix and find the content file (CSharpDbContext.Context.tt) of the installer. [You can unzip the installer by changing vsix to zip extension]
One thing I can suggest is, unzip the installer > update with your logic > change the extension back > re-install to visual studio.
I marked Min Min's answer as Accepted because he found what I needed in MSDN: the location those files are installed:
%LocalAppData%\Microsoft\VisualStudio\10.0\Extensions\Company\Product\Version
For the extensions I sought, that amounted to:
C:\Users\%username%\AppData\Local\Microsoft\VisualStudio\10.0\Extensions\Microsoft\EF 4.x DbContext Generator for C#\1.0.2.0
Min Min stated he could not find the DbContextCSharp.vsix file nor the CSharpDbContext.Context.tt file. I assume he did this by doing a search, and indeed, those files are nowhere to be found on my system, either.
However, going to the indicated directory does locate the installed files. The vsix won't be there, however, and the content files are locked up in a ZIP file - hence those files could not be found via search. But everything needed is there and can be altered as needed.
I am making changes to a Visual Studio wizard that creates a project from a template, and needs to add a reference to an assembly to the project that also lives in the extension directory. So I need to set the <hintpath>.
I have not been able to figure out how a running VS extension can discover its extension directory, which is a directory name like this:
%USERPROFILE%\AppData\Local\Microsoft\VisualStudio\10.0\Extensions\myCompany\myExtension
Using System.Reflection.Assembly.GetExecutingAssembly().CodeBase yields:
"C:\Windows\Microsoft.Net\assembly\GAC_MSIL\myCompany.myExtension\v4.0_1.0.0.0__936015a19c3638eb\myCompany.myExtension.dll"
Unfortunately, not helpful. Using GetCallingAssembly() is no better--it points at another directory in the MSIL_GAC.
Is there a Visual Studio interface that returns this information? I haven't been able to find it.
If that's not possible, is it at least possible to determine if the extension is running in the experimental instance vs. non-experimental? I could use that information to locate the extension directory.
Maybe look at IInstalledExtension.InstallPath. You can get an IInstalledExtension via an IVsExtensionManager.
Unfortunately, the message in the remarks suggests this is not the right way to do things:
Although this API supports the Extension Manager infrastructure, we recommend that you do not use it because it is subject to change.
EDIT: Here's the code:
static IVsExtensionManager GetExtensionManager()
{
return myPackage.GetService(System.typeof(IVsExtensionManager)) as IVsExtensionManager;
}
static IInstalledExtension GetExtension(string identifier)
{
return GetExtensionManager().GetInstalledExtension(identifier);
}
static string GetExtensionDirectory(string identifier)
{
return GetExtension(identifier).InstallPath;
}
The string identifier is whatever you put in the "ID" field of your extension's source.extension.vsixmanifest file. It defaults to the package GUID.
Sorry for digging up an old answered question...
I was looking into a similar problem, and have implemented the Extension Manager, but decided this is just pretty awful, though if you do want to do use it these links will also help:
https://stackoverflow.com/a/24294185
http://blog.ninlabs.com/2011/04/auto-update-visual-studio-extensions/
However, I decided to look into how the CodeGenerator in Asp.Net.Scaffolding accessed template files. Turns out, very easily...
var path = Path.Combine(Path.GetDirectoryName(GetType().Assembly.Location), "MyPath");
Simples
In Visual Studio 2010, I want to create a project template that includes links to two files that should exist on the system. One of them is a common AssemblyInfo.cs file. Another is the strong name key file (*.snk).
I need these references to be relative, because each developer's workspace will be set up differently. Is it possible for the project template to somehow figure out where these files reside in each developer's environment?
From reading about templates, it sound like they're pretty static so I wonder if tricks can be done to do something like this. If nothing else, I can add bogus references that will cause compilation errors and force the developer to hook these files in. But if I can do it for them, that would be better.
You should set the CreateInPlace property to true in the vstemplate. The documentation says
Specifies whether to create the project and perform parameter replacement in the specified location, or perform parameter replacement in a temporary location and then save the project to the specified location.
If you want relative paths to work, you need the parameter replacement to occur in the place where you're creating the project, not in a temporary location.
Microsoft have confirmed that this is a bug with the extensibility model and project templates. I managed to get round this by using IWizard. I added the following code in the RunFinished method of my IWizard implementation:
//Get linked file directory
string coreDir = Path.GetDirectoryName(MyProject.FullName);
//Data folder
ProjectItem propertiesProjectItem = slSharedProject.ProjectItems.Cast<ProjectItem>().Where(p => p.Name == "Data").First();
propertiesProjectItem.ProjectItems.AddFromFile(coreDir + #"\Service\TheFileIWantToLink.cs");
This code links in a copy of TheFileIWantToLink.cs file to my shared Silverlight project (slSharedProject).
You could try to integrate a Wizard into your Project Template and set the Paths to the linked files. If i remember right you don't have to create an User Inteface; you only have to specify the correct replacements in the replacementsDictionary and VS will replace the values in your Template File. See this or this for further information.
ASP.NET application w/CSLA framework; Visual Studio 2008
I have a class library of business objects. I am storing the broken rules strings in the Resource file associated with the project (My Projects > Resources.resx). I added a new resx file to the project and named it Resources.fr-CA.resx to store the french language equivalents of the rules.
I am calling the strings with the My.Resources object, like this:
e.description = My.Resources.BrokenRulesString
This works like a charm when I run the application locally (i.e. hit "play" in Visual Studio). However, when I build and deploy the application to another environment I always get the values in the default resource file.
Even if I explicitly set the culture to "fr-CA" in the Resources.Designer.vb file, like this, the property returns the string from the default resource file:
Public ReadOnly Property BrokenRulesString() As String
Get
Return ResourceManager.GetString("BrokenRulesString", "fr-CA")
End Get
End Property
It looks to me like the application can't see the fr-CA resource file so defaults to the... default file. Any tips to get this working?
Thank you.
You need to make sure the satellite assembly containing your localized strings is deployed in the correct directory structure. See this MSDN article for details.
From the article:
After you have compiled your satellite assemblies, they all have the same name. The runtime differentiates between them based upon the culture specified at compile time with Al.exe's /culture option and by each assembly's directory location. You must place your satellite assemblies in expected directory locations.
Ultimately it came down to the fact that I hadn't added the proper Project Output Group (Localized resources) for the Business.Library project to the setup project. I added it to the bin folder and now the deployed application works like a charm as well.
Oded, thanks for getting my head pointed in the right direction. Cheers!