Serge's Technology View

Talk about Technologies, Software Architecture and Management

Posts Tagged ‘crystal reports 2008’

Crystal Reports 2008 : hacking datetime parameter format – reloaded

Few weeks ago I have wrote on how to hack Crystal Reports 2008 ASP.Net Viewer control to suppress time part in the parameter calendar control.

With release of Service Pack 1 for Crystal Reports 2008, suggested solution no longer works since structure of the files has been changed.

So I went digging around again. Forgot to mention last time, but in situations like this, scripting debugging supported in Visual Studio really helps (if you are not familiar with JS debugging check following links [1] [2] for more info.

Note. It is interesting to observe how code is changing over time. And after some analisys, I would say that SAP development team is one click away from adding ability to suppress time parts for datetime parameters: only one thing missing – new property on parameter level which would allow specify how to treat it (date, time or datetime). Question is if they will decide to do so.

I will be using Visual Studio 2008 and run against my WebDev.WebServer.

After creating simple CrystalReports ASP.Net application with report which has datetime parameter, lets see what exactly is happening here.

Step 1 Step 2

Let’s run an application up to the point when engine would request parameter values being entered (Img 1).

And then let’s open Solution Explorer in Visual Studio (Img 2).
You would notice a few JavaScript files, where one we were looking for - promptengine_calendar2.js.

While having page open, dbl-click on the file in Solution Explorer and look around. (In my case actual file location is C:\Windows\Microsoft.NET\Framework\v2.0.50727\ASP.NETClientFiles\crystalreportviewers12\prompting\js\, but may vary.)

Internal Calendar control (which reside in Calendar.js file) relay on setShowTime method to manage visibility and behaviour of the calendar and this is where we will “hack” our way in.

As usual code below only highlights changes to the code in promptengine_calendar2.js file.
This time I am making no changes to the data, only how it is displayed and extracted from the calendar control. And it seems to work much better then prior solution.
Make sure you have the copy of original file backed up.

/** First, lets add one more variable to control data flow **/
    bobj.prompt.Calendar = function
    ...
       this.isDateTimeData = false;
    }
...
    /** While suppressing DateTime format we still need to know original type of the data **/
    setIsDateTime : function(isDateTime) {
       // this.isDateTime = isDateTime;
       this.isDateTimeData = isDateTime;
       this.isDateTime = false;
    },
...
    /** while suppressing time part, it is still need to be returned back in to parameter form **/
    _getStringValue : function(dateValue) {
        var format = this.isDateTime ? this.dateTimeFormat : this.dateFormat;

        if ((!this.isDateTime) & this.isDateTimeData) {
                format = format + ' 00:00:00';
        }

        return  bobj.external.date.formatDate(dateValue, format);     
       
    },

Changes are very isolated and allows a) hide time entry box and b) properly return data back into parameter form.

This solution is generic and applies to all datetime parameters visible. As a result, calendar control become for date entry only, while resetting time portion. User can still enter time part if necessary, but on the page level.

Again, make sure that file with changes we just made is replaced everywhere. Depend on your development and production environment you may have few other locations for it.

Crystal Reports 2008, ASP.Net and impersonation

We have created our perfect reporting solution using Crystal Reports 2008 viewer control, tested everything, and  deployed it into production environment… and it is working… until Friday night… :(

Information below is provided for both IIS 6 and IIS 7 along with 32 and 64 bit Windows environment. Make sure that proper reference is used.

For some strange reasons, things usually happen when nobody anticipate it anymore (usually about a week after an initial deployment).
In addition, Project creep situation may occurs: after usual management meeting, requirements are changed and some security measures are to be introduced.

Easy! <IMPERSONATE> option of ASP.Net… and this is where it become interesting.

There is slight small issue, locally developer is usually an administrator of the machine, where in production, s/he just regular user.

More testing… everything would be fine in development infrastructure and not cause any problems. But being released some strange errors may occur.

Examples:

  • “Load Report Failed”
  • “System.Runtime.InteropServices.COMException: Invalid file name”
  • “Exception Details: System.Runtime.InteropServices.COMException: Access is denied.”

Hint: When reviewing ASP.Net Stack Trace (debug/trace mode needs to be enabled), first line may contain the following text ”CrystalDecisions … ReportClientDocumentClass.Open”.

What is going on here?

ASP.Net impersonation

In default situation, ASP.NET impersonation is turned off and the resources can be accessed using a “local system process” account. Nothing needs to be done here, since initial installation of the IIS would have addressed it.
But when impersonation is turned on, ASP.NET executes every resource using the account of a specified user who is authenticated when the user makes the request. If you specify the IUSR_machinename account to be used as the user account, then ASP.NET will behave like previous versions of ASP, in providing access to the resources (more).

IIS impersonates users with its own IUSR account.
In the case of ASP.NET, impersonation is used to decide whether the user’s request should be executed using the account of the requested user, or that of a local system-process account that ASP.NET uses for anonymous requests.

There are some rules applied when combination of impersonation and anonymous access is used in ASP.Net application:

  1. Impersonation is enabled:
    • Anonymous access is enabled in IIS - the request is made using the IUSR_machinename account.
    • Anonymous access is disabled in IIS - the request is made using the account of the authenticated user.
  2. Impersonation is disabled:
    • Anonymous access is enabled in IIS – the request is made using the system-level process account.
    • Anonymous access is disabled in IIS - the request is made using the account of the authenticated user.
  3. In either case - permissions for the account are checked in the Windows Access Control List (ACL) for the resource(s) that a user requests, and a resource is only available if the account they are running under is valid for that resource.

Lets assume that the following settings are used

<system.web>
  <identity impersonate="true" />
 <!-- WS: Allow only Authenticated users -->
 <authorization>
 <!-- allow users="*"/ -->
    <deny users="?" />
  </authorization>
</system.web>

In this mode ASP.NET impersonates the current Web user. It gets this token from IIS which passes this account token on the ISAPI thread that originally fires off this request.

We can go further and impersonate the process directly by specifying its identity:

<identity impersonate="true" password="password" userName="username" />

In this case access to any resource would be performed in the context of the user specified, instead of user associated with the session.
To ensure the proper context, it can be verified with the following code:

// Returns the security identity of the current running thread
System.Security.Principal.WindowsIdentity.GetCurrent().Name

// Returns the identity of the user which session is belong to
WindowsIdentity.GetCurrent().Name

As you can see, we need to ensure that all accounts involved have sufficient rights to access resources involved.

Before going further, check if including an impersonation account in the default IIS_WPG user group would be sufficient before setting more complex scenario.

Crystal Reports effect

Being an insight process, Crystal Reports engine would also require access to some additional file resources:

  1. Location of the report files
  2. Local TEMP folder as described below

Why User TEMP folders is involved? Why would Crystal Reports control in IIS need to access it?

Short answer – because CR engine keeps cache of report files for the session.
Do a little experiment, without impersonation enabled, check Temp folders when report is visible in the Viewer.
You would notice files appear and disappear there:

  • <Report Name> {GUID}.rpt is a cache of the report file for the session
  • ~cpe{GUID}.rpt is a cache of the report data view

The location of TEMP folder may vary: C:\WINDOWS\Temp for older versions of Windows, or more elaborate ”C:\Documents and Settings\…” and “C:\Users\…“ in latest versions.
And in case of user account specific variation, one would have to guess which user related folder has to checked.  With impersonation enabled and finding context of the call, we can now properly determine the location and required access level:

  • Associated account should be allowed create/modify/delete files in TEMP folder.
  • For IIS 7.0, Temp folder location would be different.
    Proper default location would be %windir%\serviceprofiles\networkservice\AppData\Local\Temp as described here.

Limit CR Engine access to TEMP folder

 Described is default behavior, which could be adjusted to limit access to more relevant location.

Visit the following location:

HKEY_LOCAL_MACHINE\SOFTWARE\Business Objects\Suite 12.0\Report Application Server\InprocServer

or in case of 64 bit Vista (not being familiar at first with new registry structure you may be surprised about this)

HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Business Objects\Suite 12.0\Report Application Server\InprocServer

then add/update the following value

TempDir: String = “your folder”

This will tell engine which folder to use. And then by granting proper permissions as discussed above it would solve the grand problem. Restart your web server and you should be good to go.

To validate that account has proper permissions for the folder specified, the following command can be used

CACLS * /T > output.txt
being executed from command prompt it will create output.txt which contains list of permissions for the current folder

Notes:

  1. Solution above can be used for any prior version of Crystal Reports, but may require minor adjustments.
  2. Problem with permissions could also cause broken image links in the Viewer
  3. Depend on configuration, permissions could be required for NETWORK SERVICE account and/or IIS_WPG group.

Crystal Reports 2008 : hacking datetime parameter format

One would think that this should be a no-brainer : ability to specify an edit format for date/time parameter in Crystal Reports. Not so fast…

Problem is as following:

ASP.Net Web client with Crystal Reports Viewer control is used.

When our report is based of some stored procedure which uses datetime parameter, it will inherit it as is and when report parameter entry form is displayed we would be asked to enter both date and time portion.

While, in general, it is OK, some reports are really interested only in date part being entered and time should be always set to 00:00:00. So we are forced to type time every time because if it is not provided calendar control would try to set time part initially to current time.

After some research off the Internet, visiting SAP forums, it is appear to be engine limitation. But we would want to overcome it somehow.

DISCLAIMER: solution below could only be used as a last resort and only if your business logic requires using date only params. And while it is only applies to calendar control, it is not per se a generic solution. This is a first “rough” attempt of achieving desired result and may lack some features otherwise expected.

It has been reported that solution above only works for current month. Since we are now using Crystal Reports 2008 with SP1, I would address this issue in my new post below.

IMPORTANT! With release of Service Pack 1 for Crystal Reports 2008, method blow is no longer applicable since structure of the files has changed. Please refer to this new post for more information.

Otherwise, Where there is a will, there is a way…

Fortunately we have access to internals behind the parameter handlers in Crystal Report Viewer web control.

Navigate to one of following locations:

  • C:\Inetpub\wwwroot\aspnet_client\system_web\2_0_50727\crystalreportviewers12\
  • C:\windows\Microsoft.NET\Framework\v2.0.50727\ASP.NETClientFiles\crystalreportviewers12\
  • C:\Program Files\Business Objects\Common\4.0\crystalreportviewers12\

and locate the file called allInOne.js – this is our victim. This file contains all JS code behind for CRV control which would be used by your web-site.

IMPORTANT: always create a backup copy before making any modifications.

(more…)

How to deploy Crystal Reports 2008 project – part 2

Introduction

From part 1 of this article, you got list of steps in order to deploy Crystal Reports 2008 project created in Visual Studio 2008.

Next step is to choose deployment strategy, prepare installation script and then install it on IIS server.
There is enough written about deployment process from within Visual Studio so let’s give some people credit for their work - for example, please check this article – I am going to use it as a base.

All things considered there is still a variation to that process specific to Crystal Reports.

Note: Make sure you have latest runtime available for you – visit SAP download page - as of 10/19/2009 runtime version available is 12.2 .

(more…)

Valid XHTML 1.0 Transitional  Valid CSS!