Basically, I have my application with a resource for the title of the main window in my Resources.resx file. I bind this to my main windows title
Title={Binding Title, FallbackValue='My Generic Title'}
I have 2 installers (one for each of my clients). This is how I do it right now:
Set the title particular to client A.
Compile the application.
Build the installation file for client A.
Set the title particular to client B.
Compile the application.
Build the installation file for client B.
Is there any way to set the resource to be particular to the installer project I use? Then, afterwards, change the value back to a "default" value?
I think you can do the following:
1) Create two assemblies named Resources.ClientA and Resources.ClientB. They should have exactly the same content (same classes in the same namespaces) but this content should be client-specific for corresponding clients. For example I've added following class just for illustration:
// assembly for ClientA :
namespace Resources
{
public class Class1
{
public static string Text { get { return "Client A text"; } }
}
}
// assembly for ClientB :
namespace Resources
{
public class Class1
{
public static string Text { get { return "Client B text"; } }
}
}
2) Open your main project file (csproj) and add:
<PropertyGroup>
<ClientToken>ClientA</ClientToken>
</PropertyGroup>
3) In the same file below add the reference:
<ItemGroup>
<ProjectReference Include="..\Resources.$(ClientToken)\Resources.$(ClientToken).csproj">
<Name>Resources.$(ClientToken)</Name>
</ProjectReference>
</ItemGroup>
Now by replacing the ClientToken property you can substitute client specific assemblies. You will also be able to specify this property as part of continuous integration process but probably you will need to modify your csproj file a bit so it will take this property from outside and only if it is not set then set some default value.
Also I'm not sure about easier ways to accomplish your task, probably there are some.
Related
What would be the optimal solution to implement syntax coloring for a Text Editor (Eclipse E4 RCP) where the words to be colored are about 1200 at least.
My intention is to create a file to be stored in a folder inside the application installation directory.
Then, by means of an OSGI service read the file and return IRule[] to the SourceViewerConfiguration:
The OSGI service shall be something similar to:
public interface IRulesLoader {
public IRules[] loadRules(String path);
}
and
public class RulesLoaderImpl implements IRulesLoader {
#Override
public IRules[] loadRules(String path) {
//Read the file or whichever method to obtain IRules[]...
}
}
Then, at the Text Editor Part (which extends SourceViewerConfiguration) set the rules:
scanner.setRules(iRulesLoader.loadRules(path));
This link shows an example about where to include the above line.
In case that OSGI services are good option to load the file:
How can I read the file at runtime from the installation directory (when released) and at developing time from the project (workspace) folders?
I have a javascript bundle that I only want to include when testing, not when the code is deployed to production.
I have added a Property called IsEnabledTestingFeatures. In the BundleConfig.cs file I access it like so:
if(Properties.Settings.Default.IsEnabledTestingFeatures) {
bundles.Add(new ScriptBundle("~/bundles/testing").Include("~/Scripts/set-date.js"));
}
This works correctly.
Now, I only want to include the bundle in my page if this property is set to true.
I have tried the following, but the compiler is complaining that it cannot find the Default namespace:
#{
if( [PROJECT NAMESPACE].Properties.Default.IsEnabledTestingFeatures)
{
#Scripts.Render("~/bundles/testing")
}
}
I tried finding how to access the Scripts.Render functionality from the Controller itself, but have been unsuccessful.
I prefer to add the bundle in the view itself, but will settle for adding it via the Controller.
The ViewBag should not be necessary...
Using appSettings from web.config you don't need to recompile for testing and it deploys easily.
<appSettings>
<add key="TestingEnabled" value="true" />
</appSettings>
View or Layout
#{
bool testing = Convert.ToBoolean(
System.Configuration.ConfigurationManager.AppSettings["TestingEnabled"]);
}
#if (testing) {
#Scripts.Render("~/bundles/testing")
}
And I would define "~/bundles/testing" in BundleConfig regardless of the testing condition unless you wish to bundle this with other scripts.
If you assigned Properties.Default.IsEnabledTestingFeatures from AppSettings then the root of your problem is how you implemented your Properties.
Until, hopefully, an alternative [read: better] solution is proposed, I have implemented it using ViewBag.
BundleConfig.cs
//if testing features are enabled (eg: "Set Date"), include the necessary scripts
if(Properties.Settings.Default.IsEnabledTestingFeatures)
{
bundles.Add(new ScriptBundle("~/bundles/testing").Include(
"~/Scripts/set-date.js"));
}
Controller
public ActionResult Index()
{
ViewBag.IsEnabledTestingFeatures = Properties.Settings.Default.IsEnabledTestingFeatures;
return View();
}
View
#if (ViewBag.IsEnabledTestingFeatures != null && ViewBag.IsEnabledTestingFeatures)
{
#Scripts.Render("~/bundles/site")
}
Some Notes:
I did not implement this via a property in the ViewModel due to this
property/feature being independent of the data being displayed. It
seemed incorrect to associate this condition with individual data
models as it is a site-wide feature.
I used application-level settings because it will be easier to configure this property on a per-environment basis due to the fact we utilize web transforms. Thus each environment can set this property as needed.
I need to get the absolute output path of the project's assembly via DTE. I tried doing this using this method, where I would access the OutputPath property, combining it with the assembly name, however this produces the relative path, such as:
..\..\Output\AnyCPU\Debug\MyAssembly.dll
Using Path.GetFullPath is not good for me, because my project might be executing from another location.
I noticed that the $(TargetPath) macro (in Build Events tab in project properties) contains the full path of the assembly. How can I access this value programmatically from the DTE?
Actual question is - how do I get the absolute output path of the project?
I don't know how to programmatically access the "$(TargetPath)", I agree that that could've been the best solution.
However, the approach you mentioned should still be workable,since the OutputPath property is relative to the folder in which the project file resides. (Please let me know if I'm missing some scenario where this is not the case?)
So you can do something similar to this:
private static string GetProjectExecutable(Project startupProject, Configuration config)
{
string projectFolder = Path.GetDirectoryName(startupProject.FileName);
string outputPath = (string)config.Properties.Item("OutputPath").Value;
string assemblyFileName = (string)startupProject.Properties.Item("AssemblyName").Value + ".exe";
return Path.Combine(new[] {
projectFolder,
outputPath,
assemblyFileName
});
}
(the overload of Path.Combine used here is only available in .NET 4.0 but you could always backport it)
I'm trying to add an Import task to a .csproj file programmatically, but I don't want to use the Microsoft.Build.BuildEngine objects to do this because VS will then pop up warnings about the project file being modified from outside of Visual Studio.
I've seen a few pages [1] [2] suggesting that the IVsBuildPropertyStorage interface will let me access the MSBuild parts of the .csproj file, but I'm having trouble figuring out how to do this, or if it's even possible really. It looks like I need to specify the name of the property I want to access, but I'm not sure how to figure that out. Calling GetPropertyValue() for an "Import" property doesn't return anything for project files that are already set up how I want my final results to look:
EnvDTE.Project proj = ...;
var sol = Package.GetGlobalService(typeof(VsSolution)) as IVsSolution;
IVsHierarchy hier;
sol.GetProjectOfUniqueName(p.UniqueName, out hier);
var storage = hier as IVsBuildPropertyStorage;
string val;
storage.GetPropertyValue("Import", String.Empty,
(uint)_PersistStorageType.PST_PROJECT_FILE, out val);
// val is null
[1] https://mpfproj.svn.codeplex.com/svn/9.0/Tests/UnitTests/ProjectTest.cs
[2] http://social.msdn.microsoft.com/Forums/en-US/vsx/thread/e1983591-120a-4a2f-a910-e596dd625e68
Thanks. I'd appreciate any suggestions I can get with this.
I asked a similar question see here Programmatically adding and editing the Targets in a Visual Studio Project File What you can do to add an import to the project file programmatically is to use this namespace http://msdn.microsoft.com/en-us/library/microsoft.build.construction.aspx which is from the assembly (in the GAC) Microsoft.Build.dll. You can accomplish this in about 3-4 steps:
the following is pseudo code:
Get the Project File location using the DTE.ActiveSolutionProjects and getting the Properties of each Project. Get the FullPath and the FileName to get the full path of the project file.
Once you have the full path of the project file, call the ProjectRootElement.Open static method:
ProjectRootElement project = ProjectRootElement.Open(projectPath);
Once you have the ProjectRootElement reference, you can call the AddImport method (where name is the Project Identifier Attribute):
project.AddImport(name)
That should do it.
Import element is not a Property element in MSBuild nor and Item one.
I think you can't add an Import using IVsBuildPropertyStorage.
What I would like to do is have VS2008, when I open a code file, collapse all members of the classes/interfaces in the file by default (including, crucially, any XML documentation and comments).
I do not want to use regions, at all.
I would also like to be able to use the ctrl+m, ctrl+l chord to toggle all member outlining (for example, if everything is collapsed, I would like it to expand all of the members, but not the comments or XML documentation).
Possible? How?
Yes to part 1.
Unsure about part 2.
To have VS2008 automatically open files in a Collapsed state you'll need to create an addin to run the "Edit.CollapsetoDefinition" when each document opens.
This isn't overly tricky - The difficult parts seems to be the that you have to run the code a few milliseconds after the document is actually opened so you need to use the threed pool to do that.
Create an Addin project for VS2008.
Add this code (see following) to the end of the OnConnection Method of the Connect class.
switch (connectMode)
{
case ext_ConnectMode.ext_cm_UISetup:
case ext_ConnectMode.ext_cm_Startup:
//Do nothing OnStartup will be called once IDE is initialised.
break;
case ext_ConnectMode.ext_cm_AfterStartup:
//The addin was started post startup so we need to call its initialisation manually
InitialiseHandlers();
break;
}
Add this method to the Connect class
private void InitialiseHandlers()
{
this._openHandler = new OnOpenHandler(_applicationObject);
}
Add a call to InitialiseHandlers() to the OnStartupComplete method of the Connect class.
public void OnStartupComplete(ref Array custom)
{
InitialiseHandlers();
}
Add this class to the project.
using System;
using System.Collections.Generic;
using System.Text;
using EnvDTE80;
using EnvDTE;
using System.Threading;
namespace Collapser
{
internal class OnOpenHandler
{
DTE2 _application = null;
EnvDTE.Events events = null;
EnvDTE.DocumentEvents docEvents = null;
internal OnOpenHandler(DTE2 application)
{
_application = application;
events = _application.Events;
docEvents = events.get_DocumentEvents(null);
docEvents.DocumentOpened +=new _dispDocumentEvents_DocumentOpenedEventHandler(OnOpenHandler_DocumentOpened);
}
void OnOpenHandler_DocumentOpened(EnvDTE.Document document)
{
if (_application.Debugger.CurrentMode != dbgDebugMode.dbgBreakMode)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(Collapse));
}
}
private void Collapse(object o)
{
System.Threading.Thread.Sleep(150);
_application.ExecuteCommand("Edit.CollapsetoDefinitions", "");
}
}
}
And now all opened files should be fully collapsed.
It would be much easier to use the Visual Studio Macros to do the same thing. Editing the "EnvironmentEvents" Macro file in MyMacros and adding a handler for DocumentEvents.DocumentOpened with :
DTE.ExecuteCommand("Edit.CollapsetoDefinitions")
A quick way to collapse all outlining to function-definitions is to press:
Contextmenu-button*(next to your right windows button)*, L, O
I use it all the time. If there is a real hotkey for this please tell me :)
I had tried working out some Visual Basic code for a macro myself, borrowing from different places, and couldn't get anything to work. So what did I do? Why, I asked a question on StackOverflow of course! It got answered, I added the suggested code to my EnvironmentEvents macro, and now when I open CS files, after about a second, all my definitions are collapsed. :)