Is there a way to save EnvDTE Project global variables to the vcxproj.user file rather than the .vcxproj file? - visual-studio-extensions

As the title states, I'm trying to save data to the user file (projectname.vcxproj.user) rather than the project file (projectname.vcxproj)
Reading the variable (or initialising it) is done like this:
var globals = project.Globals;
string readValue = "";
if (!globals.VariableExists["variablename"])
{
globals.VariablePersists["variablename"] = true;
}
else
{
readValue = (string)globals["variablename"];
}
and writing the data is done with this line
var globals = m_project.Globals;
globals["variablename"] = "write this value";
However, the data gets written into the .vcxproj file as
<ProjectExtensions>
<VisualStudio>
<UserProperties variablename="write this value" />
</VisualStudio>
</ProjectExtensions>
rather than into the .vcxproj.user file. Is it possible to write to .vcxproj.user instead?

There is few information about .vcxproj.user file, you may have read this doc: .user files and why they are problematic or this doc: .vcxproj.user files.
Normally, the properties are set/stored in .xxproj file by default these days. Due to some reasons, the .user file is used for specific properties, or under specific circumstance.
I believe the global variables are written to the .vcxproj file by default, and it is not possible to write the global variables to the .vcxproj.user file.

Related

Deleting contents of xml file in Qt

I have a program which writes xml, I used a logic where it creates a blank xml if(file.open(QIODevice::ReadWrite))
{
QTextStream stream(&file);
stream<<""<<endl;
}
XMLWriter();
Then i call XMlwriter . But the problem is when I want to make changes and save it for 2nd time, it's not overwriting. it's just adding to the exisiting file hence creating duplicates. is there any where i can delete the enitre xml contents maybe before stream<<""<<endl;
To truncate the file, pass the QIODevice::Truncate flag into your QFile::open() call:
if (file.open(QIODevice::ReadWrite | QIODevice::Truncate)) {
// ....
}
Alternately, if you are only writing to the file (and not reading from it), you can use the QIODevice::WriteOnly flag, which implies QIODevice::Truncate:
if (file.open(QIODevice::WriteOnly)) {
// ....
}

Reference variables in a separate less file using SquishIt (support dynamic LESS content)?

We are using bootstrap for our project in MVC4. So far, we were referencing the bootstrap.less file in our main layout page and it worked great. However, a new requirement has come along that requires us to have customized look for each of our department pages (each department has its own layout that use the main layout)
bootstrap.less has this structure:
#import variables.less // defines all the variables
#import others // all imports like mixins.less, reset.less etc
since we need to inject our variable override, we created another less file:
bootstrap-without-variables.less //contains all the imports without the variables.less from bootstrap.less
The reason for this separation is to inject our variable override so that we can customize the bootstrap styles for our pages.
We are using SquishIt to bundle the less files into a bundle.
Here is the Bundle:
Bundle.Css()
.Add("~/bootstrap/variables.less")
.Add("~/variable-override.less") // custom override
.Add("~/bootstrap/bootstrap-without-variables.less")
.MvcRender("styles_combined_#.js");
This does not work at all. If I remove the variables.less and reference that in bootstrap-without-variables.less (which now becomes similar to bootstrap.less), it works perfectly fine.
The issue, I think, is that each file is evaluated and converted to css independently before combining them together.
Is there a way to tell the bundler to first bundle the files into one and then to evaluate and convert to css or a better solution to this problem?
Like mentioned by AlexCuse, there was no way for me to do what I mentioned above using only SquishIt. However, as mentioned in https://github.com/jetheredge/SquishIt/issues/170, there is an overload to AddString() that lets you add dynamic less content.
For example,
.AddString("LessString",".less") // .less being the extension
This works perfectly fine as long as the LessString does not contain any imports (#import). So, I downloaded the source from https://github.com/jetheredge/SquishIt and started diving into the code. Going through the code I found that the content loaded through AddString() has the CurrentDirectory set to the path of my IIS ("c:\windows\system32\inetsrv"). As a result of which, the imports were throwing
FileNotFoundException (You are importing a file ending in .less that
cannot be found.)
So, I needed a way to set the current directory (reference location from where my imports will be searched)
Here is what I did:
STEP1: Extended Asset to have a property called CurrentDirectory
internal string CurrentDirectory { get; set; }
STEP2: Added a third optional parameter to the AddString() overload
public T AddString(string content, string extension, string currentDirectory = null)
{
return AddString(content, extension, true, currentDirectory);
}
STEP3: Updated the AddString() to add the current directory to the Asset
T AddString(string content, string extension, bool minify, string currentDirectory = null)
{
if (bundleState.Assets.All(ac => ac.Content != content))
bundleState.Assets.Add(new Asset { Content = content, Extension = extension, Minify = minify, CurrentDirectory = currentDirectory });
return (T)this;
}
STEP4: Modify the PreprocessArbitary (For Release) on BundleBase to set the current directory
protected string PreprocessArbitrary(Asset asset)
{
if (!asset.IsArbitrary) throw new InvalidOperationException("PreprocessArbitrary can only be called on Arbitrary assets.");
var filename = "dummy." + (asset.Extension ?? defaultExtension);
var preprocessors = FindPreprocessors(filename);
return asset.CurrentDirectory != null ?
directoryWrapper.ExecuteInDirectory(asset.CurrentDirectory, () => MinifyIfNeeded(PreprocessContent(filename, preprocessors, asset.Content), asset.Minify)) :
MinifyIfNeeded(PreprocessContent(filename, preprocessors, asset.Content), asset.Minify);
}
For Debug, modify the RenderDebug to set the current directory
if (asset.IsArbitrary)
{
var filename = "dummy" + asset.Extension;
var preprocessors = FindPreprocessors(filename);
var processedContent = asset.CurrentDirectory != null ?
directoryWrapper.ExecuteInDirectory(asset.CurrentDirectory, () => PreprocessContent(filename, preprocessors, asset.Content)) :
PreprocessContent(filename, preprocessors, asset.Content);
sb.AppendLine(string.Format(tagFormat, processedContent));
}
Here is my how I add dynamic or static less files now:
.AddString("#import 'content/bootstrap/variables.less';", ".less", AppDomain.CurrentDomain.BaseDirectory)
For my above requirement, I read the variables.less into a string builder, then add my variable-override.less and finally add the bootstrap-without-variables.less to the string builder.
It has worked for me so far. I tested following scenarios:
normal less files with imports, e.g. .Add("~/content/styles.less")
inline less without imports, e.g. .AddString(LessString, ".less")
dynamic less files with imports, e.g. .AddString("#import content/bootstrap/variables.less';", ".less", AppDomain.CurrentDomain.BaseDirectory)
I'll try to do a pull request soon. I hope this helps people looking to support dynamic LESS content with imports.
You are right, SquishIt does the less processing before combining files. There is no way to do what you ask using only SquishIt, but I suppose you could combine the files on your own on the way in (use the .AddString method to add your resulting .less content to the bundle). One of the alternatives may suit your needs better, I'm not sure.

Manually use precompiled handlebars templates

How to manually use the precompiled handlebars.js templates?
Let's say, we have
source = "<p>Hello, my name is {{name}}</p>"
data = { name: "Joe" }
Currently, I have
template = Handlebars.compile(source)
render: -> template(data)
The source is coming from the database, and in order to cut down on the compilation time, I want to use a compilation step, precompiling the template server side with Handlebars.precompile(source) and then using something like:
template = precompiled_template
render: -> precompiled_template(data)
The precompiled_template is a string with function definition, so that doesn't work.
Also, I've found that Hanlebars.compile(source)() == Handlebars.precompile(source), but after browsing the source codes of handlebars, it's compilers and runtime, I'm still not sure how to achieve this.
if you did not find the right question till now, the answer is pretty simple.
Handlebars comes with a C pre-compiler on the command line, if you can access your shell you can simple just compile your templates each separated or merge them together into one file.
you can install Handlebars via npm / or build it on your system.
on the shell you can access the help file
$> Handlebars [ENTER]
You will see a help file like >
- f --output Output File etc etc ..
- m --min Minimize Output
$> Handlebars mysupertemplate.handlebars -f compiled.js -m ("-m" if
you want to minify the js file)
To run Handlebars.compile in the browser is a huge loss in performance, so it's worth a try to precompile on the server before sending the file to the browser.
To register Handlebars templates in your browser you have to load them like this:
var obj = {"foo":"bar"}
var template = require("./mytemplate-file.js") // require.js example
template = template(Handlebars) // Pass Handlebars Only if the template goes mad asking for his Father
var html = Handlebars.templates[template-name](obj)
For example if you have more then one template registered in the "templates-file" you will be able to access after the require call all templates by name using
var html = Handlebars.templates["templateName"]({"foo":"bar"});
You can go even further by register all the know helper within the file and / or making custom helpers for partials like so..
*// This will be the helper in you app.js file*
Handlebars.registerHelper("mypartials", function(partialName, data) {
var partial = Handlebars.registerPartial(partialName) || data.fn
Handlebars.partials[partialName] = partial
})
And in your template file you can put this...
{{#mypartial "divPartial"}}
<div id="block"><h2>{{foo}}</h2><p>{{bar}}</p></div>
{{/mypartial}}
{{#mypartial "formPartial"}}
<form id="foo"><input type="text" value="{{foo}}" name="{{bar}}"></form>
{{/mypartial}}
Now you can access this files by calling
var html = Handlebars.partials["divPartial"]({"foo":"bar","bar":"foo"})
var formHtml = Handlebars.partials["formPartial"]({"bar":"bar","foo":"foo"})
Hope this helped a bit ..
This speed test http://jsperf.com/handlebars-compile-vs-precompile/3 gave the answer.
Apparently, one solution is to eval() that resulting string and it will work.
The code is
var data = { name: "Greg" };
var source = "<p>Howdy, {{ name }}</p>";
eval("var templateFunction = " + Handlebars.precompile(source));
var template = Handlebars.template(templateFunction);
template(data);
=> "<p>Howdy, Greg</p>"
Of course one needs to be careful with eval and probably a better solution exists.

Is there way to read a text file from an assembly by using Reflection in C#?

I have a text file inside the assembly say MyAssembly. I am trying to access that text file from the code like this :
Stream stream = Assembly.GetAssembly(typeof(MyClass)).GetFile("data");
where data is data.txt file containing some data and I have added that .txt as Embedded Resources. I have dome reading of the images from the Assebly as embedded resources with code like this :
protected Stream GetLogoImageStream()
{
Assembly current = Assembly.GetExecutingAssembly();
string imageFileNameFormat = "{0}.{1}";
string imageName = "myLogo.GIF";
string assemblyName = current.ManifestModule.Name;
int extensionIndex = assemblyName.LastIndexOf(".dll", StringComparison.CurrentCultureIgnoreCase);
string file = string.Format(imageFileNameFormat, assemblyName.Remove(extensionIndex, 4), imageName);
Stream thisImageStream = current.GetManifestResourceStream(file);
return thisImageStream;
}
However, this approach did not work while reading the .txt file from an the executing assembly. I would really appreciate if anybody can point me to the approach to read .txt file from an assembly. Please dont ask me why I am not reading the file from the drive or the network share. Just say that the requirement is to read the .txt file from the Assembly.
Thank you so much
GetManifestResourceStream is indeed the correct way to read the data. However, when it returns null, that usually means you have specified the wrong name. Specifying the correct name is not as simple as it seems. The rules are:
The VB.NET compiler generates a resource name of <root namespace>.<physical filename>.
The C# compiler generates a resource name of <default namespace>.<folder location>.<physical filename>, where <folder location> is the relative folder path of the file within the project, using dots as path separators.
You can call the Assembly.GetManifestResourceNames method in the debugger to check the actual names generated by the compiler.
Your approach should work. GetManifestResourceStream returns null, if the resource is not found. Try checking the run-time value of your file variable with the actual name of the resource stored in the assembly (you could check it using Reflector).
I really appreciate for everybody's help on this question. I was able to read the file with the code like this :
Assembly a = Assembly.GetExecutingAssembly();
string[] nameList = a.GetManifestResourceNames();
string manifestanme = string.Empty;
if (nameList != null && nameList.Length > 0)
{
foreach (string name in nameList)
{
if (name.IndexOf("c.txt") != -1)
{
manifestanme = name;
break;
}
}
}
Stream stream = a.GetManifestResourceStream(manifestanme);
Thanks and +1 for Christian Hayter for this method : a.GetManifestResourceNames();

Convert CSV file or Excel spreadsheet to RESX File

I am looking for a solution or recommendation to a problem I am having. I have a bunch of ASPX pages that will be localized and have a bunch of text that needs to be supported in 6 languages.
The people doing the translation will not have access to Visual Studio and the likely easiest tool is Excel. If we use Excel or even export to CSV, we need to be able to import to move to .resx files. So, what is the best method for this?
I am aware of this question, Convert a Visual Studio resource file to a text file? already and the use of Resx Editor but an easier solution would be preferred.
I'm not sure how comprehensive an answer you're looking for, but if you're really just using [string, string] pairs for your localization, and you're just looking for a quick way to load resource (.resx) files with the results of your translations, then the following will work as a fairly quick, low-tech solution.
The thing to remember is that .resx files are just XML documents, so it should be possible to manually load your data into the resource from an external piece of code. The following example worked for me in VS2005 and VS2008:
namespace SampleResourceImport
{
class Program
{
static void Main(string[] args)
{
XmlDocument doc = new XmlDocument();
string filePath = #"[file path to your resx file]";
doc.Load(filePath);
XmlElement root = doc.DocumentElement;
XmlElement datum = null;
XmlElement value = null;
XmlAttribute datumName = null;
XmlAttribute datumSpace = doc.CreateAttribute("xml:space");
datumSpace.Value = "preserve";
// The following mocks the actual retrieval of your localized text
// from a CSV or ?? document...
// CSV parsers are common enough that it shouldn't be too difficult
// to find one if that's the direction you go.
Dictionary<string, string> d = new Dictionary<string, string>();
d.Add("Label1", "First Name");
d.Add("Label2", "Last Name");
d.Add("Label3", "Date of Birth");
foreach (KeyValuePair<string, string> pair in d)
{
datum = doc.CreateElement("data");
datumName = doc.CreateAttribute("name");
datumName.Value = pair.Key;
value = doc.CreateElement("value");
value.InnerText = pair.Value;
datum.Attributes.Append(datumName);
datum.Attributes.Append(datumSpace);
datum.AppendChild(value);
root.AppendChild(datum);
}
doc.Save(filePath);
}
}
}
Obviously, the preceding method won't generate the code-behind for your resource, however opening the resource file in Visual Studio and toggling the accessibility modifier for the resource will (re)generate the static properties for you.
If you're looking for a completely XML-based solution (vs. CSV or Excel interop), you could also instruct your translators to store their translated content in Excel, saved as XML, then use XPath to retrieve your localization info. The only caveat being the file sizes tend to become pretty bloated.
Best of luck.
I ran into similar problem and realized that the simplest way to create a .resx file from excel file is using a concatenate function of excel to generate "<"data">".."<"/data">" node for the .resx file and then manually copying the generated rows to the .resx file in any text editor. So lets say that you have "Name" in column A of an excel document and "value" in Column B of the excel document. Using following formula in Column C
=CONCATENATE("<data name=","""",A14,""" xml:space=""preserve"">","<value>", B14, "</value>", "</data>")
you will get the data node for resource. You can then copy this formula to all the rows and then copy the contents of Column C in your .resx file.
If it's in csv here's a quick Ruby script to generate the data elements.
require 'csv'
require 'builder'
file = ARGV[0]
builder = Builder::XmlMarkup.new(:indent => 2)
CSV.foreach(file) do |row|
builder.data(:name => row[0], "xml:space" => :preserve) {|d| d.value(row[1]) }
end
File.open(file + ".xml", 'w') { |f| f.write(builder.target!) }

Resources