0

I'm trying to localize a SSRS reports. I have a DLL that uses a ResourceManager to access resource files that are embedded in the dll. My report has a reference to the dll. The dll is signed and strongly named. The dll and resource files' dll are compiled and in MicrosoftVisualStudio9.0/Common7/IDE/PrivateAssemblies and in Microsoft SQL Server\MSRS10.REPORTSERVER\Reporting Services\ReportServer\bin. The resource dll's are also installed in the GAC using gacutil.

Occasionally the SSRS correctly finds the resource key it needs and displays it. However, when changing the resource files to add more key's and values, I cannot get the SSRS to access the newly added files. I have repeated all of the above steps and even uninstalled and installed the resources in the GAC. Still I cannot get it to work.

Any idea what step I'm missing? Clearly the process works, I'm just not repeating something that I need to be.

2 Answers2

1

For those interested in a slightly different approach, you may want to try using a localization assembly that doesn't use the standard resource management, but instead relies on simple file IO. This makes making changes to existing resx files or adding new ones less problematic. You can add or change the resx files and instantly be able to retrieve values for use in the reports. I followed this example, with only minor tweaks and have been very happy with the results: http://www.codeproject.com/Articles/294636/Localizing-SQL-Server-Reporting-Services-Reports

One note though, the steps to follow when adding the new CodeGroup are lacking a bit in that if you place the new CodeGroup anywhere except after the unnamed UnionCodeGroup (it's the one with the Url="$CodeGen$/*") your attempts to access your custom assembly will fail.

After a lot of digging I was able to find confirmation of this on one of the msdn pages (see the "Placement of CodeGroup Elements for Extensions" section). Their wording was that "it is recommended", but from my testing I'd say it's required, at least when testing directly on the report server: http://msdn.microsoft.com/en-us/library/ms152828.aspx

The xpath to use in wix for this location in the rssrvpolicy.config file is:

//PolicyLevel/CodeGroup/CodeGroup[\[]@class='FirstMatchCodeGroup'[\]]/CodeGroup[\[]@PermissionSetName='ReportLocalization'[\]]

Here's an example of how this can be done in WiX using the util:XmlConfig extension:

    <DirectoryRef Id="TARGETDIR">
        <Component Id="I18N_RSSRVPOLICY_CONFIG" Guid="some GUID">
            <util:XmlConfig
                Id="RS_i18n_PermissionSet_remove_if_already_exists"
                File="[SQLREPORTINGSERVICESPATH]ReportServer\rssrvpolicy.config"
                Action="delete"
                On="install"
                ElementPath="//NamedPermissionSets"
                VerifyPath="//NamedPermissionSets/PermissionSet[\[]@Name='ReportLocalization'[\]]"
                Node="element"
                Sequence="100">
            </util:XmlConfig>
            <util:XmlConfig
                Id="RS_i18n_PermissionSet_add"
                File="[SQLREPORTINGSERVICESPATH]ReportServer\rssrvpolicy.config"
                Action="create"
                On="install"
                ElementPath="//NamedPermissionSets"
                VerifyPath="//NamedPermissionSets/PermissionSet[\[]@Name='ReportLocalization'[\]]"
                Node="document"
                Sequence="101">
                <![CDATA[
        <PermissionSet class="NamedPermissionSet" version="1" Unrestricted="true" Name="ReportLocalization" Description="A special permission set that allows Execution and Assertion" />
        ]]>
            </util:XmlConfig>
            <util:XmlConfig
                Id="RS_i18n_CodeGroup_remove_if_already_exists"
                File="[SQLREPORTINGSERVICESPATH]ReportServer\rssrvpolicy.config"
                Action="delete"
                On="install"
                ElementPath="//PolicyLevel/CodeGroup/CodeGroup[\[]@class='FirstMatchCodeGroup'[\]]"
                VerifyPath="//PolicyLevel/CodeGroup/CodeGroup[\[]@class='FirstMatchCodeGroup'[\]]/CodeGroup[\[]@PermissionSetName='ReportLocalization'[\]]"
                Node="element"
                Sequence="102">
            </util:XmlConfig>
            <util:XmlConfig
                Id="RS_i18n_CodeGroup_add"
                File="[SQLREPORTINGSERVICESPATH]ReportServer\rssrvpolicy.config"
                Action="create"
                On="install"
                ElementPath="//PolicyLevel/CodeGroup/CodeGroup[\[]@class='FirstMatchCodeGroup'[\]]"
                VerifyPath="//PolicyLevel/CodeGroup/CodeGroup[\[]@class='FirstMatchCodeGroup'[\]]/CodeGroup[\[]@PermissionSetName='ReportLocalization'[\]]"
                Node="document"
                Sequence="103">
                <![CDATA[
          <CodeGroup class="UnionCodeGroup" version="1" PermissionSetName="ReportLocalization" Name="Verint.SSRS.Localization" Description="This grants the Verint.SSRS.Localization.dll ReportLocalization Permissions">
            <IMembershipCondition class="UrlMembershipCondition" version="1" Url="UPDATE_ME"/>
          </CodeGroup>]]>
            </util:XmlConfig>
            <util:XmlConfig
                Id="RS_i18n_CodeGroup_update"
                File="[SQLREPORTINGSERVICESPATH]ReportServer\rssrvpolicy.config"
                Action="create"
                On="install"
                ElementPath="//IMembershipCondition[\[]@Url='UPDATE_ME'[\]]"
                Name="Url"
                Value="[SQLREPORTINGSERVICESPATH]ReportServer\bin\Verint.SSRS.Localization.dll"
                Node="value"
                Sequence="104">
            </util:XmlConfig>
            <util:XmlConfig
                Id="RS_i18n_REDP_CodeGroup_update"
                File="[SQLREPORTINGSERVICESPATH]ReportServer\rssrvpolicy.config"
                Action="create"
                On="install"
                ElementPath="//CodeGroup[\[]@Name='Report_Expressions_Default_Permissions'[\]]"
                Name="PermissionSetName"
                Value="FullTrust"
                Node="value"
                Sequence="105">
            </util:XmlConfig>
        </Component>
    </DirectoryRef>

I recommend backing up the original config files (with WiX or custom actions). This can make uninstall easier since you can just replace those originals, and also because you can test this over and over again till it's doing what you want. Good luck to you all!

idclaar
  • 688
  • 2
  • 7
  • 17
  • Can you post how you used WiX to deploy this? Thanks! – paulwhit Jun 08 '15 at 04:37
  • Why not use this XPath to find the node referenced? //CodeGroup[IMembershipCondition[@Url='$CodeGen$/*']] – paulwhit Jun 08 '15 at 05:54
  • @paulwhit, could you post this as a question, and I'll do my best to add comments/answers there. Post the link back here, if that's allowed. Most of my work was based on the codeproject mentioned above, so if you read through that and hit snags, the questions you have could be based on those. I think I remember the codeproject poster as being receptive to questions as well. Best of luck! – idclaar Jun 08 '15 at 19:24
  • I decided to just do it through a custom executable rather than wix – paulwhit Jun 17 '15 at 13:40
  • @paulwhit, for your earlier question about using the "$CodeGen$/*" xpath, did you mean for use in placing the ReportLocalization code group? the WiX documentation is scanty, but from what I remember, when you add an element (with Action="create" On="install") it appends it to the end of the childlist for the ElementPath. Doing this with custom actions is a little easier, so hopefully you've got that working! – idclaar Jun 18 '15 at 21:59
  • yes, I'm just updating it in our custom setup tool using the Xpath I posted – paulwhit Jul 24 '15 at 18:06
0

Are your rebuilding and redeploying all the satellite assemblies with each of your updates (including in the GAC)?

If not, it sounds like the problem is due to assembly versioning. There is a SatelliteContractVersion attribute that you can apply to your main assembly to help with this problem. Although rebuilding/resigning/redeploying all satellite assemblies each time you deploy an update may be easier.

Clafou
  • 15,250
  • 7
  • 58
  • 89