Report on Projects/Modules Last Modified Date

Hello

I'm looking for some code that will list all the projects in my database, or better yet, all the modules, and their "Last Modified On" date.

I'm not really that much of a coder, but I found in the help file how to list all the projects in the module

////////
string s
for s in database do {
print s "\n"
}
////////

and I have some code that will list all the modules in my database

///////
//Demo
/*List modules in database*/
Buffer b = create
string sType
Item cItem

void FormalModules(Item pItem)
{ sType=type(pItem)
if(sType=="Formal") b+= fullName(pItem) "\n"
if((sType=="Folder")||(sType=="Project"))
for cItem in folder(pItem)do FormalModules(cItem)
}

FormalModules(item("/"))
print b ""
////////
what I'd like to do is list all my projects with their last modified on date, OR list all my modules in my db with their last modified on dates. Doing this as a justification to try to buy some more licenses based on use.

Thanks
richmason - Thu Aug 19 08:53:27 EDT 2010

Re: Report on Projects/Modules Last Modified Date
llandale - Thu Aug 19 15:25:03 EDT 2010

Buying more licenses would be needed if you often ran out of licenses. It doesn't matter how often or how many modules are edited by a single user. We are struggling with the license statistics and its not easy. You can query the current status of the flexLM licensing, but its tough to get reliable statistics without buying something.

The "for s in Project" loop only finds modules in the top-level folder of the Project, making it pretty worthless. The "for Item in Project" loop will find all items, but I presume they are found in created order and not alphabetically in any way, also making it pretty weak. I use the "for Item in Folder" loop that finds anything directly in that folder, and if its a sub-folder then recursively search it. Actually, two loops; the first deals with the type "Formal" items in the folder, the 2nd dealing with the "Folder" or "Project" items in the folder.

You may be able to get the last modified date of a module without opening it. There is no such attribute for a Folder or Project; so you will need to presume, I suppose, that the Last Modified Date of a Folder is the most recent Last Modified Dates of any of its modules or sub-folders. That makes for a tricky Recursive script, something like this outline:
 

Date   LastModofiedModule(Item itm)
{  // figure this out
}
 
Date   LastModifiedFolder(Folder fld)
{
   if (null fld) return(Date null)
   Item  itm
   Date  datFold = dateOf(1), datSub = dateOf(1)
   for itm in fld do
   {  if (type(itm) == "Project" or type(itm) == "Folder")
      {  datSub = LastModifiedFolder(Folder(fullName(itm)))  // ** Recursion **
         if (datSub > datFold) datFold = datSub
      }
   }
   for itm in fld do
   {  if (type(itm) == "Formal"))
      {  datSub = LastModifiedModule(itm)
         if (datSub > datFold) datFold = datSub
      }
   }
   print name(fld) "\t" datFold "\t" fullName(fld) "\n"
}  // end recursive LastModifiedFolder()

 

  • Louie

 

Re: Report on Projects/Modules Last Modified Date
richmason - Fri Aug 20 07:33:02 EDT 2010

Louie

Thanks for the response, after some extensive searching I was able to find a utility that did what I wanted for the most part off of the SmartDXL website under DXL Scripts/Metrics and reports to parse out a module list and I tweaked it to add the "Last Modified On" attribute to the script.

////////////////
// Generate Inventory of current Project from Smartdxl.com

/*
*/

pragma runLim,0

Buffer outBuf = create
outBuf = ""
/******************************************************************************
scanModule
******************************************************************************/
void scanModule(Item itm)
{
Module thisModule = null
bool opened = false

string mName = fullName(itm)

if (!open(module mName))
{
thisModule = read(mName, false)
opened = true
}

outBuf += mName ","
outBuf += thisModule."Created On" ","
outBuf += thisModule."Created By" ","
outBuf += thisModule."Last Modified On" ","
outBuf += version(thisModule) ","
outBuf += thisModule."Description" ","
outBuf += uniqueID(itm) "\n"

if (opened)
{
close(thisModule)
}
}
/******************************************************************************
scanFolder
******************************************************************************/
void scanFolder(Folder f)
{
Item itm

for itm in f do
{
if (null itm) continue
if (isDeleted(itm)) continue

if ((type (itm) == "Project") ||(type (itm) == "Folder"))
{
scanFolder(folder(itm))
}
else if (type (itm) == "Formal")
{
scanModule(itm)
}
}
}
/******************************************************************************
MAIN
******************************************************************************/
string currFolder = fullName current Folder

if (confirm("Generate inventory for " currFolder "?"))
{
scanFolder(folder currFolder)

string fName = "c:/temp/inventory.csv"
Stream outfile = write(fName)

outfile << "Module Name,Created On,Created By,Last Modified On,Version,Description,Unique Id\n"
outfile << outBuf
close(outfile)
delete(outBuf)
// notify the user that the script is complete
ack "Inventory Complete."
}
//////////////////

Btw, also wanted to figure out last login for my users and found a script from Galactic Solutions website to parse login history.
both these scripts are open source as far as I know, but I wanted to give them the plug.

////////////////
// Parse Login History http://galactic-solutions.com/GalacticDownloads.htm

/*
Copyright (c) 2006 Galactic Solutions Group, LLC

Parses "login_history.txt" file, determines last login for users in file.
Exports results to tab separated value (.tsv) file.

For location of the "login_history.txt" file,
see "Understanding the login history file"
in the Telelogic DOORS "Managing DOORS" manual.
*/

/*
Copyright (c) 2006 Galactic Solutions Group, LLC
http://galactic-solutions.com
Author: michael.sutherland@galactic-solutions.com

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or contact http://www.gnu.org

If you find defects with or improve upon this library, please contact
support@galactic-solutions.com
*/

/*
1.0 08 August 2006 Michael Sutherland - Galactic Solutions Group, LLC
- Initial Release for 2006 Telelogic UGC - "Script Exchange and Competition for DOORS"
*/

pragma runLim,0
Regexp LOGIN_HISTORY_LOGIN_FOR_ACCOUNT = regexp "^(a-zA-Za-zA-Za-zA-Z) " "(a-zA-Za-zA-Za-zA-Z) " "( 0-9|0-90-9) " //-
"(0-90-9:0-90-9:0-90-9) " "(0-90-90-90-9) " "\[" "(.*)" "\] Login for account " "(.*)$"
Skip LOG_lastLoginDateForUserName = createString ; Skip LOG_lastLoginComputerNameForUserName = createString
Skip months = createString
put( months, "Jan", 1 ) ; put( months, "Feb", 2 ) ; put( months, "Mar", 3 ) ; put( months, "Apr", 4 ) ; put( months, "May", 5 ) ; put( months, "Jun", 6 )
put( months, "Jul", 7 ) ; put( months, "Aug", 8 ) ; put( months, "Sep", 9 ) ; put( months, "Oct", 10 ) ; put( months, "Nov", 11 ) ; put( months, "Dec", 12 )
DB LOG_DB = null ; DBE LOG_input_fn_DBE = null ; DBE LOG_toggle_DBE = null ; DBE LOG_listView_DBE = null ; DBE LOG_output_fn_DBE = null
Stream outFile = null
void LOB_parseLoginHistoryFile( string fn ) {
if ( fileReadable_( fn ) ) {
Stream file = read( fn )
if ( !null LOG_lastLoginDateForUserName ) { delete LOG_lastLoginDateForUserName ; delete LOG_lastLoginComputerNameForUserName }
LOG_lastLoginDateForUserName = createString ; LOG_lastLoginComputerNameForUserName = createString
if ( !null file ) {
string line
for ( file >> line ; !end file ; file >> line ) {
if ( LOGIN_HISTORY_LOGIN_FOR_ACCOUNT line ) {
string monthStr = line match 2 ; string computerName = upper( line match 6 ) ; string userName = line match 7
int monthInt = 0 ; find( months, monthStr, monthInt )
Date d = monthInt "/" line match 3 "/" line match 5 " " line match 4 ""
Date storedDate
if ( find( LOG_lastLoginDateForUserName, userName, storedDate ) ) {
if ( d > storedDate ) { delete( LOG_lastLoginDateForUserName, userName ) ; delete( LOG_lastLoginComputerNameForUserName, userName ) }
}
put( LOG_lastLoginDateForUserName, userName, d ) ; put( LOG_lastLoginComputerNameForUserName, userName, computerName )
} } } } }
int LOG_compareString( string s1, string s2 ) { return( cistrcmp( s1, s2 ) ) }
int LOG_compareDate( string s1, string s2 ) {
Date d1 = null ; if ( !null s1 ) d1 = s1
Date d2 = null ; if ( !null s2 ) d2 = s2
if ( d1 > d2 ) return( 1 ) ; if ( d1 < d2 ) return( -1 ) ; return( 0 ) }
void LOG_openOutputFile( string output_fileName ) { if ( fileOverwriteOK_( output_fileName ) ) outFile = write binary ( output_fileName ) }
void LOG_listView_create_row( Icon i, string userName ) {
insert( LOG_listView_DBE, noElems( LOG_listView_DBE ), "", i ) ; set( LOG_listView_DBE, noElems( LOG_listView_DBE ) - 1, 0, userName ) }
void LOG_listView_populate( bool useUserList ) {
empty( LOG_listView_DBE )
Icon i = iconUser
if ( useUserList ) {
User u ; for u in userList do {
bool userDisabled = u.disabled ; string userName = u.name ; i = iconUser ; if ( userDisabled && useUserList ) i = iconUserDisabled
LOG_listView_create_row( i, userName )
Date d = null ; if ( find( LOG_lastLoginDateForUserName, userName, d ) ) set( LOG_listView_DBE, noElems( LOG_listView_DBE ) - 1, 1, d "" )
string c = null ; if ( find( LOG_lastLoginComputerNameForUserName, userName, c ) ) set( LOG_listView_DBE, noElems( LOG_listView_DBE ) - 1, 2, c )
} }
else {
Date d ; for d in LOG_lastLoginDateForUserName do {
string userName = ( string key LOG_lastLoginDateForUserName ) ; LOG_listView_create_row( i, userName )
set( LOG_listView_DBE, noElems( LOG_listView_DBE ) - 1, 1, d "" )
string c = null ; if ( find( LOG_lastLoginComputerNameForUserName, userName, c ) ) set( LOG_listView_DBE, noElems( LOG_listView_DBE ) - 1, 2, c )
} } }
void LOG_toggle_callback( DBE x ) { LOG_listView_populate( get( LOG_toggle_DBE ) ) }
void LOG_input_fn_callback( DBE x ) { LOB_parseLoginHistoryFile( get( LOG_input_fn_DBE ) ) ; LOG_listView_populate( get( LOG_toggle_DBE ) ) }
void LOG_output_fn_callback( DBE x ) { string fn = get( LOG_output_fn_DBE ) ; if ( !( fileOverwriteOK_( fn ) ) ) warningBox( "Cannot open " fn " for writing" ) }
void LOG_output_apply_callback( DB x ) {
LOG_openOutputFile( get( LOG_output_fn_DBE ) )
if ( !null outFile ) {
int i ; for ( i = 0 ; i < noElems( LOG_listView_DBE ) ; i++ ) {
outFile << getColumnValue( LOG_listView_DBE, i, 0 ) "\t" getColumnValue( LOG_listView_DBE, i, 1 ) "\t" getColumnValue( LOG_listView_DBE, i, 2 ) "\n"
}
infoBox( "Exported " i " records." ) } }
string dummyList[] = {}
LOG_DB = create( "Last Login" )
DBE LOG_input_fn_label_DBE = label( LOG_DB, "Location of input \"login_history.txt\" file:" )
LOG_input_fn_DBE = fileName( LOG_DB, "", "*.txt", "login_history.txt", true ) ; set( LOG_input_fn_DBE, LOG_input_fn_callback )
LOG_toggle_DBE = toggle( LOG_DB, "Merge with User List from Database", false ) ; set( LOG_toggle_DBE, LOG_toggle_callback )
LOG_listView_DBE = listView( LOG_DB, listViewOptionSortText, 0, 10, dummyList )
DBE LOG_output_fn_label_DBE = label( LOG_DB, "Location of output \"last_login.tsv\" file:" )
LOG_output_fn_DBE = fileName( LOG_DB, "", "*.tsv", "last_login.tsv", false ) ; set( LOG_output_fn_DBE, LOG_output_fn_callback )
DBE LOG_output_apply_DBE = apply( LOG_DB, "Export", LOG_output_apply_callback )
realize( LOG_DB ) ; setSize( LOG_DB, 800, 530 )
insertColumn( LOG_listView_DBE, 0, "Name", 125, iconNone ) ; set( LOG_listView_DBE, 0, LOG_compareString )
insertColumn( LOG_listView_DBE, 1, "Last Login", 125, iconNone ) ; set( LOG_listView_DBE, 1, LOG_compareDate )
insertColumn( LOG_listView_DBE, 2, "Computer Name", 125, iconNone ) ; set( LOG_listView_DBE, 2, LOG_compareString )
show LOG_DB
///////////////////

these both worked for me on DOORS 9.2