Visual Studio Extension - set "Copy To Output Directory" property
Asked Answered
W

2

5

I'm creating a VS extension, and I want to add a file to solution and set some properties. One of them is Copy to output directory, but I cannot find a way of setting it. Setting Build action works fine, but the desired property is not even listed in array while debugging.

private EnvDTE.ProjectItem AddFileToSolution(string filePath)
{
  var folder = CurrentProject.ProjectItems.AddFolder(Path.GetDirectoryName(filePath));
  var item = folder.ProjectItems.AddFromFileCopy(filePath);

  item.Properties.Item("BuildAction").Value = "None";
  // item.Properties.Item("CopyToOutputDirectory").Value = "CopyAlways"; // doesn't work - the dictionary doesn't contain this item, so it throws an exception

  return item;
}

How can I set the property for my newly added item?

Whose answered 28/3, 2017 at 11:10 Comment(2)
What do you mean by "doesn't work"? What is the error you are seeing?Erse
I need a vs extension like this. can you share your extension for me? I want to paste content and set the default value of Copy To Output Directory to "Copy if newer" and Build Action to "Content". thanksArva
B
4

For C# or VB projects, Cole Wu - MSFT's answer should work.

If you're trying to do the same thing for different kind of project than you might be out of luck since each project type has different properties.

From what I have tried:

  • C# and VB have 23 properties including "CopyToOutputDirectory"
  • F# has 9 properties including "CopyToOutputDirectory"
  • Node.js has 13 properties and "CopyToOutputDirectory" is missing

Look at property window of file in project you are trying to modify. Does it contain "CopyToOutputDirectory" property? If not than this property is probably not available.

EDIT:

Another options to set ProjectItem property is through it's attributes (modifying it in *.csproj). I would say that it is workaround, not real solution since you need to reload project afterwards.

private EnvDTE.ProjectItem AddFileToSolution(string filePath)
{
    var folder = CurrentProject.ProjectItems.AddFolder(Path.GetDirectoryName(filePath));
    var item = folder.ProjectItems.AddFromFileCopy(filePath);

    item.Properties.Item("BuildAction").Value = "None";

    // Setting attribute instead of property, becase property is not available
    SetProjectItemPropertyAsAttribute(CurrentProject, item, "CopyToOutputDirectory", "Always");

    // Reload project

    return item;
}

private void SetProjectItemPropertyAsAttribute(Project project, ProjectItem projectItem, string attributeName,
    string attributeValue)
{
    IVsHierarchy hierarchy;
    ((IVsSolution)Package.GetGlobalService(typeof(SVsSolution)))
        .GetProjectOfUniqueName(project.UniqueName, out hierarchy);

    IVsBuildPropertyStorage buildPropertyStorage = hierarchy as IVsBuildPropertyStorage;

    if (buildPropertyStorage != null)
    {
        string fullPath = (string)projectItem.Properties.Item("FullPath").Value;

        uint itemId;
        hierarchy.ParseCanonicalName(fullPath, out itemId);

        buildPropertyStorage.SetItemAttribute(itemId, attributeName, attributeValue);
    }
}
Bidentate answered 30/3, 2017 at 21:22 Comment(3)
It has 5 items: BuildAction, FileName, FullPath, Extension and ExtenderCATID, but no CopyToOutputDirectory. Maybe I invoke it in a wrong way if it's not available?Whose
Can you set "Copy to output directory" property manually in Properties windows of Visual Studio for added item in project you are trying to modify?Metalware
Yes I can, that's why it's odd there is no such option in the codeWhose
B
3

Please modify the code like below, it works on my side.

    foreach (Property p in item.Properties)
            {
                if (p.Name == "CopyToOutputDirectory")
                {
                    p.Value = 1;
                }

                //dic[p.Name] = p.Value;
            }

Update:

Please add the following code on your code, then check if the dictionary object has 'CopyToOutputDirectory'

 Dictionary<string,object> dic = new Dictionary<string, object>();
            foreach (Property p in item.Properties)
            {
                dic[p.Name] = p.Value;
            }
Bagworm answered 29/3, 2017 at 1:43 Comment(4)
It throws NullReferenceException for me, because item with this key is not present in the listWhose
I have update my answer, please add related and check if has related property.Bagworm
It has 5 items: BuildAction, FileName, FullPath, Extension and ExtenderCATID, but no CopyToOutputDirectoryWhose
if so, the file does not have Property named CopyToOutputDirectory, so that you could not change the value. it will throw NullReferenceException exception.Bagworm

© 2022 - 2024 — McMap. All rights reserved.