Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Westi on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Modify/Append General - Opening Word Read Only 1

Status
Not open for further replies.

wsjames

Programmer
Apr 7, 2003
50
US
Is it possible to open a word.doc readonly using modify general. Thus far, in my attempts the NOMODIFY/NOEDIT option doesn't seem to work.

I opted to use the Append/Modify General approach due to my inability to launch (within my app) Word from various workstations. Seems Foxpro 2.6 needs to know where Winword.exe resides and the workstations have MSWord installed in various locations. I am without the expertise to know the best method of identifying its location.

Or, if there is a better approach please let me know.
 
You stated your using Fox2.6, But you failed to mention the windows version you are using. You can try this on a NON-VISTA system.
Code:
*/***************************************************************************
*#Is File in Windows Registry
*/Program   : File_Registry
*/System    : FoxPro Library
*/Purpose   : Return the full path of a exe file if it is in the windows registry.
*/Syntax    : Path = File_Registry(exefile)
*/Returns   : Path - string - fullpath and name
*/Parameter : exefile - string - application name (with the exe extension)
*/Defaults  : none
*/Requires  : Win9x, WinNT
*/Changes   : nothing
*/Calls     : External : WinApi AdVapi32.dll
*/Version   : 1.0
*/Dated     : 09/11/2000
*/Written By: David W. Grewe
*/***************************************************************************
*&Application - Utility
*/***************************************************************************
*/ Record Of Change
*/ 
*/***************************************************************************
*procedure File_Registry
LPARAMETERS pcExeName
* returns full path of EXE file taking it from Windows registry, or empty string

IF	EMPTY(m.pcExeName) OR VARTYPE(m.pcExeName)<>"C" OR PARAMETERS()<1
	RETURN ' '
ENDIF 
m.pcExeName = justfname(m.pcExeName)

declare long RegOpenKey    in advapi32 long hKey, string lpSubKey, long @phkResult
declare long RegQueryValue in advapi32 long hKey, string lpSubKey, string @lpValue, long @lpcbValue
declare long RegCloseKey   in advapi32 long hKey
#define HKEY_LOCAL_MACHINE  -2147483646  && bitset(0,31)+2

LOCAL lnErrorRes, phkResult, lpSubKey, lpValue, lpcbValue

phkResult = 0
lpSubKey = 'SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths'
lpValue = .null.
lpcbValue = 0

lnErrorRes = RegOpenKey(HKEY_LOCAL_MACHINE, lpSubKey, @phkResult)
IF lnErrorRes # 0 or phkResult = 0        && Cannot open registry key - unknown error
	=MESSAGEBOX('Cannot open Windows registry.',16,'')
	RETURN ''
ENDIF 

&& open key for exe
lnErrorRes = RegQueryValue(phkResult, m.pcExeName, @lpValue, @lpcbValue)
IF 	lnErrorRes # 0 or lpcbValue = 0        && exe-file not registered or path not stored (0 byte length)
	lnErrorRes = RegCloseKey(phkResult)
*  = messagebox('Exe file not registered in Windows.',16,'')
	RETURN ''
ENDIF 

lpValue = space(lpcbValue)        && in lpcbValue - size of string
lnErrorRes = RegQueryValue(phkResult, m.pcExeName, @lpValue, @lpcbValue)
IF 	lnErrorRes # 0 or isnull(lpValue) or empty(lpValue)
&& cannot read default value - unknown error
	lnErrorRes = RegCloseKey(phkResult)
	=MESSAGEBOX('Cannot read value from registry.',16,'')
	RETURN ''
ENDIF 

lnErrorRes = RegCloseKey(phkResult)
IF  lnErrorRes # 0
&& cannot close key - ignore this error
ENDIF 

&& in lpValue - path for exe
lpValue = CHRTRANC(lpValue, chr(0), '')        && delete ending #0

RETURN lpValue

David W. Grewe Dave
 
Dave,

I want to apology for not providing more detail. Window XP is the OS.

The program you provided is a great solution for identifying file locations within the 32-bit environment of VFP. But I have not yet figured how to convert (or apply) to the 16-bit version - Foxpro 2.6a.

My ultimate goal to modify an existing FoxPro 2.6a application which will allow SysAdmns to modify Word 2003 documents, and provide readonly/print access to the end-user. Ideally, I would not want to force the user to install additional software (i.e. Word Viewer), as there are approximately 50 end-users.

As I mentioned in my orginal post, the Append/Modify General commands seem to offer promise. However, the Modify General command (used in conjunction with the NOMODIFY or NOEDIT) does not protect the document from user edits - that is, from within my application. However ( and I just realized this), the command works great from within the Foxpro 2.6a developer environment.

Additional assistance would be greatly appreciated.
 
I never had much luck with General fields, they tend to be unstable, fill up fast, slow down the system and reach the 2 gig limit often. So I stopped placing files in the field and went to reference locations. Gave that up as unstable and went back to memo fields, Gave that up and when back to Char fields.

In a bid tracking system for a Bid service company that tracked all the jobs and bids from the U.S.G.P.O., I stored the file location in a char field and used the file attributes to control access.

If you want to go that route, here is a function to set file attributes using 3 different methods to do it.
Code:
*/***************************************************************************
*# Change a File Atrributes using DOS, FOX, or Windows
*/Program   : File_Attr
*/System    : Fox Library
*/Purpose   : Change the file Attribute
*/Syntax    : Stauts = File_Attr(Filename, Attribute , Method)
*/Returns   : Status - integer - 0 or better means completed, negative means not completed
*/Parameter : Filename - String
*/          : Attribute - String with the any of the letters (+,-,N,R,H,S,D,A,L,C) in it 
*/Defaults  : 
*/Requires  : 
*/Changes   : 
*/Calls     : 
*/Version   : 1.0
*/Dated     : <<DATE>>
*/Written By: David W. Grewe
*/***************************************************************************
*& File Handling
*/***************************************************************************
*/ Record Of Change
*/ 
*/***************************************************************************
*/Normal      0 Normal file. No attributes are set. 
*/ReadOnly    1 Read-only file. Attribute is read/write. 
*/Hidden      2 Hidden file. Attribute is read/write. 
*/System      4 System file. Attribute is read/write. 
*/Directory  16 Folder or directory. Attribute is read-only. 
*/Archive    32 File has changed since last backup. Attribute is read/write. 
*/Alias      1024 Link or shortcut. Attribute is read-only. 
*/Compressed 2048 Compressed file. Attribute is read-only. 
*/***************************************************************************
parameter pcFile,pcAttrib,pcMethod
do case
case parameters() < 0.5 
	return -1
case type("pcFile") != "C" 
	return -2
case empty(pcFile) 
	return -3
case !file(pcFile)
	return -4
endcase
*
*set step on
*
lcError = on("ERROR")
IF  parameters() < 1.5 or type("pcAttrib") != "C" or empty(pcAttrib)
	pcAttrib = "N"
ENDIF 

IF  parameters() < 2.5 or type("pcMethod") != "C" or empty(pcMethod)
	pcMethod = "WSH"
ENDIF 
*
lnAttrib = 0
IF  "R" $ pcAttrib
	lnAttrib = lnAttrib + 1
ENDIF 
IF  "H" $ pcAttrib
	lnAttrib = lnAttrib + 2
ENDIF 
IF  "S" $ pcAttrib
	lnAttrib = lnAttrib + 4
ENDIF 
IF  "A" $ pcAttrib
	lnAttrib = lnAttrib + 32
ENDIF 
IF  "D" $ pcAttrib
	lnAttrib = lnAttrib + 16
ENDIF 
IF  "L" $ pcAttrib
	lnAttrib = lnAttrib + 1024
ENDIF 
IF  "C" $ pcAttrib
	lnAttrib = lnAttrib + 2048
ENDIF 
*
lnError = 0
on error do InternalErrorTrap
*
DO CASE 
CASE  pcMethod = "DOS"
	lcRun = "Attrib.exe "+PcAttrib+" " +pcFile
	run &lcRun

CASE  pcMethod = "WSH"
	*You can use the FileSystemObject of WSH:
	oFSO  = CreateObject('Scripting.FileSystemObject')
	oFile = oFSO.GetFile(pcFile)
	oFile.Attributes = lnAttrib

CASE  pcMethod = "API"
	* use the SetFileAttributes API function:
	DECLARE INTEGER SetFileAttributes IN WIN32API STRING @, INTEGER
	SetFileAttributes(@pcFile , lnAttrib) && Archive

ENDCASE 
on error &lcError
RETURN iif(lnError > 0 , lnError * -1 , lnAttrib)
*
*********************************************************************************
*
PROCEDURE InternalErrorTrap
lnError = error()
RETURN 




* Example use:
* If EXE is already Hidden, make it read only, but not System:
IF 'H' $ GetFileAttr( 'C:\MyDir\MyApp.exe' )
  * Make EXE read only:
  SetFileAttr( 'C:\MyDir\MyApp.exe', 'Rs' )
ENDIF


PROCEDURE SetFileAttr( pcFile, pcAttr )
* Author: William GC Steinford 2003
* Takes a file and a list of attributes to change on the file, and does the change
*
* pcFile  : either just the file name or the full path to the file.
*           Either way, the full path will be resolved using FULLPATH()
* pcAttrs : a list of attributes to change on the file
*           if the attribute character is Uppercase it will be turned on,
*             Lowercase, it will be turned off, 
*             Not listed, it will be left alone.
*           a,A - Archive
*           s,S - System
*           h,H - Hidden
*           r,R - Read Only
*           i,I - Not Content-Indexed
*           t,T - Temporary Storage (try to keep in memory)
*           N   - Normal (clear all other attributes)

*!*    BOOL SetFileAttributes(
*!*      LPCTSTR lpFileName,      // file name
*!*      DWORD dwFileAttributes   // attributes
*!*    )
*!*    DWORD GetFileAttributes(
*!*      LPCTSTR lpFileName   // name of file or directory
*!*    )

#define FILE_ATTRIBUTE_READONLY             0x00000001
#define FILE_ATTRIBUTE_HIDDEN               0x00000002
#define FILE_ATTRIBUTE_SYSTEM               0x00000004
#define FILE_ATTRIBUTE_DIRECTORY            0x00000010
#define FILE_ATTRIBUTE_ARCHIVE              0x00000020
#define FILE_ATTRIBUTE_ENCRYPTED            0x00000040
#define FILE_ATTRIBUTE_NORMAL               0x00000080
#define FILE_ATTRIBUTE_TEMPORARY            0x00000100
#define FILE_ATTRIBUTE_SPARSE_FILE          0x00000200
#define FILE_ATTRIBUTE_REPARSE_POINT        0x00000400
#define FILE_ATTRIBUTE_COMPRESSED           0x00000800
#define FILE_ATTRIBUTE_OFFLINE              0x00001000
#define FILE_ATTRIBUTE_NOT_CONTENT_INDEXED  0x00002000

DECLARE INTEGER GetFileAttributes IN kernel32 STRING lpFileName
DECLARE SHORT SetFileAttributes IN kernel32 STRING lpFileName,INTEGER dwFileAttributes  

LOCAL lcFile, lnAttr, lcAttr, laDir[1]
lcFile = FULLPATH(pcFile)
* File() doesn't see Hidden or system files: if NOT FILE(pcFile)
IF adir(laDir,lcFile,'DHS')=0
  RETURN .F.
endif
lcAttr = upper(pcAttr)

if 'N' $ pcAttr
  * "NORMAL" must be used alone.
  lnRes = SetFileAttributes(lcFile,FILE_ATTRIBUTE_NORMAL)
  RETURN (lnRes<>0)
endif

lnAttr = GetFileAttributes( lcFile )
* These attributes Can't be set using SetFileAttributes:
lnAttr = BitAnd( lnAttr, BitNot( FILE_ATTRIBUTE_COMPRESSED ;
     + FILE_ATTRIBUTE_DIRECTORY + FILE_ATTRIBUTE_ENCRYPTED ;
     + FILE_ATTRIBUTE_REPARSE_POINT ;
     + FILE_ATTRIBUTE_SPARSE_FILE ) )
if 'A' $ lcAttr
  if 'A' $ pcAttr
    lnAttr = BitOr( lnAttr, FILE_ATTRIBUTE_ARCHIVE )
  else
    lnAttr = BitAnd( lnAttr, BitNot(FILE_ATTRIBUTE_ARCHIVE) )
  endif
endif
if 'R' $ lcAttr
  if 'R' $ pcAttr
    lnAttr = BitOr( lnAttr, FILE_ATTRIBUTE_READONLY )
  else
    lnAttr = BitAnd( lnAttr, BitNot(FILE_ATTRIBUTE_READONLY) )
  endif
endif
if 'H' $ lcAttr
  if 'H' $ pcAttr
    lnAttr = BitOr( lnAttr, FILE_ATTRIBUTE_HIDDEN )
  else
    lnAttr = BitAnd( lnAttr, BitNot(FILE_ATTRIBUTE_HIDDEN) )
  endif
endif
if 'S' $ lcAttr
  if 'S' $ pcAttr
    lnAttr = BitOr( lnAttr, FILE_ATTRIBUTE_SYSTEM )
  else
    lnAttr = BitAnd( lnAttr, BitNot(FILE_ATTRIBUTE_SYSTEM) )
  endif
endif
if 'I' $ lcAttr
  if 'I' $ pcAttr
    lnAttr = BitOr( lnAttr, FILE_ATTRIBUTE_NOT_CONTENT_INDEXED )
  else
    lnAttr = BitAnd( lnAttr, BitNot(FILE_ATTRIBUTE_NOT_CONTENT_INDEXED) )
  endif
endif
if 'T' $ lcAttr
  if 'S' $ pcAttr
    lnAttr = BitOr( lnAttr, FILE_ATTRIBUTE_TEMPORARY )
  else
    lnAttr = BitAnd( lnAttr, BitNot(FILE_ATTRIBUTE_TEMPORARY) )
  endif
endif
if 'N' $ lcAttr
  lnAttr = iif('N'$pcAttr, FILE_ATTRIBUTE_NORMAL, lnAttr )
endif

lnRes = SetFileAttributes(lcFile,lnAttr)
RETURN (lnRes<>0)

FUNCTION GetFileAttrib( tcFName )
*GetFileAttrib( cFName ) Return the File Attributes (RSHA)
*!*    DWORD GetFileAttributes(
*!*      LPCTSTR lpFileName   // name of file or directory
*!*    )
  DECLARE LONG GetFileAttributes IN Win32Api AS util_GetFileAttributes ;
    STRING LPCTSTR_lpFileName 
  LOCAL lnAttr, lcAttr
  lnAttr = util_GetFileAttributes( tcFName )
  CLEAR DLLS util_GetFileAttributes
  if lnAttr=0xFFFF
    RETURN 'error'
  ENDIF
  lcAttr = iif( BITAND(lnAttr,util_FILE_ATTRIBUTE_READONLY )>0, 'R', '' ) ;
         + iif( BITAND(lnAttr,util_FILE_ATTRIBUTE_HIDDEN   )>0, 'H', '' ) ;
         + iif( BITAND(lnAttr,util_FILE_ATTRIBUTE_SYSTEM   )>0, 'S', '' ) ;
         + iif( BITAND(lnAttr,util_FILE_ATTRIBUTE_ARCHIVE  )>0, 'A', '' ) ;
         + iif( BITAND(lnAttr,util_FILE_ATTRIBUTE_DIRECTORY)>0, 'D', '' )
  RETURN lcAttr
ENDFUNC


David W. Grewe Dave
 
Dave,

Thank you so much for the tips. You not only helped me solve the problem, you also inspired me to think outside the box.

Willard
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top