Technology Blogs by SAP
Learn how to extend and personalize SAP applications. Follow the SAP technology blog for insights into SAP BTP, ABAP, SAP Analytics Cloud, SAP HANA, and more.
cancel
Showing results for 
Search instead for 
Did you mean: 
former_member203619
Contributor
0 Kudos

There have been a couple issues / bugs in the past which have resulted in orphaned files in the input or output file repository servers (FRS).  The scripts on this page were created to help clean up the FRS servers so there aren't any excess files taking up room.

All of these scripts were written in VBScript and designed for BOE XI R2, however they will generally work on BOE XI R3 as well (Although they are not supported when run on BOE XI R3)

Note:

For other scripts and information on how to run these scripts see here:

shawn.penner/blog/2013/06/04/scripts-and-samples

Scan and Clean FRS Servers

This script will scan the input and output FRS for files that do not have corresponding entries in enterprise and delete them.  It will also delete the folders left over after removing the orphaned objects.  The way it determines if a matching InfoObject exists is by assuming that the folder name at the deepest level is the SI_ID of the object.  If an object with that SI_ID exists on the Enterprise Server, then that object is assumed to be valid.

Notes:

  • You will need to change the username, password, and CMS name to the values specific to your enterprise server.  It is highly recommended that you use the Administrator user as other users may not be able to see all the objects on the enterprise server.  And if the script can't see the object - it assumes that it doesn't exist and removes the corresponding files.
  • This script creates a log file in "C:\output.log" which stores the results of the script running
  • To run this script in test mode, set the DoDelete variable to false.  To take it out of test mode, set the DoDelete variable to True
  • This script must be run on the server where the FRS is physically located - or where you have a direct path to the FRS folder location.
  • You will need to change the inputFRSRoot and outputFRSRoot to the base folder of your filestores
    • Default location for XI R2:
      • "C:\Program Files\Business Objects\BusinessObjects Enterprise 11.5\FileStore\Input"
      • "C:\Program Files\Business Objects\BusinessObjects Enterprise 11.5\FileStore\Output"
    • Default location for XI R3:
      • "C:\Program Files (x86)\Business Objects\BusinessObjects Enterprise 12.0\FileStore\Input"
      • "C:\Program Files (x86)\Business Objects\BusinessObjects Enterprise 12.0\FileStore\Output"
  • The path to the input and output FRS must not have a slash at the end or the script will not work.
  • If you are running this on a 64-bit OS such as Windows 7, you will need to specify the 32-Bit version of cscript in order to run it succesfully.  Otherwise you will encounter the error "ActiveX component can't create object: 'CrystalEnterprise.SessionMgr' ".

    e.g.
    %windir%\SysWOW64\cscript.exe scanfrs.vbs

Scan and Clean Input and Output FRS

Dim DoDelete
Dim inputFRSRoot
Dim outputFRSRoot

DoDelete = False   ' False = Test Mode, True = Actually Delete the Files
inputFRSRoot = "C:\Program Files (x86)\Business Objects\BusinessObjects Enterprise 12.0\FileStore\Input"
outputFRSRoot = "C:\Program Files (x86)\Business Objects\BusinessObjects Enterprise 12.0\FileStore\Output"

'Declare CMS logon variables
Dim CMS
Dim Usnername
Dim Password
Dim Authtype

CMS = "localhost"
Username = "Administrator"
Password = ""
Authtype = "secEnterprise"

'Declare variables for Enterprise Session
Dim oEnterpriseSessionMgr
Dim ceSession
Dim oInfoObjects
Dim oInfoObjects2
Dim boServer1Admin
Dim boServer2Admin

' File IO stuff
Dim objFSO
Dim outputFile

'Open the outputFile for logging.
Set objFSO = CreateObject("Scripting.FileSystemObject")
set outputFile = objFSO.OpenTextFile("C:\output.log",8,True)

outputFile.WriteLine("-------- Starting Script --------")

'Load the Enterprise Session Manager
Set oEnterpriseSessionMgr = CreateObject("CrystalEnterprise.SessionMgr")

'Logon to the CMS and create iStore object
Set ceSession = oEnterpriseSessionMgr.Logon(Username, Password, CMS, Authtype)
Set iStore = ceSession.Service("","InfoStore")

outputFile.WriteLine("Input FRS Root = " & inputFRSRoot)
outputFile.WriteLine("Output FRS Root = " & outputFRSRoot)

' Now that we have the root folders - we need to loop through them and drill down to the deepest level
' The logic used is:
' - Is there a file?  If not, is there a sub-folder.
' - If there is a sub-folder - then go into it
' - If there is a file - then look at the last folder name - that will be the SI_ID
' - Check if an object with that SI_ID exists.  If it does - all is well - if not - flag for deletion
' - The deletion will go up folder by folder until one of three conditions occur. 
' - 1. A file exists in the folder.
' - 2. More than 1 sub-folder
' - 3. The name of the current folder is either Input, or Output

Dim finalOutput
Dim finalInput

' Scan the Input FRS
outputFile.WriteLine("Starting Input FRS")
finalInput = CheckAndDelete(DoDelete, iStore, objFSO, outputFile, inputFRSRoot)
outputFile.WriteLine("")

' Scan the Output FRS
outputFile.WriteLine("Starting Output FRS")
finalOutput = CheckAndDelete(DoDelete, iStore, objFSO, outputFile, outputFRSRoot)

outputFile.WriteLine("All Done")

' Clean everything up
outputFile.close
ceSession.Logoff()
Set oInfoObjects = Nothing
Set oInfoObject = Nothing
Set iStore = Nothing
Set ceSession = Nothing
Set oEnterpriseSessionMgr = Nothing


Function CheckAndDelete(DoDelete, iStore, objFSO, outputFile, fileRoot)
Dim boFolder
Dim boFile
Dim folderCount
Dim fileCount
Dim boSubFolder
Dim DeleteThisFolder
Dim boInfoObjects

' Set it initially to not delete the folder
CheckAndDelete = false

Set boFolder = objFSO.GetFolder(fileRoot)

' Get a count of the files in this folder, and a count of the sub-folders
fileCount = boFolder.Files.Count

' Are there files here - then we need to check if the matching SI_ID exists
if fileCount > 0 then
  Set boInfoObjects = iStore.Query("select SI_ID from CI_INFOOBJECTS, CI_SYSTEMOBJECTS, CI_APPOBJECTS where SI_ID = " & boFolder.Name)

  ' If the count is 0 - then this is an orphan
  if boInfoObjects.count = 0 then
   outputFile.WriteLine("Orphaned File with ID " & boFolder.Name & " found at " & fileRoot)
  
   ' Delete the files in this folder
   For Each boFile in boFolder.Files
    if DoDelete = True then
     outputFile.WriteLine("Deleting File: " & fileRoot & "\" & boFile.Name)
     objFSO.DeleteFile fileRoot & "\" & boFile.Name, true
    Else
     outputFile.WriteLine("In Test Mode - Would have deleted File: " & fileRoot & "\" & boFile.Name)
    End If
   Next

   ' Set the delete flag to true to tell the function one up the recursive stack to remove this folder
   CheckAndDelete = true
  end if
end if

For Each boSubFolder in boFolder.SubFolders
  'outputFile.WriteLine(boSubFolder.Name)
  DeleteThisFolder = CheckAndDelete(DoDelete, iStore, objFSO, outputFile, fileRoot & "\" & boSubFolder.Name)
 
  if DeleteThisFolder = true then
   if DoDelete = True then
    outputFile.WriteLine("Deleting Folder: " & fileRoot & "\" & boSubFolder.Name)
    objFSO.DeleteFolder(fileRoot & "\" & boSubFolder.Name)
   Else
    outputFile.WriteLine("In Test Mode - Would have deleted Folder: " & fileRoot & "\" & boSubFolder.Name)
   End If
 
   ' Now check and see if there are any more sub-folders in this folder - or if the name of the folder is Input or Output.
   folderCount = boFolder.SubFolders.Count
   if folderCount = 0 then
    if boFolder.Name = "Input" or boFolder.Name = "Output" then
     CheckAndDelete = false
    else
     CheckAndDelete = true
    end if
   end if
  end if
Next
End Function

Parse RepoScan XML

This next script doesn't actually use an BusinessObjects SDK's to clean out the Input and Output FRS.  Instead it relies on the use of the RepoScan tool to identify mismatches between the CMS database and what is on disk.

Notes:

  • You will need to run the RepoScan tool to generate a log file.  To run RepoScan, do the following:
    • Create an options.txt file.  I have pasted an example below:

      -dbdriver mysqldatabasesubsystem
      -inputfrsdir "C:\Program Files\Business Objects\BusinessObjects Enterprise 12.0\FileStore\Input"
      -outputfrsdir "C:\Program Files\Business Objects\BusinessObjects Enterprise 12.0\FileStore\Output"
      -connect UID=sa;PWD=bopassword123;DSN=BOE120;HOSTNAME=MyEnterpriseServer;
      -outputdir c:\
      -repair false

      The above options file specifies what database is used, the location of the input and output FRS, the database connection string, where to store the log file that is generated, and whether or not to try and repair the issues.
    • Once you have the options.txt file, go into the folder C:\Program Files\Business Objects\BusinessObjects Enterprise 12.0\win32_x86 (For BOE XI R2) and execute the command:

      reposcan -optionsfile c:\options.txt

      where c:\options.txt is the location of the options file.
    • This will generate a log file with a title "Repo_Scan_<Date and Time>.xml" and it will be located in the output directory specified above (in this case c:\)
  • You will need to change the file path in the script to the location of the xml file generated by RepoScan.
  • If you are running this on a 64-bit OS such as Windows 7, you may need to specify the 32-Bit version of cscript in order to run it succesfully.  Otherwise you might encounter error "ActiveX component can't create object: 'Scripting.FileSystemObject' ".

    e.g.
    %windir%\SysWOW64\cscript reposcanxmlparser.vbs

RepoScan XML Parser

Dim xmlDoc
Dim fname
Dim fpath
dim filesys

Set filesys = CreateObject("Scripting.FileSystemObject")
Set xmlDoc = CreateObject("Microsoft.XMLDOM")
xmlDoc.Async = "False"
xmlDoc.Load("C:\Documents and Settings\spenner\My Documents\xmlparse\Repo_Scan_2008_11_24_12_21_24.xml")

strQuery = "/ScanResults/File"
Set colItem = xmlDoc.selectNodes(strQuery)

For Each objItem in colItem
fname = objItem.selectSingleNode("File_Name").nodeTypedValue
fpath = objItem.selectSingleNode("Directory_Path").nodeTypedValue

WScript.Echo "Manually Deleting File: " + fpath + fname
filesys.DeleteFile fpath + fname, true

'WScript.Echo objItem.nodeName & ": " & objItem.text
Next