Поделиться через


How to make generated resource class public

If you create managed application in Visual Studio 2005, you will notice that a resource class is generated when you add resources to the resx file. The class makes getting resource values much easier.  But some are troubled because the class is generated as Internal, which blocks you to access it in another assembly.  For people who create one assembly specially for resources, it could be a problem.

It is a limitation of the current code generator within VS.  However, the command line tool resgen.exe (in the Framework SDK) does support you to create a public class from your resource file.

We want to do is to disable the default code generator in the VS. To do that, we need show all hidden files in the solution explorer (from the toolbar). Select the resx file, and clear the "Custom Tool" property of this item.  However, if we are using VB, for the default resource.resx under "My Project", the resource designer will add "Custom Tool" back when we open it.  We would have to create a new resource file to the project, and do not use the default resource file.

Now, after editing the resx file, we can bring up a command window, and run the resgen.exe with property option, we will get the generated code, and of course, need to add it to the project.  It will be pain to do that everytime you edit the file.  However, we can put this in the project file, so it will be done automatically when we build the project.

Just save the project, and open the project file in notepad. Edit the file carefully (and backup one in case we mess it up.)  Just add those to project file (It is a sample with csproj, we need change some for VB):

  <Target Name="BeforeBuild" DependsOnTargets="CreateStrongTypeResource"/>
  <Target Name="CreateStrongTypeResource" DependsOnTargets="GenStrongTypeResource" >
    <CreateItem Include="Properties\Resources.cs">
      <Output TaskParameter="Include" ItemName="Compile" />
    </CreateItem>
  </Target>
  <Target Name="GenStrongTypeResource" Inputs="Properties\Resources.resx" Outputs="Properties\Resources.cs">
        <GetFrameworkSdkPath>
            <Output
                TaskParameter="Path"
                PropertyName="SdkPath" />
        </GetFrameworkSdkPath>
   <Exec Command="&quot;$(SdkPath)\bin\resGen.exe&quot; /str:c# /publicClass Properties\Resources.resx"/>
  </Target>

Save the csproj file, and reload it in the Visual Studio. Now, we can change the resx file with the new resource designer in VS2005, and build it, the generated type will be built into the assembly.

Comments

  • Anonymous
    May 08, 2007
    Note: in VS next version, VS supports to generate public strong type resource class directly.

  • Anonymous
    June 07, 2007
    The feature (PublicResXFileCodeGenerator) is broken in beta 1 product, because one setup registry item hasn't been updated after a version number update.  However, it is easy to patch the machine by updating a few registry items. It is mentioned in the readme document of beta1: http://download.microsoft.com/download/7/8/7/7876F535-3722-4986-8E55-F92DD55675AA/Express_contents.htm in 1.4.14 section said you need update a few registries: [HKEY_LOCAL_MACHINESOFTWAREMicrosoft%SKU%9.0CLSID{74d398e9-7cc3-4ff2-9a4d-acd177f40b58}] "InprocServer32"="C:\WINDOWS\system32\mscoree.dll" "Class"="Microsoft.VisualStudio.Design.Serialization.PublicVBMyResXFileCodeGenerator" "Assembly"="Microsoft.VisualStudio.Design, Version=9.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" "ThreadingModel"="Both" @="Microsoft.VisualStudio.Design.Serialization.PublicVBMyResXFileCodeGenerator" [HKEY_LOCAL_MACHINESOFTWAREMicrosoft%SKU%9.0CLSID{69b6a86d-ef43-4d9e-a758-8a18b38a7384}] "InprocServer32"="C:\WINDOWS\system32\mscoree.dll" "Class"="Microsoft.VisualStudio.Design.Serialization.PublicResXFileCodeGenerator" "Assembly"="Microsoft.VisualStudio.Design, Version=9.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" "ThreadingModel"="Both" @="Microsoft.VisualStudio.Design.Serialization.PublicResXFileCodeGenerator" The %SKU% here should be picked up to match what SKU (vb express, visual studio, or other express) you installed.  Check the registry with regedit, you know where to fix it.  The only thing has been changed is the version number of the full qualified assembly name.

  • Anonymous
    June 23, 2007
    MonoRail - Collocate your Strings

  • Anonymous
    July 13, 2007
    MonoRail - Collocate your Strings

  • Anonymous
    August 28, 2007
    I have tried the same thing but when I try to access the resource (from other project) by using that class it gives me following error.. "Could not find any resources appropriate for the specified culture or the neutral culture.  Make sure "SocResources.resources" was correctly embedded or linked into assembly "Rules Prototype" at compile time, or that all the satellite assemblies required are loadable and fully signed." Is there something I am missing?

  • Anonymous
    August 29, 2007
    First, ensure that "Build Action" of the resx is set to "Embedded Resource", so it will be embedded into the assembly. Second, well, if you are using VB, the code generated by the resGen.exe doesn't work well when root namespace is set.  The problem is that VB compiler automatically add a root namespace to the class, while resGen doesn't expect it.  If you open the generated code, see how it creates the resource manager, the resource name used there does not contain the root namespace. To workaround this, you can set root namespace of your resource assembly to be empty.  Or, you can edit the project file again to ensure that the logicName of the resource item does not contain the rootNamespace. It would look like:    <EmbeddedResource Include="Resource1.resx" >      <SubType>Designer</SubType>      <LogicalName>Resource1.resources</LogicalName>    </EmbeddedResource> after you change it. Hope this could resolve your problem. BTW, generating public resource classes is working in Orcas beta 2.  

  • Anonymous
    November 26, 2007
    Hey! I have some problems to implement this fine solution of yours. I have created a couple of resx files and I am have set them up as you have stated. The cs file are created on build but it is not included into the project? No errors are thrown on build!? This is how my project file looks like: <Import Project="$(MSBuildBinPath)Microsoft.CSharp.targets" />  <!-- To modify your build process, add your task inside one of the targets below and uncomment it.       Other similar extension points exist, see Microsoft.Common.targets.-->  <Target Name="BeforeBuild" DependsOnTargets="CreateStrongTypeResource" />  <Target Name="CreateStrongTypeResource" DependsOnTargets="GenStrongTypeResource">    <CreateItem Include="GUI.cs">      <Output TaskParameter="Include" ItemName="Compile" />    </CreateItem>  </Target>  <Target Name="GenStrongTypeResource" Inputs="GUI.resx" Outputs="GUI.cs">    <GetFrameworkSdkPath>      <Output TaskParameter="Path" PropertyName="SdkPath" />    </GetFrameworkSdkPath>    <Exec Command="&quot;$(SdkPath)binresGen.exe&quot; /str:c# /publicClass GUI.resx" />  </Target>  <!--  <Target Name="AfterBuild">  </Target>  --> The resx file I am testing is GUI.resx This project are Teamfoundation sourcesafe controled. I have a reference from another project to this resx project but there is no namespaces or resources to get!? What have i missed?

  • Anonymous
    November 27, 2007
    The comment has been removed

  • Anonymous
    August 01, 2008
    Generating public class is not directly supported in the Visual Studio 2008.  To enable this function, open the resource designer, and on the top of the designer(right side), "Access Modifier" will allow you to select whether to generate a public class. This function will resolve the most problem we talked here, so editing the project file is no longer needed.