Applies_ToNS 7
SummaryThis document explains how reports work in NS 7 and how you can develop reports as part of a solution.

About reports

One of the most valuable parts of an IT management system is its reporting function. Reports can show what the state of the system was, how it has changed, and what its current state is. Often, reports are the only interaction (or one of the only interactions) business managers have with IT and/or the IT management system. Thus, reports offer a rare opportunity for IT to demonstrate its value to the organization.

Business managers (outside IT) appreciate good reports that are accurate and contain useful data. These are the people who are usually judging how well IT is doing its job for the buiness. IT personnel are also very dependent on reports for doing their day-to-day jobs. They too appreciate reports that are accurate and contain useful data, but they may want to create their own ad-hoc reports to return additional data or to or modify existing reports to present data in different ways.

So, providing meaningful, well-designed, accurate reports "out of the box" in your solution is one way to generate a positive impression of a product or solution from the very beginning. It is important to know what constitutes a good report and how to create such a report. That is the purpose of this topic. However, the possible variations a report may have are so numerous and the data on which to report is so vast that no one description will fit every circumstance.

In one sentence, a good report displays the data indicated by a concise, focused topic and does so in the most useful, easy-to-understand format for the type and amount of data being presented.

Reports are created by the solution developer as well as the customer. Not every report an administrator or IT customer may want can be anticipated and created as part of a solution. However, the more comprehensive and thorough a solution team is when creating the reports that it develops and delivers with its solution, the more likely this team is to have happy customers. (This assumes that all other parts of the solution also function well.)

Reports should cover all the common scenarios, as defined by the product manager and/or the solution developers. Because solutions have different purposes and functions, the set of reports that each includes will necessarily be unique. One of the best ways to look at the reports requirement is to view it as if you were "the customer." When planning which reports to create as part of the solution, put yourself in the place of a new IT administrator, or confer with someone who can play that role.

Following are examples of questions that you can ask yourself (or someone else who is playing the role of a new IT administrator). Some of these questions pertain to a solution that includes an agent:

Important! "More" is not always "better" in terms of reports. Rather than hard-coding several reports, create reports that have changeable parameters so that one report can serve many purposes. If you provide this flexibility, the IT administrator will not have to navigate from one report to another, and the solution will have a neater appearance with a concise but thorough-enough list of reports. If you create several reports and change only a few parameters, you may be creating a list of nearly identical reports that will clutter the interface and possibly cause confusion about which report to run. Let the IT administrator set parameters to return the data that is important to him or her.


About Query Builder

In NS 7 a new interface, Query Builder (QB), has been created for producing reports. A new language has also been created to make upgrades from one NS version to another as seamless as possible: Resource Query Language (RQL). Using RQL means that customers do not have to write direct SQL queries. Instead, the graphical user interface (GUI) allows customers to select options from drop-down lists to build reports. The QB then converts the RQL into SQL for actual execution against the data in the database.

RQL was created because writing direct SQL can circumvent the security of the Symantec Management Platform. Using RQL helps preserve the security model of the Console because users do not need to write direct (raw) SQL. In addition, using RQL rather than writing direct SQL lessens upgrade issues, as using table names in direct SQL can result in customers having to review and update all reports and queries when moving from one version of NS to another. (Table names are not guaranteed to stay the same from one version of NS to the next version.)  However security can be included in ras SQL queries.  The proper statements just need to be included and by default they are included by the QB.  Queries built in SQL Enterprise manager would need to have the security enforcing code added to them.

About report data and the CMDB

Report information almost always comes from the Configuration Management Database (CMDB), which is created and maintained by the Symantec Management Platform. Each solution that relies on the Platform as its management platform should follow the Item Model and Resource Model so that the solution data is available through the standard Query Builder interface. By following the standard models inherent in the Platform, the specific data that a solution needs to create and report is already linked to the common data provided by Basic Inventory and Inventory Solution as well as data created and reported by any other conforming solution. This is a key point, as it is one of the core benefits of relying on a management platform that includes a federated CMDB. 

Another advantage: Data does not need to be duplicated by each solution. (This would occur if each solution saved its data outside the model, as other solutions would not have a standard way to look up or access this data.) Nor do solutions need to keep separate code for accessing data from each different solution in a different way. Because the data is reported and stored in a federated CMDB, the size of the database is smaller than it would otherwise be, and solutions focus on storing their critical information. It also allows solutions to easily access data and combine data from different solutions, which can provide a benefit above and beyond what each solution individually can provide. For example, the selection criteria for a software-delivery (SWD) job could include the date of the last full backup by the backup solution. If the backup had not been performed in the last day, then the software would not install. This would be (1) a check on the backup state, (2) scheduling for the software delivery, and (3) protection for the computer if the SWD had some rare, undetected interaction that could damage the computer.

As of Platform version 7.0 service pack (SP) 1, the Platform CMDB is hosted in a MS SQL 2005 database. Some of the types of data that are created and reported through the Item Object Model are as follows:

Data in the CMDB is contributed from several sources, including these:

When developing reports, avoid creating dependencies on other solutions. However, if another solution contains data that is essential to your solution, you may have to include such a dependency. In this case, include an installation-time dependency through the Symantec Installation Manager (SIM). This way, the solutions that are dependencies are installed along with the target solution, and they will be allowed to uninstall only as a package as well. If the solution in question is dependent on Network Inventory Solution, and if Network Inventory Solution is selected for uninstallation, a warning will appear stating that the solution in question must be uninstalled as well. The dependency for data could also be done on an as-available basis: If requested data exists, it is used; otherwise, a fall-back level of data is used, or the report states that the data is not available. Another option is to use a policy to hide or disable the report until the dependent data is available or the solution is loaded.

Some of the data generating components/solutions of or for the Platform are fee based, and others are free of charge. Cost can be a deciding factor when determining solution interdependencies. These are the components/solutions that are free of charge, as of NS 7.0 SP1:

Most other solutions require a license, as they do not separate any inventory or event data functionality they have from the NS Core functionality. Few run by default; so, although they are free of charge, users may need guidance about how to set them up or enable them either through a new or existing wizard or documentation item in order to have their data included in the CMDB.

The next section details how to implement reports in your solution.

Implementing reports

Two main types of reports are available: Resource and SQL. Resource reports report on resources, but they also use the resource query language (RQL). SQL reports can report on anything in the database (whether it is a resource, an item, SQL management data itself, or anythng else in the database or accessible by SQL). Details are at in the video titled "The Different Report Types."

Following is an outline of the major steps involved in incorporating reporting into a solution:

  1. Select the resource types to report on.
    1. From the Query tab, select the resource types.
    2. Add items to the base query by selecting Actions or right-clicking the Base Query.
    3. Add other resources through resource type associations (details are in the Training section of the Portal, in the "02-Using-Resource-Associations" video).
    4. From the Query tab, select the fields/columns of data. To do this, you can use either the sub-tab Fields or select the action Use Fields and Data Class Attributes. (They go to the same control. This control is a drop-down list of all the data class columns available for the resource types selected. Even third-party dataclass columns are available as long as they have done their integration properly.)

      Note: This is a search-select control type that will filter the list of items shown by what is typed in the box. It does a search in the string (not just matching from the front of the string), so if the Data_Class.Data_Column contains the sub-string "tcpip," typing "tcpip" in the drop-down box will return a filtered list that includes any column with "tcpip" anywhere in the name string of that column. Details for this step are in the video titled "Introduction to QB" (at 
  2. Filter the results. Just selecting columns to include does not usually return the desired results. Often you have to filter the query to narrow the results to exactly the computers you want to report on. For example, very few (if any) actions can be run exactly the same way on any of the most common desktop operating systems (Windows, Linux, and Mac). So, when among all possible resources you want to find PCs on which to run a specific command, you will probably have to filter the results to show a specific operating system and sometimes even a specific HF or SP version of that OS.
    1. To filter results, click Data Source > Filter Expressions.
    2. Add filters. Filters act the same as the "where" clause in a SQL query. The filter builder has two modes: Simple and Advanced. In the Advanced mode, you can incorporate parameters that the person running the report can change. See the video titled "Using Filters" for details.
    3. Create parameters. Parameters are values that can be pre-set or can be adjusted by the report user when he or she runs or re-runs the report. Including parameters in a report allows administrators to create fewer reports. They can create generic reports and then choose the parameters that will filter the results to return exactly the result set the user desires. Users can simply select parameters from a list of options or click check boxes. They do not need to learn all of the details about creating reports. Instead, with the simple options presented by the paramters created by an administrator (for the report they are using), they can apply filtering to the results in a specific manner to return the results they want.
  3. Use parameters. Parameters exist in several locations in a report.
    1. First they exist in the Data Source. From the Query Parameters sub-tab, you can add new parameters to the query.
      Note: Some parameter templates are listed under the Add section. See the Platform documentation for more information. The parameters entered here are the parameters incorporated into the database query. Note also that parameters entered in the Data Source are then available in the next location, the Report Parameters.
    2. Parameters also exist under the Report Parameter tab. The parameters listed here are those displayed to the report user and are the parameters he or she can select. (Of course those parameters are almost always used in the query; otherwise, they wouldn't be listed.).  The values selected in the Report Parameters are passed to the Query parameters and incorporated in the SQL query.  Parameters can also be passed to drill-down reports.  That is why they must match on name.  As mentioned before, parameters created in the query section are available for selection in the Report Parameter section.  Why don't Query Parameters automatically appear as a Query Parameter?  They need to be configured in the Report Parameter section above and beyond what is available in the Query Parameters section.  The configuration is the data/options which are displayed/available in the Report Parameter and where they are obtained from [static list, query, etc] and how it is displayed.  Details on how to do this are given in the videos "Using Parameters" and "Query Based Parameters"
    3. Validating input for parameters.  It may be necessary to validate user input of the report parameter.  An example could be "the Int value must be larger than 10, if not alert user and do not allow to proceed."  If this is the requirement (preventing the user from entering an invalid value) then creating or customizing a parameter value edit control would be the best option.
      1. There is an option on report parameters for a "ValueValidator".  But this has been developed for use when running Reports from Webservice calls.  The current value of the Parameter will be checked against the ValueValidator (and the specified range/checks) at the Server in the process of running the Report. If one or more of the checks fail then the Report will not run. Note: this operates completely at the server side as this feature was intended to validate irrespective of UI.
      2. Drilldown reports are a specific case where ValueValidation has been co-opted to assist in parameterizing the visibility of the controls. One reason is that a drilldown report may have have dynamic SQL which changes the results substantially depending on a parameter value to the point where some of the parameters no longer apply and thus should not be shown. However, ParameterValueValidators were initially designed to be used at the parameter level in conjunction with the ValueProvider/ParameterValueEditControl. So move the <valueValidation> node out of <visibility> and at the same level as the <valueProvider> node for normal functionality.
  4. Format the report.
    1. There are three main options for formatting a report: Grid, Chart, and Fre-form text.  These options are available in the Views tab along which many parameters which can effect them.
    2. A new and interesting option is the ability to display items other than data in the Grid format.  Values can be replaced with icons for example.  Please see the videos "Grid Formatting Rules" and "Grid Formatting Templating."
  5. Test and optimize reports.
    1. Having a well-populated database allows for more through testing of reports and the performance they will have when used in a production environment.  Of course just testing on a development system with only a few resources will not identify issues that would cause reports to run slowly, unless the issue is really bad to begin with.  Databases can be populated with the SimAgent.  See links for this in the Wiki.
    2. If issues are identified there are several steps which can help.  Copy the resolved query into the Query Analyzer and run with the option under Query for Include Actual Execution plan.  This shows where the longest/most expensive parts of the query are.  It does however require SQL knowledge (or some good Google searching) to know how to change the query to alleviate these issues.

Creating reports

Create reports in the Console user interface (UI) because of its advanced query-builder tools. After creating a report, you can export it or view it as XML by right-clicking the report as shown in the tree on the left-hand side of the Console. Then, copy your report into Reports.config after exporting the XML from the Console. (If you prefer, you can create a standalone Report Project to contain your reports. If you create a standalone report project, that project will create a product MSI of its own.)

Note: Some parts of the XML need to be removed from the version given by either "Export" or "View as XML" to make it generic so that when it loads as part of the solution everything in the report will work properly. A known issue with the "View as XML" option is that the plus (+) and minus (-) signs get into the copy-and-paste function and have to be removed. For this reason, "Export" is probaby the best option.

Please see the topic Creating Items in the Console. Although this may seem to be a more complicated method or workaround, it is the best and fastest way to create reports. These topics illustrate the recommended method for creating reports and shows how Core team for the Symantec Management Platform creates them. The reason for following their method is that so many tags are part of a report, so coding or filling them in by hand is very time-consuming and the potential for missing tags is high. Creating reports through the Console ensures that all of the necessary tags are placed where they need to be. The Platform framework for reports creates the entire XML when do it through the Console UI. No known exceptions to this rule exist. The main items to remove are the Security, Localization, and sections that identify the owner, origin, or source NS. After stripping the unneeded sections of XML, copy and paste the remaining XML into your configuration files in the solution.

Designing reports

Good examples of reports can be found in the base NS or in other solutions. In the root of the solution of NS, (\Program files\Altiris\Notification Server or \Program files\Altiris\... other), look in the \Config directory. You should see a .config file with Reports in the name. This file usually contains the XML for all of the reports that are loaded by the core NS (or the solution) exactly as is it loaded into the database. For a new solution, you should configure the XML in the same way as you find it configured in the base NS or in other published solutions.

The following is a simple (short) report XML.


- <item guid="{0535d3cf-a809-4159-b915-04748ece3142}" classGuid="{a968a2a6-c9b9-483b-b9e0-7f0b199f9da3}"> - <!--   Type: Altiris.Reporting.ReportManagementItem    --> - <!--   Assembly: Altiris.Reporting, Version=7.0.4739.0, Culture=neutral, PublicKeyToken=d516cb311cfb6e4f    -->   <name>Agent Version</name>   <alias />   <productGuid>{d0e33520-c160-11d2-8612-00104b74a9df}</productGuid>   <itemAttributes>NoReplication, Readonly</itemAttributes> - <report> - <implementation classGuid="71207142-7e58-41af-85f8-9080dd4b6ffe"> - <customAttributes> - <reserved>   <type>Altiris.Reporting.StandardSQLReport</type>   <assembly>Altiris.Reporting, Version=7.0.4739.0, Culture=neutral, PublicKeyToken=d516cb311cfb6e4f</assembly>   </reserved>   </customAttributes> - <configuration isScoped="True" isSnapshotMode="False"> - <dataPresentations> - <dataPresentation key="view"> - <implementation classGuid="5701f69d-820e-4da4-a047-91b32fdf9a3c">   <customAttributes /> - <configuration> - <base> - <id visible="True"> - <![CDATA[ view   ]]>   </id> - <name> - <![CDATA[ DefaultDataView   ]]>   </name>   </base> - <grid>   <hiddenColumns />   </grid>   </configuration>   </implementation>   </dataPresentation>   </dataPresentations> - <parameters> - <parameter>   <name>ClientPkgBuild</name>   <description>ClientPkgBuild</description>   <required>true</required>   <nullable>false</nullable>   <parameterTypeGuid>89cd55bd-fad5-4e81-92a7-b763ec46742a</parameterTypeGuid>   <testValue>0</testValue>   <defaultValue>0</defaultValue>   <order>1</order> - <valueProvider classGuid="920c4d59-b5ce-4cb4-945e-3a03b31dc194"> - <configuration>   <registryPath>\eXpress\NS Client Package\version</registryPath>   </configuration>   </valueProvider>   <requiredParameters />   <configurationControlClassGuid>73bded50-f1aa-4ff4-a80e-a6c9e047d472</configurationControlClassGuid>   </parameter>   </parameters> - <dataSource guid="7e7d0a0b-4e1f-46be-9094-888513b9b8bf" embed="True"> - <item guid="{7e7d0a0b-4e1f-46be-9094-888513b9b8bf}" classGuid="{aa232a71-e633-4f4a-a48f-bcccc7535269}"> - <!--   Type: Altiris.Reporting.DataSource.DataSourceManagementItem    --> - <!--   Assembly: Altiris.Reporting, Version=7.0.4739.0, Culture=neutral, PublicKeyToken=d516cb311cfb6e4f    -->   <name>Agent Version Query</name>   <alias />   <ownerNSGuid>{64ae1305-2a19-45c2-a16a-0905e864b121}</ownerNSGuid>   <productGuid>{d0e33520-c160-11d2-8612-00104b74a9df}</productGuid>   <itemAttributes>Hidden, NoReplication, Readonly</itemAttributes> - <dataSource> - <implementation classGuid="b29ba3f7-cc80-4988-a341-d8471b05ea1d"> - <customAttributes> - <reserved>   <type>Altiris.Reporting.DataSource.RawSqlDataSource</type>   <assembly>Altiris.Reporting.DataSource, Version=7.0.4739.0, Culture=neutral, PublicKeyToken=d516cb311cfb6e4f</assembly>   </reserved>   </customAttributes> - <configuration> - <base> - <scope> - <scopingFields>   <scopingField>_ItemGuid</scopingField>   </scopingFields>   </scope> - <parameters> - <parameter>   <name>ClientPkgBuild</name>   <description>ClientPkgBuild</description>   <required>true</required>   <nullable>false</nullable>   <parameterTypeGuid>89cd55bd-fad5-4e81-92a7-b763ec46742a</parameterTypeGuid>   <testValue>0</testValue>   <defaultValue>0</defaultValue>   <order>10</order>   <requiredParameters />   <configurationControlClassGuid>73bded50-f1aa-4ff4-a80e-a6c9e047d472</configurationControlClassGuid>   </parameter> - <parameter>   <name>TrusteeScope</name>   <description>Scoping Parameter</description>   <required>true</required>   <nullable>false</nullable>   <parameterType>PType-ScopeTrusteeList</parameterType>   <testValue>S-1-1-0,S-1-5-21-1245139182-1733588159-312552118-58345,S-1-5-21-1390067357-117609710-839522115-1013</testValue>   <order>10</order> - <valueProvider classType="Altiris.Reporting.Parameters.ParameterValueProviders.CurrentIDMembershipValueProvider">   <configuration />   </valueProvider>   <requiredParameters />   <configurationControlClassGuid>73bded50-f1aa-4ff4-a80e-a6c9e047d472</configurationControlClassGuid>   </parameter>   </parameters>   </base> - <query> - <![CDATA[ DECLARE @v1_TrusteeScope varchar(99)    SET @v1_TrusteeScope = '%TrusteeScope%'

select [Product Version] as 'Agent Version',  Count( distinct CAST(vc.[Guid] AS NVARCHAR(50)) ) as 'Count',  '%ClientPkgBuild%' as 'Staged Altiris Agent Build' from Inv_AeX_AC_Client_Agent DApps INNER JOIN vComputerResource vc on DApps._ResourceGuid = vc.Guid INNER JOIN [fnGetTrusteeScopedResources](@v1_TrusteeScope) AS [fnGTSR_3]          ON vc.Guid = [fnGTSR_3].[ResourceGuid] where upper([Agent Name]) in ( 'ALTIRIS EXPRESS NS CLIENT', 'ALTIRIS AGENT', 'ALTIRIS AGENT FOR UNIX AND LINUX', 'ALTIRIS AGENT FOR MAC' ) group by [Product Version]
  ]]>   </query>   </configuration>   </implementation>   </dataSource>   <parentFolderGuid>6c27551d-5251-4ee6-8c50-32c438e3bb9e</parentFolderGuid>   <sourceNS guid="{64ae1305-2a19-45c2-a16a-0905e864b121}" name="NSVM1" url="http://NSVM1/Altiris/NS/" /> - <security owner="@APPLICATION_ID" inherit="True"> - <aces> - <ace type="reserved" name="@APPLICATION_ID"> - <permissionGrants>   <permissionGrant guid="{eca6254f-5017-4730-9b3f-5add230829b7}" name="Delete" />   <permissionGrant guid="{983a2d22-7a82-4db0-a707-52c7d6b1441e}" name="Read" />   <permissionGrant guid="{ac296df1-eb40-4592-899f-25d5c07d45f6}" name="Write" />   <permissionGrant guid="{819dae1e-b1a5-4643-81a1-26ef95feb8a8}" name="Change Permissions" />   <permissionGrant guid="{726b1c09-7108-450d-ae24-5f8e93135ed6}" name="Clone" />   <permissionGrant guid="{4ddc04c3-f0a5-4e88-84aa-c44c8c5ebcc4}" name="Read Permissions" />   </permissionGrants>   </ace>   </aces>   </security>   <itemReferences />   </item>   </dataSource> - <contextMenus> - <contextMenu key="ItemMenu"> - <implementation classGuid="46e1a3a9-52f1-4e57-b2b0-83d2bf80394e">   <customAttributes /> - <configuration>   <itemGuidField showResourceTools="False">_ItemGuid</itemGuidField>   </configuration>   </implementation>   </contextMenu> - <contextMenu key="LinkMenu"> - <implementation classGuid="bb9fb2dc-74a5-4cb1-9fdd-0801d7b1cf47">   <customAttributes />   <configuration />   </implementation>   </contextMenu>   </contextMenus>   </configuration>   </implementation> - <viewingControl> - <implementation classGuid="a967db13-cd5f-4246-8fc1-29959ee5046f">   <customAttributes /> - <configuration> - <base> - <id> - <![CDATA[ DefaultReportView   ]]>   </id> - <linking> - <links> - <link id="Link1" name="Details" sourceId="view" targetId="DefaultReportView" event="Select"> - <action id="Drilldown"> - <arguments> - <argument name="MoveToReport"> - <![CDATA[ 4f24e69a-07ee-4ac6-a3c4-9321aaa6bdd5   ]]>   </argument>   </arguments>   </action> - <parameterMappings>   <map sourceParameter="SelectedRow[Agent Version]" destinationParameter="AgentVersion" destinationTypeAlias="ptype-string" />   </parameterMappings>   </link> - <link id="ShowContextMenu" visible="false" name="Context menu" sourceId="view" targetId="DefaultReportView" event="ContextMenu"> - <action id="ContextMenu"> - <arguments> - <argument name="MenuFactories" list="true">   <value>LinkMenu</value>   </argument>   </arguments>   </action>   <parameterMappings />   </link>   </links>   </linking>   </base>   </configuration>   </implementation>   </viewingControl>   </report>   <requiredItems />   <parentFolderGuid>6c27551d-5251-4ee6-8c50-32c438e3bb9e</parentFolderGuid> - <itemReferences>   <itemReference guid="{7e7d0a0b-4e1f-46be-9094-888513b9b8bf}" hint="report datasource" type="RelatedChild" />   </itemReferences>   </item>

To see some short, relevant videos about specific areas of creating reports in NS 7, please click the Training tab from the Developer Portal and look at the section labeled NS Reporting. These videos were produced by the development manager with responsibility over the new Query framework (which includes the RQL and the new graphical user interface for Report/Filter Builder). Here is the link:


Scoping reports

When creating reports that display resource data, consider whether the results of the report should be scoped. To scope the results of a report is to limit its results to include only those resources to which the user running the report has access through the Organizational Groups and Organizational Views.

Use the Reports.config file to define reports in the Console, and follow the guidelines below to provide full reporting functionality (including scoping) to customers. Note that if you fail to support scoping, this omission will show up during testing in the Symantec Product Quality Labs, with remediation possibly causing your schedule to slip or creating other complications.

Again, your solution's report items must support scoping. Scoping allows the user (IT Administrator) to view resources in the report (meaning resources to which he or she has access). Without support for scoping, reports will not restrict what the user can view. 

To enable report scoping, be sure to do the following:

  1. In the report's DataSource, properly define the "TrusteeScope" parameter, which is populated by the Altiris.Reporting.Parameters.ParameterValueProviders.CurrentIDMembershipValueProvider class.
  2. In the Datasource, use the value of the TrusteeScope parameter to limit its results. Do this in one of the following ways: Note that the first bulleted item lists the recommended way to limit results:

Observing best practices

Consider the ways in which users want and need to gather data. It may be that some data should be aggregated first and filtered second; other data should be filtered first and then aggregated (to improve performance, for example). Keep in mind these two primary considerations:

Optional: You can include additional parameters in the report. One useful parameter is "ScopeCollectionGuid." The "ScopeCollectionGuid" parameter will allow the user to futher filter the report based upon an Organizational Group or Organizational View to whi ch he or she has permission. (This is referred to as "filtering the results.") To see a list of additional parameters or to learn how to create your own parameters, view the Query Parameters tab in Report Builder (in the Console).     


Viewing examples of scoped reports

The best example of a scoped report, using either raw SQL or Resource Query, is obtained by simply creating a new report using the menu on the Symantec Management Console. The default versions of SQL Report and the various resource-based reports are all created with all the elements to ensure that their data is scoped.

To see an example of report filtering, see the report labeled "Scoped and Filtered Resource Report" in the NS 7.0 Example Reports folder. (If you do not have this folder, it is simply hidden. However, it contains several examples of report features and can be very useful. Although the contents of this folder are still included in the Reporting Solution, they are not imported during installation, so you must restore the folder.) Follow these steps to edit the Reporting.config file (usually installed in C:\Program Files\Altiris\Reporting\Config):

  1. In C:\Program Files\Altiris\Reporting\Config, search for the file labeled "Reporting_WIP.config."
    This configuration file will be commented.
  2. Remove the comments.
  3. Reconfigure your database, or re-import the Reporting solution using AexConfig.exe. 

Creating scoped reports through the UI

 You can create a scoped report by converting a query-based or a raw SQL report to a scoped report.

Converting resource query-based reports

To convert a non-scoped resource report to a scoped report using the Report Builder UI, follow these steps:

  1. In the Console, navigate to the Report Builder.
  2. In the Report Builder, select the report that you want to convert, and then select Edit.
  3. From the available tabs, select Data Source > Query.
  4. In the Query Tree, select the main resource node (for example, "Computer").
  5. Check the Scoped checkbox.
  6. Optional: Select any other resource types in the Query tree that should be scoped, and scope those as well.
  7. Save the report.

The report-editing UI will automatially add the appropriate Scoping Parameters to the selected report.

Converting raw SQL reports

To convert a non-raw SQL report to a scoped one using the Report Builder UI, follow these steps:

  1. In the Console, navigate to the Report Builder.
  2. In the Report Builder, select the report that you want to convert, and then select Edit.
  3. From the available tabs, select Data Source > Query Parameters.
  4. Using the Add button, add the scoping parameter and select Advanced Types/Scoping Parameter. This will add a parameter called "TrusteeScope" to the query.
  5. Click the Parameterized Query tab.
  6. Edit the SQL to add the TrusteeScope parameter to the SQL, and join using one of the scoping functions. A simple example follows.
            DECLARE @v1_TrusteeScope nvarchar(max)
        SET @v1_TrusteeScope = N'%TrusteeScope%'
        [vri2_Resource].[Guid] AS [_ItemGuid],
        [vRM_Resource_Item] AS [vri2_Resource]
           INNER JOIN [fnGetTrusteeScopedResources](@v1_TrusteeScope) AS [fnGTSR_3]
              ON [vri2_Resource].[Guid] = [fnGTSR_3].[ResourceGuid]


Creating scoped reports in XML

You can create both resource reports and raw SQL reports in XML.


Adding other scoping functionality

Scoping a report using the "TrusteeScope" parameter will limit the resources to include all resources that the user running the report has access to. However, in some cases the use may want to further restrict that list. One situation where this might be appropriate could be when the user has access to all the computers in a particular building, but they only want to see what is on one of the floors, or one of the departments.

A report can be constructed that allows the user to control which organisation groups and views that they can see. To do this from the report Builder UI add the parameter called "Advanced Types/Scope By Organisation Group Parameter" To both the Report Parameters and the Query parameters. This Parameter will be called "ScopeCollectionGuid".

For a Resource query nothing more needs to be done as just defining the "ScopeCollectionGuid" will cause it to be used automatically.

For a RawSQL report the parameter should be passed in like the TrusteeScope parameter, and then SQL adjusted to join against the CollectionMembership> table to restrict the results to match what the user selected.


Localizing reports in NS 7

This topic discusses the general process of how Reports are localized in NS7. In general the method is similar to the NS6 localization process in that the XML tags that report authors use are (where possible) the same. Additional NS7 features to localization are the ability to provide Solution/Product global localization elements.


Here is some info on how to see an actual example of the data in a report being localized. There are a couple of bugs here that will be worked out.

I found a report "Top 10 most run reports" that is in the default console. It is a graph report. It has the localization function in the SQL in it but it doesn't localize correctly out of the box because it isn't quite set up correctly. I figured out how to fix it up though.

The report is under Reports, Notification Server Management, Report History. Make a copy of the Report so you can edit it. Then edit and first under the DataSource tab (in the first level of tabs) go to the Query Parameters tab and select Add and then add Advanced Types, "Localization Key Parameter". This adds a Parameter called _culture. Saving changes I think will take you out and run the Report but it appears that is the only way to do it. If you just go to the next tab and make the changes there and then save it doesn't appear to save any of the changes. So save the changes there and then go back into edit mode. On the tab that comes up "Parameterized query" just change the 2 entries to %_culture% and save changes and I believe "Wa La" the report is localized on the data in the report.

 Update Note: possibly if you change the "Parameterized query" and click apply and then add the "Localization Key Parameter" and 
 click apply it may save in one round without having to click save changes, but if you add the "Localization Key Parameter" first
 and click apply it shows it applies but when you go to the "Parameterized query" and make the change and click apply and then go
 back to the Parameters tab the _culture parameter is not there.

How an individual report is localized

When a report is displayed, a number of elements of the reporting framework will look for strings in the database that match the strings defined in the report XML. e.g. A report might contain a column in it's result set called "System Type", when the report is run the framework will look for a string named "column.System Type" to see if there is a localized version of it, and if so it will adjust the grid's column heading to use the string returned from the database.

                                It's possible that a report has no strings in the DB (e.g. user generated reports) in this case the string is displayed as is.

There are actually 3 levels of localization that may apply to each string. The framework looks for these strings in the following order, with the first one matching being used;

  1. Strings defined in <reportLocalization> nodes on individual reports. These use the reports's guid as the string baseGuid, and a string ref like "parameter.XXX" or "tooltip.XXX".
  2. Strings defined at a product level. These use the product Guid as the baseGuid and string refs the same as for #1 above. The Framework uses the product guid defined in the report to lookup this string (if necessary).
  3. Strings defined in the NS Core. These use the internal BaseGuid and the same string ref as #1 above. This is usually used to define a global localization for Resource Data Class Columns (and potentially somoe other system level strings).

The General Processes around Report localization

Localization of a solution's reports is achieved by using an SDK language pack project. The Language pack extracts invariant strings from the reports contained in the solution, adds them to the language pack so that appropriate language specific strings can be generated for each report and translated using the polyglot database in the usual fashion.

The Process at a solution level is summarized as;

  1. A SDK Language pack project is added to the Solution (it should be already).
  2. Modify the Language Pack Project to ensure that the config file "Language-independent Files/XXX.ReportingStrings.config" is added to the main language pack Product config file.
  3. Reports requiring Localization are identified.
  4. <reportlocalization> nodes are added to the reports, containing the invariant strings for that report.
  5. Any product wide report localisation strings are added to the solution's "XXX_Strings.config" file
  6. Run the Language Packs's "Extract Invariant Strings" from the context menu.
  7. Run the Language Pack's "Update Language Dependant Files" from the context menu.
  8. Import the Language pack to get the invariant and language dependent strings in the DB.

Important Note: its important to note that the invariant strings in <reportLocalization> nodes are not imported when reports are imported. The generated invariant strings should be added to the LanguagePack project. Likewise when testing individual reports, the Language pack menus should be used to generate and import strings.

Product Wide Report Localization

Many reports in a solution could us the same strings across it's reports (e.g. Asset might use a column called "Asset Status" in all it's report). To make Solution level localization easier any string not found in a <reportLocalization> node (which uses the Reports Guid) is also looked for in the DB using the Product's Guid.

Supported reportLocalization string nodes

node name Generated String Ref Description XML example
parameter parameter.XXX Used to localize parameter descriptions which are used to label parameters <parameter>Software</parameter>
listitem listitem.XXX Used to localize static parameter list items for drop down list parameters <listitem>Windows</listitem>
tooltip tooltip.XXX used to localise any Report elemts with static tooltips (e.g. Parameters, charts) <tooltip>A second tier operating system</tooltip>
label label.XXX Used to localize static labels in parameter layout tables. <label>OS Type</label>
legend legend.XXX Used to localize the legend of charts <legend>Agent types</legend>
charttitle charttitle.XXX Used to localise the Titles (main and axis) of titles <chartTitle>Agent Usage</chartTitle>
drilldown drilldown.XXX Used to localize Report Drilldown strigns that appear in the context menu <drilldown>Open Google</drilldown>

Note - The values used in charttitle are used to localize both the Chart Title and the X Axis & Y Axis.

If those have different values, just make sure there is an entry for each. 


      <culture name="">
        <parameter>From Date</parameter>
        <parameter>To Date</parameter>
        <parameter>Filter by solution</parameter>
        <ChartTitle>My Report</ChartTitle>
        <ChartTitle>My X Report axis</ChartTitle>
        <ChartTitle>My Y Report axis</ChartTitle>
        <legend>My Report Legend</legend>

To add this type of localization string to a Solution add the string to the Solutions "XXX.Strings.config" file as per the following example;

     <!-- Test for report localization at a product level-->
     <string baseGuid="PUT-YOUR-PRODUCR-GUID-HERE" stringRef="listitem.All" culture="" string="All" />
     <string baseGuid="PUT-YOUR-PRODUCR-GUID-HERE" stringRef="listitem.Unix" culture="" string="Unix" />
     <string baseGuid="PUT-YOUR-PRODUCR-GUID-HERE" stringRef="parameter.System Type" culture="" string="System Type" />

Strings added as static strings to a solution are picked up by the Language Pack's "Extract Invariant Strings" as usual.

What to localize in a report

Report Name
Report Description
Parameter Name
Parameter Description
Parameter List Value
Column Name
Data Value

What needs to be changed in the Report XML

This report <item> would have a child node called <reportLocalization>. The invariant or empty culture can contain a list of all columns, parameters, listitems tooltips labels graphs etc.

So if it had report had

<item guid="{4dd28c8a-7d44-40ca-995b-803a23dcb180}">
    <name>DS I18N Demo - Report</name>
    <description>This is a testing report demonstrating the I18N</description>
        <culture name="">
            <name>DS I18N Demo - Report</name>
            <description>This is a testing report demonstrating the I18N</description>
        <culture name="">

The strings generated by the Language Pack

The SDK parser would create the following strings in the Language Pack:

  <string baseGuid="4dd28c8a-7d44-40ca-995b-803a23dcb180" stringRef="" culture="" string="DS I18N Demo - Report" />
  <string baseGuid="4dd28c8a-7d44-40ca-995b-803a23dcb180" stringRef="item.description" culture="" string="This is a testing report demonstrating the I18N" />
  <string baseGuid="4dd28c8a-7d44-40ca-995b-803a23dcb180" stringRef="parameter.Software" culture="" string="Software" />
  <string baseGuid="4dd28c8a-7d44-40ca-995b-803a23dcb180" stringRef="parameter.Company" culture="" string="Company" />
  <string baseGuid="4dd28c8a-7d44-40ca-995b-803a23dcb180" stringRef="listitem.All" culture="" string="All" />
  <string baseGuid="4dd28c8a-7d44-40ca-995b-803a23dcb180" stringRef="listitem.Microsoft" culture="" string="Microsoft" />
  <string baseGuid="4dd28c8a-7d44-40ca-995b-803a23dcb180" stringRef="listitem.Altiris" culture="" string="Altiris" />
  <string baseGuid="4dd28c8a-7d44-40ca-995b-803a23dcb180" stringRef="column.Name" culture="" string="Name" />
  <string baseGuid="4dd28c8a-7d44-40ca-995b-803a23dcb180" stringRef="column.Version" culture="" string="Version" />
  <string baseGuid="4dd28c8a-7d44-40ca-995b-803a23dcb180" stringRef="column.Company" culture="" string="Company" />