35

I got a programm that generates .resx resource files. Those resource files are used in other projects, that isnt in the same solution as the project that generates the resource files.

I wonder now, if its possible to generate a designer.cs file from the resource file, so that you can access the resources directly without using the resxresourcereader.

Paul Fleming
  • 24,238
  • 8
  • 76
  • 113
JayTee
  • 1,114
  • 2
  • 11
  • 18

6 Answers6

77

Open the resx file and on its toolbar there's an Access Modifier menu. Set this to Public. This will generate a *.Designer.cs file.

enter image description here

Appulus
  • 18,630
  • 11
  • 38
  • 46
Paul Fleming
  • 24,238
  • 8
  • 76
  • 113
11

Right click on the Resources.resx and select "Run Custom Tool".

Micha Wiedenmann
  • 19,979
  • 21
  • 92
  • 137
  • Right click the resx-file and select properties. Add the value "PublicResXFileCodeGenerator" to the "Custom Tool" property then the designer file will be generated. – AH. Feb 20 '19 at 07:55
  • 1
    Is there a way to do that in the build process itself? – AtosNicoS Feb 23 '22 at 13:28
7

If the file is added to a Visual Studio Project you have to set the Custom Tool property of the .resx file to ResXFileCodeGenerator. Then will VS automatically create the needed designer file.

In one project I made a T4 script that scans the folder within the project for all images and let create a corresponding ressource file at a click.

Here is the needed part out of the T4 script:

var rootPath = Path.GetDirectoryName(this.Host.TemplateFile);

var imagesPath = Path.Combine(rootPath, "Images");
var resourcesPath = Path.Combine(rootPath, "Resources");

var pictures = Directory.GetFiles(imagesPath, "*.png", SearchOption.AllDirectories);

EnvDTE.DTE dte = (EnvDTE.DTE)((IServiceProvider)this.Host)
                   .GetService(typeof(EnvDTE.DTE));

EnvDTE.Projects projects = dte.Solution.Projects;
EnvDTE.Project iconProject = projects.Cast<EnvDTE.Project>().Where(p => p.Name == "Icons").Single();
EnvDTE.ProjectItem resourcesFolder = iconProject.ProjectItems.Cast<EnvDTE.ProjectItem>().Where(item => item.Name == "Resources").Single();

// Delete all existing resource files to avoid any conflicts.
foreach (var item in resourcesFolder.ProjectItems.Cast<EnvDTE.ProjectItem>())
{
    item.Delete();
}

// Create the needed .resx file fore each picture.
foreach (var picture in pictures)
{
    var resourceFilename =  Path.GetFileNameWithoutExtension(picture) + ".resx";
    var resourceFilePath = Path.Combine(resourcesPath, resourceFilename);

    using (var writer = new ResXResourceWriter(resourceFilePath))
    {
        foreach (var picture in picturesByBitmapCollection)
        {
            writer.AddResource(picture.PictureName, new ResXFileRef(picture, typeof(Bitmap).AssemblyQualifiedName));
        }
    }
}

// Add the .resx file to the project and set the CustomTool property.
foreach (var resourceFile in Directory.GetFiles(resourcesPath, "*.resx"))
{
    var createdItem = resourcesFolder.Collection.AddFromFile(resourceFile);
    var allProperties = createdItem.Properties.Cast<EnvDTE.Property>().ToList();
    createdItem.Properties.Item("CustomTool").Value = "ResXFileCodeGenerator";
}

I have flattened the above code a little bit, cause in my real solution i use a custom class for each picture instead of the simple filename to also support the same filename in different sub folders (by using a part of the folder structure for the namespace generation). But for a first shot the above should help you.

Oliver
  • 43,366
  • 8
  • 94
  • 151
3

You can also do this in code: (Taken from here: msdn)

 StreamWriter sw = new StreamWriter(@".\DemoResources.cs");
  string[] errors = null;
  CSharpCodeProvider provider = new CSharpCodeProvider();
  CodeCompileUnit code = StronglyTypedResourceBuilder.Create("Demo.resx", "DemoResources", 
                                                             "DemoApp", provider, 
                                                             false, out errors);    
  if (errors.Length > 0)
     foreach (var error in errors)
        Console.WriteLine(error); 

  provider.GenerateCodeFromCompileUnit(code, sw, new CodeGeneratorOptions());                                         
  sw.Close();

You need to reference system.design.dll

Ketobomb
  • 2,108
  • 1
  • 17
  • 27
0

This also worked for me: double click and open the resx file, add a dummy resource, click save. the .designer.cs file is generated.

sean717
  • 11,759
  • 20
  • 66
  • 90
0

If you deleted it or added it to .gitignore because you thought you didn't need it. this is how you regenerate the file.

Go to the Access modifier and change it from (Public/Internal) to "No Code Generation"

Now put it back to Public/Internal. VS will regenerate the Designer file for you.

David Hunsicker
  • 1,140
  • 3
  • 14
  • 24