Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Visual Studio Extension - set "Copy To Output Directory" property

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?

like image 953
Lemurr Avatar asked Mar 28 '17 11:03

Lemurr


2 Answers

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);
    }
}
like image 150
Jan Peldřimovský Avatar answered Nov 14 '22 23:11

Jan Peldřimovský


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;
            }
like image 28
Zhanglong Wu - MSFT Avatar answered Nov 14 '22 22:11

Zhanglong Wu - MSFT