I have a nuget package which has .dlls files that it automatically copies to a directory when the program is compiled. Is there a way to specify where the dlls files will be copied to?
I know it's possible to modify the .targets file of the package but assume I don't have access to the package. The project is managed through git so I'd rather not have to distribute binaries along with the licenses included in the package. Currently when someone downloads/compiles the source, the nuget package is automatically downloaded through nuget restore. Is there a way to override the .targets file of the package?
I'd prefer not to use scripts to manage the dll files if possible. Also this is for a C++ project and I know nuget has restrictions based on the languages used.
If your question is asking if there's a simple configuration file or something similar where you can write "copy contents of package X to location Y", then no.
To most people, the difference between the various components in the build system are not important, so it doesn't matter to them if NuGet copies something or their project's SDK copies something, or MSBuild copies something. However, since you're now trying to do something more advanced, these differences may be important. NuGet only writes/copies files at restore (and therefore only to the packages folder, not the project output folder), but after restore, NuGet doesn't run at all. NuGet just makes the files known to the rest of the build system, and those components are responsible for deciding what to do. For example, where to copy files.
Since both C++ and .NET projects use MSBuild, the same debugging techniques can be used. From a "developer command prompt", build your project using the -bl switch to generate a "msbuild.binlog" file. You can open this file with the MSBuild structured log viewer. You can then use the search to find where in the build each dll is copied, and what the copy arguments (including destination) is. You can also look to find where the item that defined the file to be copied was created. Then, you can write an MSBuild target in your project file (or another file that gets imported by your project file) that runs at an appropriate time and updates the item to set the destination you want the file to be copied to. But, MSBuild is a scripting language, and you said you didn't want to write a script, so you might not like this approach. And if you're not already knowledgeable about MSBuild scripting, it's probably more effort than writing a powershell script. But at least it would happen automatically as part of the build (and therefore happen when you build and debug in Visual Studio), and not be some other process that needs to be manually run.
Related
We have a Libraries folder where we keep third-party DLLs and our own utility DLLs for all applications to reference. I want to do development against one of our utility DLLs and an application that consumes it at the same time. But if I check out the library DLL to change it for temporary local use, TFS insists on checking it out exclusively, which trips other people up. I understand the reasoning behind it doing that (hard/impossible to merge a DLL, so two people shouldn't be working on one at the same time), but I just want to mess with my local copy while I'm working on the library it represents.
I suppose I could delete my application's reference to the DLL and recreate the reference pointing to some other place, but of course this just begs for me to forget and check it in like that, which would obviously be bad. Not to mention that this is a pain in the neck.
How should I proceed in such a situation?
You are using a server workspace that does not allow editing outwith TFS. In TFS 2012 local workspaces were introduced which do not have a read only flag for files and you are free to edit at will.
You can change your existing workspace in a few clicks: http://msdn.microsoft.com/en-us/library/bb892960.aspx
You could just go into the file system and mark the file as writeable. Once you are happy the binary is good you could check it out, copy the new version of the file over and check it back in again. TFS marks binary files like this as locked for good reason, as you can't merge them in the way you can with textual content.
The best approach would be to use a NuGet repository to manage your binary dependencies, instead of relying on binaries checked into source control.
Using Visual Studio 2012, Azure SDK 2.1, I am trying to figure out the best way to create the csx folder for running in the azure emulator. My understanding is that the csx folder is not created until I package the Azure project. I can create a package manually from Visual Studio, but this is not an option for an automated build. The other option is to create the package using the msbuild command line. This seems a bit heavy handed as it will actually do a build which is more time consuming than just repackaging.
So, I thought that cspack might be a more lightweight option. However, when I call cspack with the following command line:
cspack.exe ServiceDefinition.csdef /copyOnly
I get the error: Need to specify the physical directory for the virtual path 'Web/' of role MyProjWeb.
But, I don't do anything like that when using msbuild. I have read a bunch of things about specifying the physical directory and some of the confusion that it can cause. So, I would prefer not to use it unless absolutely necessary, especially since I don't need to specify this when building from msbuild.
So, my main question is what is msbuild doing that cspack is not doing and how do I do the same with cspack?
My other question is, what is the easiest way to generate the csx folder for testing in the azure emulator?
Edit - Resolution
I thought that I would put down how I resolved this here in case it helps someone else. The big answer to my question (thanks to Chandermani and some other reading) is that CSPack with /copyOnly is basically a fancy xcopy to a folder structure according to some rules. If not using /copyOnly it then also does a fancy zip to create a package. Not complaining, it is fine that it is simple, but it is good to know this at the outset. You can use it for packaging anything for azure it is not tied to what can be built in Visual Studio, e.g. a PHP site. Using msbuild has the added benefit of only copying that files that are part of your web site deployment.
So, what I found when I got CSPack working and pointed at the mvc project folder is that it copied everything including source files. Which is not what I wanted. The solution that I could find is to first package the web site then point CSPack at the packaged files. If you do down this path then this link is very valuable as it describes it step by step.
So, it was either having an msbuild post-step in the Web project to package the files and then a post-step in my Azure project to cspack it or to have an msbuild post-step in my azure project to create the package (do cspack with the benefit of only including my web deployment files). Well, it seemed simpler and less error prone to just to have the one post step and let msbuild do the heavy lifting. So, the post step in my azure project is something like:
"C:\Program Files\Microsoft SDKs\Windows Azure\Emulator\csrun.exe" /devfabric:shutdown > NUL
"C:\Program Files\Microsoft SDKs\Windows Azure\Emulator\csrun.exe" /devstore:shutdown > NUL
if $(ConfigurationName) == Debug set CONSTANTSPARAMETER=DEBUG
if $(ConfigurationName) == Release set CONSTANTSPARAMETER=
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\MSBuild.exe $(ProjectDir)$(ProjectFileName) /t:clean;publish /p:Configuration=$(ConfigurationName) /p:TargetProfile=cloud /p:OutputPath=bin\Cloud$(ConfigurationName) /p:VisualStudioVersion=11.0 /p:overwritereadonlyfiles=true /p:DefineConstants="%CONSTANTSPARAMETER%" /verbosity:minimal /p:PostBuildEvent=
The first two lines shut down the compute and storage emulator.
The next two lines set the preprocessor constants. I found that #if DEBUG was no longer taking effect when built using the msbuild line. I think that this is safety protection that DEBUG is stripped when creating a package. I only ever use the package that is created by an automated build system, so it is safe for me to keep the DEBUG constant.
The actual msbuild line has a number of switches. I'll describe the unusual ones:
/p:PostBuildEvent=
If we don't set the postBuildEvent to empty then the same post step will keep getting called forever. And ever...
/p:VisualStudioVersion=11.0
Those clever guys at Microsoft made it possible to open projects with both Visual Studio 2010 and 2012. Which is great, but can bring great sadness when you run msbuild from the command line and end up with nasty MSB4019 error messages because it is looking in the wrong Visual Studio folder for the Azure tools.
Also, note that that I use the cloud profile. Since I am only after the csx files it doesn't seem to make a difference whether I use local or cloud at this point. When I run in azure I specify ServiceConfiguration.Local.cscfg.
Edit: In the end I took this out of the post step and put in my automated build. My original intention was that running the tests from my dev machine would be the same as my automated build, but the post step took too long and the views were sourced from the obj folder rather than the proj folder when running under the debugger which meant I had to copy across when making changes on the fly.
Unanswered questions
It would still be good to understand how msbuild does things to reduce knowledge friction when dabbling in this area. Does it create a package for the website and pass it to CSPack? Or does it parse the project files and then pass some crazy arguments to CSPack? Also when you run an azure project in the debugger, it runs in the emulator with only the binaries in the csx folder (not the images, etc). How does it do that? It would be great to see some description with pictures of the Azure build pipeline with that showed the lifecycle all the way to deployment. That might also explain why there are two copies of the binaries. Also, this would have been a whole lot easier if Visual studio had a project flag like packageOnBuild for the Azure project with options to do a copyOnly or to create a package. I see no point in uneaten cake. Edit: There is a DeployOnBuild setting that can be added to csproj.
Finally, as I mentioned the whole purpose of this is to get a csx folder that I can point the emulator at so that I can run my unit tests on my dev machine. I do the formal packaging on a build machine so don't really need it in Visual Studio. So, really I don't want to package anything and was hoping that there was an easier way of achieving all this.
Since msbuild uses the the azure project file to perform the build, it can derive a lot of information form the project file.
For cspack, the assumption is the role code has been compiled and is available for packaging. Since cspack does not depend upon project file, it needs a explicit information for the code path of the the web\workerrole project. The csdef file does not contain any such information. I suggest if you want to use cspack. Look at its documentation and try to create a package for emulator deployment from command line (CopyOnly option). Once you find the correct syntax you can embed it in you build script.
It's very straightforward to add languages to an installshield project. My goal is to
make a modified English (0x0409.ini) with some of the strings modified, such as
However I have a team of people that would have to copy these files to a directory much like C:\Program Files (x86)\InstallShield\2012Spring\Support andC:\Program Files (x86)\InstallShield\2012Spring\redist\. This is even worse with the 10+ machines in the build farm that could potentially need this file. It's a non-starter. It's hacky to have modify the install of a tool to get it to use an unsupported language.
Is it possible to check the language file to SCM and have it reside in a subfolder of <ISProjectDir>?
I don't believe so. I think you'd have to set up a post-build step that would copy in a modified ini file.
You could set up one in installshield's UI but I don't know if that persists in a stand alone build.
I have a larger solution that I desire to distribute via ClickOnce. It consists of one main shell executable that directly references only a small subsection of libraries and processes that constitute the solution.
The solution consists of a few other processes and several libraries (some C++). I need to be able to include all of these libraries and processes in one ClickOnce distribution for both local builds and TFS server builds.
I cannot reference every other library and process form the shell project. And I do not wish to push these files into a MSI to be treated as a prerequisite as it would defeat the purpose of using ClickOnce to distribute/update the product.
What is the correct method to incorporate all of our necessary files/projects into a single ClickOnce distribution?
The IDE won't detect native DLLs as dependencies when publishing, but you can run the SDK tools directly to include them manually in your ClickOnce distribution. You can either use mage.exe in your post-build script or run MageUI.exe to have a wizard to guide you through the package generation.
Suggested reading:
Walkthrough: Manually Deploying a ClickOnce Application
Understanding Dependencies of a Visual C++ Application
There is an alternative to Visual Studio for this kind of situation. You could try using Mage, but it can be a little tricky to use. My company wrote an alternative called ClickOnceMore.
ClickOnceMore is a ClickOnce build tool for when you don't want or can't use Visual Studio to do ClickOnce builds.
There is a specific page on the UI for including files (using rules to include anything from a single file to an entire directory trees) so you should be able to do exactly what you need with it.
This is what I have done in a similar situation. I use TFS at work, so convert the terms to whatever you may use (or not use) for source control.
I have a main workspace that I use for all development of my application, I keep this workspace pristine.
I then created another workspace with a proper name (ex: solution-deploy) and in this workspace I do the following:
Get latest and merge everything from source-control into the deployment workspace
I build a Release build of my application
I r-click on the root (I put them in the root, because I need to access them from there, put them in whatever folder you want) project folder for my deployment project and select "Add -> Existing Item"
I browse in the file selector to the Release directory of the assemblies I want to add to my deployment package, select them, then I use the arrow next to the Add button and drop down to "Add As Link", do this for all of the assemblies you want to add and place them wherever you want them to be organized in your deployment
In the Solution Explorer, select the added assemblies and in the Properties window set the Build Action to "Content", this should be all you have to do, but others have had to also set the "Copy to Output Directory" to "Copy Always", I don't do that
Run a Release Build
Go to the Properties view for your deployment Project
Go to the Publish Tab and Click on the Application Files button
Your files should all be available and added to the Deployment
Set up your ClickOnce settings however you need them to be
Publish your ClickOnce package
Your published package should contain all of the assemblies you need now.
Keep your separate Deployment workspace set up this way and never check it in. Do your work in your development workspace. Whenever a new deployment is needed, open your solution in your Deployment workspace and get the latest code, build, then publish.
Using a InstallScript C# .Net Wizard to connect to a WinForms solution where I used the dependency scanner to identify project outputs.
The install package is copying the un-merged app.config file to the target directory instead of the solutions merged MyApp.exe.config file. This results in a executable that does not properly pickup configuration file settings not only because the file isn't named correctly but it also does not merge in target environment settings (ie. release, debug, etc.).
How do you have the Installer copy the merged MyApp.exe.config file to the Install Directory?
Try this, I believe this should work.
Select the config file, and in the Copy to Output Directory under File.Properties, choose Copy always or Copy if newer. You can choose any file you like with this method. Basically this file will be placed to a directory where the binaries are built. This is still a better method than configuring/fixing from InstallShield, I think. I will like to hear from you, if you disagree.
Another thing, a config file is used and determined at run-time by code. That’s probably the reason why InstallShield does not know the file dependency on it. And it is out of scope for that tool.
Have fun and let me know what happens.
Tommy Kwee
I am using SlowCheetah to do my app.config transforms and here is what we're doing to get installshield to work. For postbuild step, copy all files needed by installshield to a separate Install folder (i.e. copy "$(ProjectDir)$(OutDir)." "$(ProjectDir)bin\Install"). Point installshield to that folder to build it's output
I'm also using SlowCheetah for my config transforms, but the real answer to this question is that the InstallShield project pays attention to the selected Solution Configuration. If you select the Release configuration before building the InstallShield project, the Release output will be used in the install package.