bugfixr
bugfixr

Reputation: 8077

Build Action: Content - how do get it to the Executing Assemblies folder instead of just the project folder?

I've got a Service which references a ProjectA. In ProjectA, I have a series of XML files, which all have a Build Action of Content and a Copy to Output Direction of Copy Always.

When I compile, as expected, I can go to the ProjectA/bin/debug folder and see the XML files. This is good, but when I run the Service which references ProjectA, those files are NOT included in Service/bin/debug folder (though the ProjectA.dll is there).

I was expecting the XML files to also get copied to the Service/bin/debug folder since they are marked as Content. As it is now, that "content" flag seems a bit useless since the executing assembly doesn't seem to get "access" to those files short of including them in the "Service" project as well (which I want to avoid since I'll have multiple projects referencing ProjectA).

Any tips on how to deal with this?

Upvotes: 3

Views: 3438

Answers (6)

user1179784
user1179784

Reputation: 103

can't remember where i found this but try the following. watch out for the "publish" bug in VS 2010 when deploying because it does not copy dependancy project content to the publish output directory. Currently you have to copy manually but I think I saw it was fixed in VS2012.

    /// <summary>
    /// Gets the current application directory.
    /// For class libraries and executables returns the executing directoy.
    /// For web applications returns the bin directory. This is important to find content relative to the assembly in the bin folder
    /// versus the actual executing location which maybe the shallow copy folder (Microsoft Asp.Net temporary folder).
    /// </summary>
    /// <returns>path to the appication directory</returns>
    public static string GetApplicationDirectory()
    {
        if (AppDomain.CurrentDomain.RelativeSearchPath != String.Empty && AppDomain.CurrentDomain.RelativeSearchPath != null)
            return AppDomain.CurrentDomain.RelativeSearchPath;
        else
            //if null check normal way     
            return System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
    }

Upvotes: 0

user1179784
user1179784

Reputation: 103

try this in your web.config.

<hostingEnvironment shadowCopyBinAssemblies="false" />

it forces the dlls to be read direct from the bin folder (where your content is).

has a side affects though requiring an webserver restart because the dlls get locked but easy enough to work around.

Upvotes: 0

Hans Passant
Hans Passant

Reputation: 942247

which I want to avoid since I'll have multiple projects referencing ProjectA

You've got a bigger problem, the service also needs to find the assembly. Which, if you want to share it between EXE projects needs to be in a well known location that is not going to be found automatically unless you copy the assembly to the GAC. You can't copy the .xml files to the GAC.

As long as sharing the assembly is your goal then you've got two approaches:

  • Register the assembly in the GAC so it can be found. Put the .xml files is a well-known location, the c:\programdata folder was made for that.

  • Leave the assembly in an arbitrary location, like c:\program files\projecta. You need to implement the AppDomain.AssemblyResolve event in every EXE project to help the CLR find the assembly. Making the folder path a setting in the .config file is wise. That same folder is now also a good place for the .xml files. Consider adding a public static property to the DLL that returns the folder path. You can use Assembly.GetExecutingAssembly().Location for that. Beware of the considerable danger of DLL Hell when you choose this approach, updating the DLL for one solution is going to potentially break all the other ones that use projecta.

Upvotes: 1

Russell Troywest
Russell Troywest

Reputation: 8776

Another potential option would be to add the XML files from ProjectA as a link in the service project and then set the linked files to be content and copy always. To add a file as a link select the "Add Existing" option and then select your file to add, but instead of just clicking the Add button use the drop down list and choose "Add As Link". It's an option I rarely use but it might be useful in this case...

enter image description here

Upvotes: 1

Guilherme Duarte
Guilherme Duarte

Reputation: 3441

For those kind of situations I would either:

  • Use a common folder (like Common Program Files or other) and store its location in an App settings shared troughout the solution.
  • Use a post build action to copy the files to a manually specified output directory.

You may also embed the files in the assembly and get them as resources...

Regards

Upvotes: 0

Marino Šimić
Marino Šimić

Reputation: 7340

if you create a Pre-Build event on the Service project that contains the command line copy-s required you should be fine.

Upvotes: 1

Related Questions