Tools for previewing configuration file transformations - visual-studio-2010

Are there any tools or Visual Studio 2010 extensions which allow me to view the output of a configuration file transformation short of having to publish the entire project? Is the process which performs the transformation directly invokable?
Edit
After a little more Googling I came across this:
Step 4: Generating a new transformed web.config file for “Staging” environment from command line
Open Visual Studio Command prompt by
going to Start --> Program Files –>
Visual Studio v10.0 –> Visual Studio
tools –> Visual Studio 10.0 Command
Prompt
Type “MSBuild “Path to Application
project file (.csproj/.vbproj) ”
/t:TransformWebConfig
/p:Configuration=Staging" and hit
enter as shown below:
Once the transformation is successful
the web.config for the “Staging”
configuration will be stored under obj
-->Staging folder under your project root (In solution explorer you can
access this folder by first un-hiding
the hidden files) :
In the solution explorer click the button to show hidden files
Open the Obj folder
Navigate to your Active configuration (in our current case it is “Staging”)
You can find the transformed web.config there
You can now verify that the new
staging web.config file generated has
the changed connection string section.
Source: Web Deployment: Web.Config Transformation
This isn't really a perfect solution for me as it still requires building the entire project- at least with the command he posted. If anyone knows of way to skip the build step with the MSBuild command that would be helpful (although that sounds somewhat unlikely).
Edit 2
I also found this Config Transformation Tool on CodePlex, which offers some nice functionality to extend the transformation process. This is tool is the closest thing I've seen for the functionality I'm seeking and would be a great starting point for developing an extension which creates previews. It uses the Microsoft.Web.Publishing.Tasks library to perform the transformation and does not depend on building an actual project.

The SlowCheetah VS add-in on the visualstudiogallery allows you to preview the transform results

You can transform a config file by using the same objects the MSBuild task uses, bypassing MSBuild altogether. Web config transform logic is contained in the Microsoft.Web.Publishing.Tasks library.
The following code snippet comes from a simple class library, referencing the Microsoft.Web.Publishing.Tasks library (which is installed on my machine at C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v10.0\Web).
The sample loads a source document and transform, applies the transform, and writes the results to a new file.
using System;
using Microsoft.Web.Publishing.Tasks;
// ...
var xmlTarget = new XmlTransformableDocument();
xmlTarget.PreserveWhitespace = true;
xmlTarget.Load("Web.config");
var xmlTransform = new XmlTransformation("Web.Release.config");
if (xmlTransform.Apply(xmlTarget))
xmlTarget.Save("Web.Transformed.config");
else
Console.WriteLine("Unable to apply transform.");
With a little creativity, this simple solution could be integrated into a Visual Studio plugin, perhaps as a context menu item on the web.config file. At the very least, you can make a console utility or script out of it to generate previews.
Good luck!

Old post, but thought I would share what I had found with a quick google (for those that may not have found it or tried here first):
Web.config Transformation Tester - By AppHarbor
Simply paste your original XML along with the transformation XML and see the result instantaneously.
Also, it's open source for anyone who's interested.

Just to extend on this a little.
I needed exactly what is discussed above. To be able to run the transform only.
Then hook that into my build process which happens to be TeamCity in my case.
You will need using Microsoft.Web.Publishing.Tasks, which you can just smash down with Nuget. Well, I was in VS2013 so I could. I'm sure you could acquire the dll otherwise.
Wrote a simple Console App. You may find it useful.
Program.cs
using System;
namespace WebConfigTransform
{
class Program
{
static void Main(string[] args)
{
if (args.Length != 3)
{
Console.WriteLine("Config Gen ... usage -source -transform -destination");
Environment.Exit(-1);
}
Transform t = new Transform(args[0], args[1], args[2]);
t.Run();
}
}
}
Transform.cs
using System;
using System.Collections.Generic;
using System.IO;
using System.Security;
using System.Security.Permissions;
using Microsoft.Web.XmlTransform;
namespace WebConfigTransform
{
class Transform
{
private readonly string m_source;
private readonly string m_transform;
private readonly string m_destination;
public Transform(string source, string transform, string destination)
{
m_source = source;
m_transform = transform;
m_destination = destination;
}
private void TransformFiles()
{
var xmlTarget = new XmlTransformableDocument();
xmlTarget.PreserveWhitespace = true;
xmlTarget.Load(m_source);
var xmlTransform = new XmlTransformation(m_transform);
if (xmlTransform.Apply(xmlTarget))
xmlTarget.Save(m_destination);
else
{
Console.WriteLine("Unable to apply transform.");
Environment.Exit(-1);
}
}
private void CheckPermissions()
{
string directoryName = m_destination;
PermissionSet permissionSet = new PermissionSet(PermissionState.None);
FileIOPermission writePermission = new FileIOPermission(FileIOPermissionAccess.Write, directoryName);
permissionSet.AddPermission(writePermission);
if (!(permissionSet.IsSubsetOf(AppDomain.CurrentDomain.PermissionSet)))
{
Console.WriteLine("Cannot write to file : " + m_destination);
Environment.Exit(-1);
}
}
private void CheckFileExistance()
{
List<string> ls = new List<string>();
ls.Add(m_source);
ls.Add(m_transform);
foreach (string item in ls)
{
if (!File.Exists(item))
{
Console.WriteLine("Cannot locate file : " + item);
Environment.Exit(-1);
}
}
}
public void Run()
{
CheckFileExistance();
CheckPermissions();
TransformFiles();
}
}
}

Related

Is it possible to read MSBuild macros of C/C++ project programatically outside of Visual Studio?

I am trying to do a mass edit on Visual Studio 2017 projects (.vcxproj). This edit depends conditionally on some project properties. Sadly it's more complicated than what could I do using shared .props file.
I could reimplement the functions needed to get the macros I want, such as $(TargetExt). But I was wondering if there is some Microsoft build tool that could print the required macro to stdout so that I could do:
getMacroValue.exe -project MyProject.vcxproj -value TargetExt
Is there anything like that, or some hack/trick that would lead to the same result? I don't mind dirty solution if it works, what I am doing is a one-time thing, but there are 50+ projects to edit with 5mins per edit so writing a script is worth it.
Maybe this sample(C# console app) could help you read the property value from proj file.
static void Main(string[] args)
{
if (args.Length < 2)
{
return;
}
string path = args[0];
string macro = args[1];
ProjectCollection collection = new ProjectCollection();
Project project = new Project(path, null, null, collection, ProjectLoadSettings.IgnoreMissingImports);
string val = project.GetPropertyValue(macro);
Console.WriteLine(val);
Console.ReadLine();
}

C++ Windows Forms application icon exception

I want to set an icon for my Windows Form application. My actions step by step:
I created an 'icon.ico' (256x256) and put it into my project folder
In my 'Form1.h [Design]' I chose this file using Properties
This code appeared in 'Form1.h'
void InitializeComponent(void)
{ ...
this->Icon = (cli::safe_cast<System::Drawing::Icon^>(resources->GetObject(L"$this.Icon")));
... }
The object '$this.Icon' appeared in 'Form1.resx'
I rebuilt the whole project -> no errors
During execution the line 'this->Icon = ...' causes an exception: System.Resources.MissingManifestResourceException: 'Could not find any resources appropriate for the specified culture or the neutral culture. Make sure "WinForm.Form1.resources" was correctly embedded or linked into assembly "MyProject" at compile time, or that all the satellite assemblies required are loadable and fully signed.'
Here I found numerous advices, such as remove/add icon or set some custom properties for 'Form1.resx', but none of them works for me
Just like above, change line to:
this->Icon = gcnew System::Drawing::Icon(L"ICON_NAME.ico");
You might get error/exception while opening form creator but you shouldn't lose any data.
Been there, done that :)
Place the Icon you want to connect to your Form in the project directory.
Then replace the line above with the following:
this->Icon = gcnew System::Drawing::Icon(L"app.ico");
This should neutralize the bug that Microsoft has not fixed.
If you are using visual studio 2019 , you need to change the name of namespace in Form1 the same as your project name, i did it and it works
and make sure you change it in main :
[STAThread]
int main() {
Application::EnableVisualStyles();
Application::SetCompatibleTextRenderingDefault(false);
Application::Run(gcnew your_namespace_name::Form1());
return 0;
}

How to run a single class in a console inside my MS visual studio 2012

I have the following class:-
public Class test{
public void testmethod(int i)
{
i = 56789121;
//code ges here
Console.WriteLine(i);
} }
but i need to run this class an see the result of the Console.writeline,, but i am not sure how i can do this. i usually build a web application using MS visual studio and run the application by clicking on "start" button,, but i have never try to output the result using Console.writeline.
BR
Build a Console application instead.
File -> Add -> New Project... and select Console Application
Change the .cs file that VS produces to be something like this
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication2
{
class Test
{
public void MyMethod()
{
Console.WriteLine("Hello World!");
}
}
class Program
{
static void Main(string[] args)
{
new Test().MyMethod();
}
}
}
The usual way to do this, as Nigel suggested, is to make a Console App for testing stuff.
However, as you stated, you can't do this from VS Web. I personally have started using LINQPad for one-off testing of my objects:
http://www.linqpad.net/
Once you open it, switch the Language dropdown to "C# Statement(s)" or "C# Program". Hit F4, browse to and add a reference to your DLL and an Import for your namespace. Now you can dim your object and call its methods right from LINQPad. LINQPad will not lock any files, so if you rebuild from VS, you can Alt-Tab back to LINQPad and re-run, and it will use the copy of the library you just build.
I've switched almost exclusively to this, as LINQPad has a really nice interface for exploring objects and exceptions you've .Dump()'ed to the output window.
(No, I'm not affiliated with LINQPad, I'm just a really satisfied customer.)
Alternatively....
Since the C# compiler is part of the .Net framework, and not Visual Studio, you can compile programs on the command line.
For example take the standard HelloWorld program in C#
using System;
public class HelloWorld
{
public static void Main(string[] args)
{
Console.WriteLine("Hello world!");
}
}
Create this in notepad, and save as HelloWorld.cs,
Open a command prompt and add the .net framework folder to your path (if not already there):
C:\> PATH=%PATH%;C:\Windows\Microsoft.NET\Framework\v4.0.30319
(note your .net version above may vary)
Then compile using the following command:
C:\> csc HelloWorld.cs
to create HelloWorld.exe.

Find Install directory and working directory of VSTO Outlook Addin; or any Office Addin

I created a VSTO Outlook Addin that uses a library Html2Xhtml.dll (.NET) which calls another Html2xhtml.exe by executing System.Diagnostic.Process.Start().
However, it fails to call Html2xhtml.exe (i think) because the working directory even when launched from Visual Studio is the current user My Documents folder. I have no control over the code in Html2Xhtml.dll so I cannot use absolute path; but I suppose I can change the working directory of the Add-in at runtime.
However, If I install this via ClickOnce or some other means where I do not know the install path the user is going to choose, how am I suppose to find my Html2xhtml.exe?
I found the answer here, full credits to robindotnet.wordpress.com.
//Get the assembly information
System.Reflection.Assembly assemblyInfo = System.Reflection.Assembly.GetExecutingAssembly();
//Location is where the assembly is run from
string assemblyLocation = assemblyInfo.Location;
//CodeBase is the location of the ClickOnce deployment files
Uri uriCodeBase = new Uri(assemblyInfo.CodeBase);
string ClickOnceLocation = Path.GetDirectoryName(uriCodeBase.LocalPath.ToString());
I've had a similar problem and solved it the same way as described by Christoph, I would also like to know whether there are any alternative ways of doing this but if you don't find anything here's an example
1)Create a custom actions library with the following InstallerClass
using System;
using System.Collections;
using System.ComponentModel;
using System.Configuration.Install;
using System.IO;
using System.Linq;
using System.Xml.Linq;
using Microsoft.VisualStudio.Tools.Applications;
using Microsoft.Win32;
namespace Setup.CustomActions
{
[RunInstaller(true)]
public partial class AddCustomization : Installer
{
static readonly Guid solutionID = new Guid("d6680661-c31e-4c24-9492-5919dc0uagt5");
public override void Install(IDictionary stateSaver)
{
string installPath = Context.Parameters["installPath"];
if(!String.IsNullOrEmpty(installPath))
{
AddTemplateToAvailableTemplates(installPath);
}
base.Install(stateSaver);
}
public override void Rollback(IDictionary savedState)
{
}
public override void Uninstall(IDictionary savedState)
{
}
private void AddTemplateToAvailableTemplates(string installPath)
{
//The example below is very basic, put in checks to see whether the registry key already exists and so on
RegistryKey key = Registry.CurrentUser.OpenSubKey(#"Software\Microsoft\Office\14.0\Common", true);
RegistryKey acturisKey = key.CreateSubKey(#"Spotlight\MyAppInstallPath");
acturisKey.SetValue("InstallPath", installPath);h);
}
}
}
2)In the setup project create a key on the Install custom action which points to the install directory:
If you need more info or would like to download the source have a look at this msdn post by Open Xml MVP Wouter Van Wugt titled "Deploying a Visual Studio 2010 Tools for Office Solution Using Windows Installer"
That is a real problem I had to fight with for quite some time. The solution used in an AddIn I had to work with was to write the install dir into the registry and read the value from there. That way things brought along which could not be embedded into the exe could be found. This is not a good solution but it worked.
Why MS sticks to this stupid "security mechanism" of copying the DLL to a random directory is a secret they will probably never reveal.
While writing my comment I actually had an idea which I did not try so far: Make your installer copy the files you need later on to %appdir%\YourCompany\YourApplication\libs or some such. You should be able to find your stuff then during runtime.
Had the same issue for ClickOnce applications. Here is what you need to do to get the deployment path of the addin:
Add System.Deployment.Application reference in your application
next is to use this property to retrieve the deployment path:
ApplicationDeployment.CurrentDeployment.UpdateLocation.ToString()
and there you go!
For COM plugins System.Reflection.Assembly.Location doesnt stable deliver what we need.
But even if it's possible to save the installation directory anyhow in the registry, it's not neccessary. Because:
A COM plugin has usualy a ID. You can define it with the GuidAttribute.
During installation/registration of your plugin, informations about this assembly are stored under:
Computer\HKEY_CLASSES_ROOT\CLSID\{...myPlugin id ....}\InprocServer32
in attribute "Codebase" you find the path to your file.
e.g.: file:///C:/Program Files/myPlugin.dll

Accessing AssemblyVersion number from assembly information to use in the post build event command line

I am trying to get access to the AssemblyVersion and AssemblyFileVersion numbers in the assembly information using the post build event command line in visual studio 2008. Is there a way to get access to that information similar to how $(TargetName) gets its macro definition from the project title.
They are declared in the AssemblyInfo.cs file and embedded in the $(TargetPath). You could write a little utility to dig it out again. For example:
using System;
using System.Reflection;
class Program {
static void Main(string[] args) {
if (args.Length == 0) throw new Exception("Assembly path required");
var asm = Assembly.LoadFile(args[0]);
Console.WriteLine(asm.GetName().Version.ToString());
var vers = (AssemblyFileVersionAttribute)asm.GetCustomAttributes(typeof(AssemblyFileVersionAttribute), false)[0];
Console.WriteLine(vers.Version);
}
}
Post build event ought to look something like this:
c:\bin\myutil.exe $(TargetPath)

Resources