Monday, July 28, 2014

Is your Business Objects Server running at CPU 99% load?


Today the Business Object server was running like a dog, checking the performance showed that the server was eating up 99% CPU at all times.  The problem turned out to be related to the Index Service running continually rather than on a scheduled basis.

Steps to address the where:

1. Login to CMC

2. Click on Application, Right click Platform Search Application>Properties

3. In Crawling frequency, select #Scheduled crawling#

4. In Level of indexing, select #Platform and Document Metadata#. (Optional, platform search application will index faster)

5. In Content Types, uncheck #Universe#. (Optional, platform search application will index faster)

6. In Error Recovery, check #Rebuild index#

7. Save and Close

8. Go to Folder>Platform Search Scheduling, schedule the Platform Search Scheduling object to be done when times when there is a lower usage of the resources

Monday, July 21, 2014

Changing the collation of a SQL Server database

If a SQL Server instance has been created using the wrong default collation, it can be a bit of a pain if you try to access the TempDB.

Luckily there is a way to fix this.

1) Logon to the server

2) Backup all the existing database (Note: The collections of existing databases won’t change on the system DBs and any new User database created using the default collation!)

3) Delete/Remove any existing database; this is not specifically needed, but it’s not a bad idea as it will confirm that you have a backup.

4) Open a command window with elevated permissions.

5) Go to the default SQL Server installation directory by typing:
cd C:\Program Files\Microsoft SQL Server\100\Setup Bootstrap\SQLServer2008R2

6) Enter the following command:

Setup /QUIET /ACTION=REBUILDDATABASE /INSTANCENAME=MSSQLSERVER /SQLSYSADMINACCOUNTS=WOODGROUP\GG-EPF-AU-BSG-ADMINS "NT AUTHORITY\NETWORK SERVICE" "NT AUTHORITY\SYSTEM" "NT SERVICE\MSSQLSERVER" "NT SERVICE\SQLSERVERAGENT" /SAPWD=<password>.1 /SQLCOLLATION=SQL_Latin1_General_CP1_CI_AS

Note; /INSTANCENAME=MSSQLSERVER is the name of the default instance

Important: “/SQLCOLLATION=SQL_Latin1_General_CP1_CI_AS” was just chosen at random

7) Restore the backup databases.

Monday, May 19, 2014

Adventures with hMailServer

Today I was asked to create a testing mail server; something that can read email from a test webapp and redirect it to another account.  This allows developers to see how a test web application send/receives mail without having all the overhead of changing the settings in the database.

 

Installing HMailServer

Get the software from out share: \\ap-nas-isln-01\Data-WGPSN-AU-Perth\EPF\BSG\Downloads\Hmail or from the official website :  http://www.hmailserver.com/index.php?page=download

Copy the install file to your server.

Run hMailServer-5.4.1-B1951.exe (or whatever version you use)

image

Click Next / Accept the licence agreement and click Next

image

Pick the default installation location (or another if needed).image

Choose “Full Installation” and Click Next

image

Choose “External database” click Next. and Next Again

image

Enter an admin password (e.g. Pa55word ) and Click Next

Click Install.

image

Enter the password again and Click OK

image

Click Next

image

Create a “New” database on first install of choose an existing one if required.  Click “Next”

image

I’m using SQL Server so I picked that and clicked Next.

image

Enter the server connection details; I used a Windows authentication account as the <DOMAIN>\<ServerName>$ account had access to the SQL Server.  Click Next and Next again… Next Again to Finish and then Close.

image

You should see the message above.

Configuring HMailServer

First thing you’ll see will be the Admin connection window.

image

Double click the “Localhost” entry.

image

Click “Add domain”

image

Enter the domain name you wish to use and click “Save”.

Expand the “Accounts” node and click “Add”

image

Add a User and Password for testing and click Save.

image

Expand the “Setting\Advanced\Auto-ban” node and uncheck Auto-ban.  (I do this because I’m running the system on the same machine as my webapps).

Click Save and then Exit.

Uninstalling HMailServer

Click Start/hMailServer/Installation/Uninstall hMailServer

Click “Yes” that you are sure you wish to remove the component.

Click OK.

Note: This will not remove the external SQL database (if you used one). Use SQL Manager to do that step.

Also I’d advise removing the folder from the server as the INI settings are left on the server, in case you every reinstall.

Connecting up your outlook account

Start Outlook

image

Choose File/Add Account and click “Manually Configure server settings” click Next.

Choose “Internet Email” and click Next

image

Enter the various details as required, being sure to select “IMAP” as the Account Type.  Also the Username should be FDN (e.g. test@domain.com) then click : “More Settings…”

image

In the “Outgoing Server” tab select “My outgoing SMTP requires Authentication and select “Use same settings ad my incoming mail server”.  Click OK

image

You should see the above if everything went well.

Monday, April 28, 2014

Configuring Business Objects Explorer for SSO

I had a few issues with configuring a Business Objects Server this morning for integration with Single-Sign-On.  For some reason the changes I made in the configurations just did not seem to work correctly then looking up the details.

After a few iterations I came up with the follow and figured it would be good to keep them in case I ever needed them again.

1) Edit the ssp.properties file in the folder “<Program files>\SAP BusinessObjects\Tomcat6\webapps\explorer\WEB-INF\classes\”

image

Uncomment the “sso.vintela” and set the other values to match the environment.

Further down the list make these changes too.

image

and further down again change these.

image

2) Restart the server…..

Sunday, April 13, 2014

Strange CSC build Error in Visual Studio

Today I had one of those really horrible Visual Studio errors that just would not go away …

clip_image002

OK .. Message seemed simple enough, I’m missing a reference to the DataAccess assembly, which was breaking with a compilation error … So I check the solution to make sure WGPSN.Utility has been referenced and everything looked fine…

clip_image004

Reference is correct and when I compile WGPNS.Utility it’s building correctly. Weird …… ???

I went through the usual stuff like making sure that everything was building against the same version of .NET Framework (4.5) and everything was set correctly.

Solution !!

The reason for this error was nothing to do with the code but the Build Order for the solution …

Right click the solution file and select “Project Build Order”.

clip_image006

WGPSN.DataAccess was before WGPSN.Utility??? Why?? DataAccess references Utility and therefore the build should be Utility first then DataAccess.

Click the “Dependencies” tab and select the offending project “WGPSN.DataAccess” and it has not dependencies on “WGPWN.Utility”? That was not correct as once a project is referenced, that project should be built before the project that is using the reference.

clip_image008

Check the WGPSN.Utility and click “OK”.

clip_image010

All the problems went away.

I really don’t understand why this problem occurred as these settings are usually automatically controlled by Visual Studio, but keep your eyes out for it.

Sunday, March 23, 2014

Getting AD Users into your database

I had one of ‘those’ requirements the other day where I had a WebApp that needed to see all the Users information from Active Directory; however I also had to show details from the internal database.  It’s one of the requirements that popup from time to time and has about 50 different options for implementation. 

In this case I just wanted to have a nightly job to populate a simple table that I could query.  Going direct to AD using code was to slow as there where about 20000 records and they where nested into 20 levels of folders.

The solution was to create a few simple stored procedures:

The first was to get all the Users from a provided folder name;

CREATE PROCEDURE [dbo].[GetUsersFromRoot] ( @root as varchar(1000), @name as varchar(100) = '' )
AS 
SET NOCOUNT ON
-- get the 
DECLARE @sqlString as varchar(1000)

SET @sqlString = 'SELECT '''+ @root+''' as OU, sn, givenName, lower(sAMAccountName), company, lower(userPrincipalName) FROM OPENQUERY(ADSI, ''SELECT givenName, sn, sAMAccountName, company, userPrincipalName FROM ''''LDAP://' + @root + ''''' WHERE objectClass=''''Person'''' AND objectClass=''''User'''' AND sAMAccountName='''''+@name+'*'''''')';
EXECUTE ( @sqlString )
;

The second was to get all the OU’s in the folder; this would be used for a recursive search.
CREATE PROCEDURE [dbo].[GetOUsFromRoot] ( @root as varchar(1000) )
AS 
-- get the 
DECLARE @sqlString as varchar(2000)
SET @sqlString = 'SELECT ''' + @root + ''' as RootOU, distinguishedName FROM OPENQUERY(ADSI, ''<LDAP://' + @root + '>;(&(objectClass=organizationalUnit));distinguishedName;onelevel'')';
EXECUTE ( @sqlString )
;

Now that we have these, we have something that will bind these all together…


CREATE PROCEDURE [dbo].[GetADUsers] ( @root as varchar(1000) )
AS 
DECLARE @rootOUError as varchar(1000);

IF OBJECT_ID('tempdb..#ous') IS NOT NULL DROP TABLE #ouUsers
IF OBJECT_ID('tempdb..#ouUsers') IS NOT NULL DROP TABLE #ous

-- create user table if needed
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[Users]') AND type in (N'U'))
BEGIN
    CREATE TABLE Users ( OU varchar(1000), LastName varchar(100), Firstname varchar(100), LanId varchar(100), Company varchar(100), Email varchar(100)) ;
END

-- create temp tables
CREATE TABLE #ous ( RootOU varchar(1000), OU varchar(1000), error bit)
SELECT OU, LastName, Firstname, LanId, Company, Email INTO #ouUsers FROM dbo.Users WHERE 1=2;  -- get round Collation issue
EXEC dbo.GetADUsersSub @root

-- recurse search any OU that had an error
DECLARE @ouErrorCursor CURSOR
SET @ouErrorCursor = CURSOR FAST_FORWARD FOR SELECT OU FROM #ous WHERE error=1 AND RootOU = @root
OPEN @ouErrorCursor
FETCH NEXT FROM @ouErrorCursor INTO @rootOUError
-- Get all users with the OU 
    WHILE @@FETCH_STATUS = 0
    BEGIN
        PRINT 'Error reported on ' + @rootOUError + ' so running against that OU.'
        EXECUTE dbo.GetADUsersSub @rootOUError
        FETCH NEXT FROM @ouErrorCursor INTO @rootOUError
    END
;

GO

The procedure above will create our Temp table for the data and then kick off a recursive search for any folders within the root folder.

CREATE PROCEDURE [dbo].[GetADUsersSub] ( @root as varchar(1000) )
AS 
SET NOCOUNT ON
------- Main procedure
DECLARE @alpha as int;
DECLARE @rootOU as varchar(1000);
DECLARE @ouUserCursor CURSOR
DECLARE @message as varchar(1000);
DECLARE @rootOUError as varchar(1000);

-- Get all OUs within this root
INSERT INTO #ous ( RootOU, OU ) EXECUTE dbo.GetOUsFromRoot @root;

SET @ouUserCursor = CURSOR FAST_FORWARD FOR SELECT OU FROM #ous WHERE RootOU = @root
OPEN @ouUserCursor
FETCH NEXT FROM @ouUserCursor INTO @rootOU
-- Get all users with the OU 
    WHILE @@FETCH_STATUS = 0
    BEGIN
        -- Loop over each character from A-Z as a simple way to Window the query
        -- ADSI interface has a 900 entry limit which is a limitation to stop DOS attacks
        -- increasing this limit is an option but for the moment this is a simple way to extract everything 
        SET @alpha = 65; -- start at 'A'
        WHILE @alpha < 91
        BEGIN
            BEGIN TRY
                  DECLARE @character as char;
                  SET @character = char(@alpha);
                  INSERT INTO #ouUsers ( OU, LastName, firstname, lanid, company, email ) EXECUTE dbo.GetUsersFromRoot @rootOU, @character;
                  SET @alpha = @alpha+1
            END TRY
            BEGIN CATCH
                -- Execute the error retrieval routine.
                SET @message = ( SELECT ERROR_MESSAGE());
                PRINT 'ERROR: getting OU data ' + @rootOU + '(' + @message + ')';
                -- loog the error
                UPDATE #ous set error=1 where OU = @rootOU;
                BREAK;
            END CATCH;
        END
        FETCH NEXT FROM @ouUserCursor INTO @rootOU
    END
CLOSE @ouUserCursor
DEALLOCATE @ouUserCursor

-- Clean up the OU Names by removing anything without an email
UPDATE #ouUsers set OU = REPLACE(REPLACE(REPLACE(OU, @root, ''), 'OU=', ''),',','')
MERGE dbo.Users AS T
USING (SELECT DISTINCT OU, LastName, Firstname, LanId, Company, Email FROM #ouUsers WHERE LanID is not null and Email is not null) AS S
    ON (T.LanId = S.LanId)
    WHEN MATCHED THEN
        UPDATE SET T.OU = S.OU, T.LastName = S.LastName, T.Firstname = S.Firstname, T.Company = S.Company, T.Email = S.Email
    WHEN NOT MATCHED BY TARGET THEN
        INSERT (OU, LastName, Firstname, LanId, Company, Email) VALUES (OU, LastName, Firstname, LanId, Company, Email);

PRINT 'Cleaning out Users Table';
TRUNCATE TABLE #ouUsers;

PRINT 'run the procedure for any OUs in error';
DECLARE @ouErrorCursor CURSOR
SET @ouErrorCursor = CURSOR FAST_FORWARD FOR SELECT OU FROM #ous WHERE error=1 AND RootOU = @root
OPEN @ouErrorCursor
FETCH NEXT FROM @ouErrorCursor INTO @rootOUError
-- Get all users with the OU 
    WHILE @@FETCH_STATUS = 0
    BEGIN
        PRINT 'Error reported on ' + @rootOUError + ' so running against that OU.'
        EXECUTE dbo.GetADUsersSub @rootOUError
        FETCH NEXT FROM @ouErrorCursor INTO @rootOUError
    END
;

GO

Above; we get round the limits on AD queries by going via the alphabet, All A’s, B’s, C’s etc…. It’s not fast but it was easier than getting the network limits changed.

Tuesday, March 4, 2014

Attending ThoughtWorks Hang out today

I had the good fortune to attend the ThoughtWorks technology Radar presentation this morning ..  Reviewing the Radar gave me some ideas for new technologies on the horizon, but most importantly which technologies and frameworks that I can safely ignore for a few more months.

It’s well worth a review… http://www.thoughtworks.com/radar/#/

Thursday, February 20, 2014

Primavera filter error

Today an old issue raised it head… When creating a filter on the a specific field caused an error is displayed to the User.

clip_image002

This issue addressed with a Primavera HotFix file that was released from Oracle for P6 SP 3.

Copy the file: PM.EXE hotfix file which you can download from the support site, over the existing PM.EXE file on the client PC. This can usually be located in the “C:\Program Files (x86)\Oracle\Primavera P6\Project Management” folder.

Tuesday, February 11, 2014

List of Items in Business Objects

Today one of the Users asked if it was possible to update the list of items that appear in a query list….

clip_image002

For example, the list above shows all months in 2014 .. they only want to see dates in 2013 and 2014.

You can do this using Information Designer.

1) Open the Universe

2) Select the “Parameters List of Values option”

clip_image004

3) Edit the existing list or create a new one.

clip_image006

4) Edit the Query and change the name

clip_image008

5) Add the additional values you want in the list and click OK.

6) clip_image010

7) Next ensure that the filter/field in the Universe is associated with the correct list

8) Click on “Business Layer” and the field; then click “Advanced”

clip_image012

9) Publish the Universe.

Thursday, January 30, 2014

CHM file is blank when opened

Today I was downloading some API documentation which was in CHM format.  The problem is the files where blank when I opened them!

image

The solution was simple…. Just right click on the file in windows Explorer and click the “Unblock” button on the General tab.

image

Now when you open the file the document information is shown.

image

Thursday, January 16, 2014

Running an SSRS report against SharePoint

One of the things that comes up again and again is having the ability to run reports against SharePoint Lists. You create the report like you would any other using Visual Studio and deploy it to your sever.

You set the report to run against a list and as a specific user.

Click on the down arrow and selecting the “Manage option”

clip_image002

In the DataSource Tab ensure you are using a custom data source selected with the details set such as URL and Username and Password.

clip_image004

Click “Test Connection” and it will confirm that everything is working correctly

Tuesday, January 14, 2014

Nintex workflow Inline functions

Found a handy post that lists all the Nintex workflow inline functions. http://connect.nintex.com/forums/permalink/4119/4892/ShowThread.aspx

Sunday, January 12, 2014

Compressing PDF files with Nitro PDF

Today I had a problem getting a file sent to to a client. The issue was that the PDF was running to 32Mb in size and the email limits where stoping transport. The solution was to "Optimise" the document.

Open the doc in Nitro PDF; select File / Optimize

clip_image002

Select "Web" and click "Optimize" button .. simple. After a few seconds you end up with a file just under 6Mb!