Visual Studio (C#) Build Output path using environmental variables - c#

Is it possible to use environmental variables in the build output path in VS 2008 (et al)/ I'm trying to find a solution where several developers on my team using both Windows XP & 7 and all with different Windows logons, can all modify projects and common referenced dll's (source held on Source Safe) and not screw up the relative paths? I've tried such things as %userprofile% and $(userprofile).
I've looked into post build events but these do not really seem to provide an anawer to my problem. Sadly I'm not in the position to use 3rd party add-ons either as these will be non-commercial and it's nearly impossible to get authorization for any licences for them.
(Similar unanswered question at Output path for build in visual studio 2010)

You need to open the csproj file in a text editor and manually enter your environment variables in the OutputPath section. Visual Studio escapes the '$', '(' and ')' when you try to do this from the IDE.

I've used the subst command to accomplish this sort of thing in the past. Essentially all project references define paths in relation to a known drive letter like R:\MyProject\outputs.
Then every developer can map the R: drive (or whatever) to the folder structure particular to their environment. As long as the folder structure beneath the mapped drive is the same, the location of that mapped folder can vary between machines, builds, and users.
This works well as developers can then set up their environment with a simple batch file and easily switch between branches, projects etc and relative pathing within the projects is not broken.

PaulTee,
Is it a longshot to ask you try directory replication? Like Dropbox/Synctoy and other tools that invokes a file-copy from choosen location to the expected shared location?
In your situation, I would love to use the built-in environment variables. Probably there are a way to make it work, but until then i would go for such a solution. I would also have in mind that different users compiling to same directory, would make conflicts with both file versions and file locks (used by other user).

If you don't mind the extra copies, you could add post-build event that copies the project outputs to a commonly-agreed location for shared dlls, and everyone uses a non-relative reference to that location. It would still, though, require standardization of that target location, so maybe it is not what you are looking for. (example below would allow for drive letter independence at least)
copy $(TargetPath) \dependencies

While I don't quite understand what you're asking for, it sounds like symlinked directories will help -- you can configure the solution to output to some folder that will be symlinked to arbitrary locations on each individual box.
http://en.wikipedia.org/wiki/NTFS_symbolic_link
ghost edit - mklink is apparently new in 7, but older versions still support it (Russinovich to the rescue once again):
http://technet.microsoft.com/en-us/sysinternals/bb896768

Related

Project management (sort of)

We have a big project(solution) with several smaller projects using some common assemblies (no GAC). Every time a project is changed and has to be tested, all files in the solution must be deployed in a testing location, separate from the main branch.
I would like to deploy only the files that have changed and use the ones not changed from the main branch. Something like this:
[MainBranchFolder]
File1.dll
File2.dll
File3.dll
.....
[Branch1 subfolder]
File2.dll
So, Branch1 contains only File2.dll. When the programs runs, it will look for any dlls in current folder and, if not found, will look into Parent folder.
I know a solution for this problem that requires some code changes but I wonder if something like this can be achieved using configuration only
[Edit] I see several ppl suggested some source code management. However this is not a source code issue, it's a binary code issue. MainBranch in my example is not source code, is a folder with all the compiled assemblies (exe and dll) in my projects
It sounds like you could use some Software Configuration Management (SCM)!
There are many choices out there and a quick Google search will reveal plenty. My preference is definately GIT.
Check out: http://git-scm.com/
with the Team Foundataion Server, you can do that with the customized build.
All of the responses seem to have a Code Versioning theme, which I'm seeing is not what you're looking for.
I ran into a different, but potentially similar situation:
3 Applications, each requires the same librar(ies).
Publishing the primary application requires the other 2 to be updated.
GAC was not an option (don't ask!)
Solution 1: I know where it is, just give me the damn thing!
(Which also let me store all kinds of useful common settings dictated by the master installed program.)
My solution was to maintain a known registry key:
Part 1: The registry Entry
HKLM\Software\FoobarInternational\CommonLibrary1 [String]
In CommonLibrary1 I stored the path to the common DLL's.
Part 2: The common "find my dll" library
Think plugin architecture - it looks in current dir for dll, and if fails, checks the the provided registry key for correct location.
Solution 2: Taking a walk
In a similar manner to solution 1, the library starts in its current directory, looks for the DLL, and if its not found, checks 1 directory higher.
Here are a few links to help you with each:
Getting the Parent Directory
Using the assembly once you find it
Talking to the registry
If you want the current directory of the code running (note: if the code is in a separate dll, you will get the location of THAT dll!)
Assembly.GetExecutingAssembly().Location
OR depending on what you need . .
string directoryName = new FileInfo(Assembly.GetExecutingAssembly().Location).DirectoryName;

What is the best way to publish multiple versions of the same ClickOnce application?

I have a c# ClickOnce application that I need to be able to publish multiple times for OEM purposes.
The way I understand it now is that publish settings are located in the .csproj file.
However, this is inconvenient in the case where I want to publish multiple versions.
for example, Company A needs totally different icons, start menu location, product name etc. from Company B, but the assemblies need not be renamed.
Here are a couple approaches/questions that I can think of to solve this issue...
1.Is there a way to create a separate publish settings file to use during build time?
2.Can I edit specific publish settings (like Start Menu location, etc) at build time with MSBuild.exe? I think this would be ideal...
e.g.
MSBuild.exe project.sln /target:Publish /property:edit-project-publish-settings-here
3.Maybe create a 2nd .csproj file? (Would prefer not to do this...)
Please share your thoughts as to the best approach, or any other clever ways to make this happen. Thanks!
I wish I could give you some brilliant solution, but personally I would probably go with option 3.
I mean, its pretty simple, the changes should be pretty static and it will be difficult(ish) to totally screw it up and deploy the wrong changes to the wrong company.
If you copy the .csproj in your project folder, it will reference all of the same source files and you can just change the executable name. Create another VS solution and you can reference the copied .csproj and get rid of your first one so that you can publish two separate versions.
This isn't ideal for ClickOnce however.
If you use a Singleton object that specifies the "mode" (Company A, B, C, etc.) you can easily store that in the app.config (or another xml file). Then just re-publish your ClickOnce Application but copy the correct version of your configuration file in so it gets shipped with the build. This way, you don't need any additional csprojects Just include all of your icons and set them at run-time on App Start based on your Singleton object.
I found that you are able to edit certain properties using MSBuild.exe like this
MSBuild Solution.sln /target:publish /property:ProductName=ProductA\;Publisher=CompanyA\;ApplicationIcon=companyA.ico
I found another useful post on modifying.csproj files programatically with .NET code. (This would only be needed if you're modifying things that are deeper than just the project properties specified in the ClickOnce documentation below)
The MSBuild documentation here was also useful -- especially under Publishing Properties

C# Project Standard Directory Layout

The java build tool "maven" has a standard directory layout for projects. What is the equivalent type of directory layout for a C# project? I'm just learning C# and .NET and it seems that the IDE just dumps everything into one directory, heh. Does C#/.NET follow a convention for the directory structure?
EDIT: This would be for a desktop application (windows forms or wpf). I'm looking at one of these two, but I don't know enough yet to really know which one. Ultimately I would like to learn both.
In C# directory layout should be strictly related to the namespaces you have. Each directory creates subnamespace. Here you may find instructions how to name namespaces properly.
If you use FxCop, it will inform you if your directory (namespace) layout is OK. The main rule is that there shouldn't be namespaces with a few classes/interfaces (FxCop suggests merging two namespaces into one in such a situation).
I think that's all I can say without knowing of some special project type (Uwe mentioned some of them in his comment) you have in mind.
Usually you get the following structure in your project :
/bin/Debug (after a DEBUG build)
/bin/Release (after a Release build)
/obj/Debug
/obj/Release
/Properties (contains AssemblyInfo.cs + Resource files when added via the assembly's properties)
/ServiceReferences (contains service references if any are present in your assembly)
In addition to the above, any solution folders you create (via r-click solution explorer -> add new / folder) will be present in your project's folder.
Does this help?

Move intermediates directory on C# projects in Visual Studio

I'm currently in the process of stripping down, refactoring and cleaning up a medium sized (15 ish projects) Visual Studio solution. The solution contains projects in both C++ and C#.
I'm keen to keep things as neat as possible in terms of output - seperating anything compiler created from source code, as it helps subversion (okay, I can tell it to ignore files, but I still feel it's messy) from freaking out.
The output I would like to achieve is as follows:
SolutionDir/
SolutionDir/src/project1/{ Code here }
SolutionDir/int/project1/configuration/{.obj files and other misc compiler junk here}
SolutionDir/bin/project1/configuration/{The fun stuff goes here}
This seems trivial with C++ projects as you can specify both the output and the intermediates directory. However with C#, at least through the Visual Studio 2008 User Interface it seems impossible to move the obj directory?
After doing some digging, I added
<IntermediateOutputPath>..\..\int\ProjectName\Debug\</IntermediateOutputPath>
to the C# .csproj
This appears to work, sort of. It's true the intermediates appear to end up there, but a directory 'obj' and under it a configuration directory (e.g. 'debug') and then a 'TempPE' directory are created in the old location - all of which are empty.
This isn't really a big deal, but it would be nice to know the cause of this behavior and if possible a way to fix it.
Thanks in advance!
If you add both of the following lines to each build configuration then the "obj" folder is not created by default and there is no need for a post-build action:
<IntermediateOutputPath>Assembly\obj\Debug\</IntermediateOutputPath>
<BaseIntermediateOutputPath>Assembly\obj\Debug\</BaseIntermediateOutputPath>
SVN / SCC ignore properties are also useful if desired
I've been searching for a solution for this problem myself, and came up with something less intrusive.
Create a bat file named "CleanSrcDir.bat" somewhere (i placed mine in my project path) with the following contents:
rmdir /S /Q %1obj
SET %ERRORLEVEL%=0
After this, add something similar to the C# project's post-build events:
$(ProjectDir)CleanSrcDir.bat $(ProjectDir)
(This assumes you placed your bat file in the project directory, of course.)
Then change the post-build settings to "Always", and you're done.
It's a little hackish, but sure makes the version control problem go away.
I'd recommend adding directories that you want to ignore to an SVN ignore property one-level-up. Also, when you do an initial commit and don't add bin and obje directories, SVN clients won't freak. On another note, consider placing generated files into GeneratedFiles subdirectory of your project, and not checking that directory into SVN.

How to return the Visual Studio currently open soution directory

I have a Visual Studio solution that comprises of several projects and are separated into different directories.
In my C# or VB.NET code, I want to determine the base directory (or the directory that the solution is in).
A dirty solution would be to call the directory parent.parent.parent until I find a file *.sln, but I also have several solutions in other directories that I don't want to be returned.
I am just wondering if there is a cleaner method, maybe part of System.Diagnostics.Debugger or similar?
I look forward to your reply, thanks.
As the sln file does not need to be deployed on the target machine - why are you trying to find it at all?
If you still want to use the sln- try at EnvDTE Namespace
EnvDTE.DTE dte = (EnvDTE.DTE) System.Runtime.InteropServices.Marshal.GetActiveObject("VisualStudio.DTE");
string folder = System.IO.Path.GetDirectoryName(dte.ActiveDocument.FullName);
Even though you have solutions in other directories, presumably those aren't directories within your original solution, are they? What situation do you envisage where the "recurse up until you find a .sln file" would fail (other than running from the wrong directory)?
One alternative would be to pass the solution directory as a command line argument.
What do you need this for, out of interest?
Thank you for your answers. All were very helpful. I worked with the answer from Dror and with a little modification to the following line solved this problem, thanks.
string folder = System.IO.Path.GetDirectoryName(dte.Solution.FullName);
The reason I want to do this is whilst running the code in the IDE I determine the current Subversion revision of the project so that I can embed this into the running software version.
This is done automatically. See the article I wrote at codeproject:
link text
If you look at the code you will see I perform the following:
dirinfoSourceWorkingDir = dirInfo.Parent().Parent().Parent();
I need to determine the directory of the solution currently open in Visual Studio but want a cleaner way (and if I change the directory structure this would break the code).
Hope this makes sense!
Is the code being run from within the solution, i.e. within the IDE debugger? If so you can pass the solution directory as $(SolutionDir) from the IDE to the command line.

Categories

Resources