Hoping to use a windows shell API call that can accept wild cards to change attributes programmatically. Utmost thanks/blessings for any/all thoughts.
Borrowing code from http://www.resolvinghere.com/sm/how-do-i-change-an-attribute-of-a-file-from-within-a-visual-foxpro-program.shtml
RUN /N ATTRIB +H "c:\test.txt" && Hidden causes dos window to noise itself RUN /N ATTRIB -H "c:\test.txt" && UnHidden
Tom recalled this ... but it does not take wild-cards:
*------------CHAR-------HEX------------------BIN---------NUM
* READONLY R 0x00000001 00000000 00000001 1
* HIDDEN H 0x00000002 00000000 00000010 2
* SYSTEM S 0x00000004 00000000 00000100 4
* DIRECTORY D 0x00000010 00000000 00010000 16
* ARCHIVE A 0x00000020 00000000 00100000 32
* NORMAL N 0x00000080 00000000 10000000 128
* TEMPORARY T 0x00000100 00000001 00000000 256
* COMPRESS C 0x00000800 00001000 00000000 2048
* NOINDEX I 0x00002000 00100000 00000000 8192
* CHIPHER P 0x00004000 01000000 00000000 16384
* ERROR 0xFFFFFFFF REPL("1",32) 4294967295
* ----------------------------------------------------------------------
LPARAMETER vFilename as String, vNewAttribute as String LOCAL liFlag as Integer, llResult, liAttributes, lnNewAttribute, cDummy, nBitPos, cBitMap
DECLARE INTEGER SetFileAttributes IN Win32API STRING, INTEGER DECLARE INTEGER GetFileAttributes IN Win32API STRING
llResult = .F.
IF !EMPTY(vFilename)
IF VARTYPE(vNewAttribute) = [C]
lnNewAttribute = 0
* 1234567890123456
cBitMap = [RHS DA NT C IP ]
FOR i = 1 TO LEN(vNewAttribute)
cDummy = SUBSTR(vNewAttribute,i,1)
nBitPos = AT(cDummy,cBitMap)
IF nBitPos > 0
lnNewAttribute = BITSET(lnNewAttribute, nBitPos -1 )
ENDIF
ENDFOR
ELSE
lnNewAttribute = vNewAttribute
ENDIF
liAttributes = GetFileAttributes(vFilename)
IF (liAttributes # -1)
lnNewAttribute = BITXOR(liAttributes, lnNewAttribute)
llResult = (SetFileAttributes(vFilename, lnNewAttribute) = 1 )
ENDIF
ENDIF
RETURN llResult
Of course RUN ... should not be one of your selections to accomplish a procedure where you don't need to shell to DOS at all.
Your question is two fold:
For this one you can use a bunch of alternatives such as FileSystemObject, Adir() or Filer.dll that ships with VFP and maybe more. Here I will sample with the Filer.dll (which is also the DLL used in HOME()+'tools\filer\filer.scx' ). Here is one enhanced wildcard match using filer:
*GetTree.prg
Lparameters tcStartDir,tcSkeleton,tcCursorName,;
tlSubfolders,;
tlWholeWords,tlIgnoreCase,tlSearchAnd,tcSearch1,tcSearch2,tcSearch3
Create Cursor (m.tcCursorName) ;
(filepath m, filename m, ;
FileSize i, fattr c(8), createtime T, lastacc T, lastwrite T)
Local oFiler, lnFound
oFiler = Createobject('filer.fileutil')
With m.oFiler
.SearchPath = m.tcStartDir
.FileExpression = m.tcSkeleton && Search for skeleton
.Subfolder = Iif(m.tlSubfolders,1,0) && Check subfolders
.IgnoreCase = Iif(m.tlIgnoreCase,1,0)
.WholeWords = Iif(m.tlWholeWords,1,0)
.SearchAnd = Iif(m.tlSearchAnd,1,0)
.SearchText1 = Iif(Empty(m.tcSearch1),"",m.tcSearch1)
.SearchText2 = Iif(Empty(m.tcSearch2),"",m.tcSearch2)
.SearchText3 = Iif(Empty(m.tcSearch3),"",m.tcSearch3)
lnFound = .Find(0)
For ix=1 To m.lnFound
With .Files(m.ix)
If !(Bittest(.Attr,4) And .Name = '.')
Insert Into (m.tcCursorName) ;
(filepath, filename, FileSize, fattr, createtime, lastacc, lastwrite) ;
values ;
(.Path, .Name, .Size, Attr2Char(.Attr), ;
Num2Time(.Datetime), Num2Time(.LastAccessTime), Num2Time(.LastWriteTime))
Endif
Endwith
Endfor
Endwith
Return m.lnFound
Function Num2Time
Lparameters tnFloat
Return Dtot({^1899/12/30}+Int(m.tnFloat))+86400*(m.tnFloat-Int(m.tnFloat))
Function Attr2Char
Lparameters tnAttr
Return ;
IIF(Bittest(m.tnAttr,0),'RO','RW')+;
IIF(Bittest(m.tnAttr,1),'H','_')+;
IIF(Bittest(m.tnAttr,2),'S','_')+;
IIF(Bittest(m.tnAttr,4),'D','_')+;
IIF(Bittest(m.tnAttr,5),'A','_')+;
IIF(Bittest(m.tnAttr,6),'E','_')+;
IIF(Bittest(m.tnAttr,7),'N','_')
If you are not after those fancy attributes, that are rarely used, here is the function I have written for myself:
*SetFAttributes.prg
lparameters tcFileName, tlReadOnly, tlHidden, tlSystem
#define FILE_ATTRIBUTE_READONLY 0x00000001
#define FILE_ATTRIBUTE_HIDDEN 0x00000002
#define FILE_ATTRIBUTE_SYSTEM 0x00000004
local lnNewAttr
lnNewAttr = iif(m.tlReadonly,FILE_ATTRIBUTE_READONLY,0)+;
iif(m.tlHidden,FILE_ATTRIBUTE_HIDDEN,0)+;
iif(m.tlSystem,FILE_ATTRIBUTE_SYSTEM,0)
declare integer SetFileAttributes in Win32API ;
string @ lpFileName, integer dwFileAttributes
declare integer GetFileAttributes in Win32API ;
string @ lpFileName
return ( SetFileAttributes(@tcFilename, ;
bitor(bitand(GetFileAttributes(@tcFilename),0xFFFFFFF8),m.lnNewAttr)) = 1)
Having the above prg files on hand, lets say you want to set all .txt files under c:\MyFolder and its subfolders to readonly, (not hidden, not system) you would be doing this:
Local lcFileName
GetTree('c:\MyFolder','*.txt', 'myCursor', .T.)
Select myCursor
scan for Atc('D',fAttr) = 0
lcFileName = Addbs(Trim(FilePath))+Trim(FileName)
SetFAttributes(m.lcFileName, .T., .F., .F.)
endscan
User contributions licensed under CC BY-SA 3.0