Structure DIRECTORY_INFO :
---->This structure (system library SysLibDir.lib contains information on a directory, which is read via
function SysDirRead.
If the directory_info object ,"stDirInfo.diDirectory" , is Hex 2 (16#2), then the Directory is a folder, otherwise if "stDirInfo.diDirectory" is
Hex 0 (16#0) ,then the object is a File.
The Code for looping to get folder names is toward the middle on the code below: The result folder names are put into an array
programnames[]
NOTE : You will need to manually put arbitrary folder names in your PLC directory 1st. (This code will autogenerate the file names).
When the code executes,the filter will be on folder names (directories only) and only directory names will populate programnames[]
( This program uses the synchronous functions for directory modification)
IF xStartTest THEN
( create the complete file pathes)
( The file names can be adapted )
sDirName := '/SystemDirExample';
sFirstFileName := '/firstTest.txt';
sSecondFileName := '/secondTest.txt';
sThirdFileName := '/thirdTest.txt';
xError := FALSE;
xTestDone := FALSE;
sDirName := CONCAT(g_sMainDirectory, sDirName);
sFirstFileName := CONCAT(sDirName, sFirstFileName);
sSecondFileName := CONCAT(sDirName, sSecondFileName);
sThirdFileName := CONCAT(sDirName, sThirdFileName);
( Clean up existing example files)
( Delete existing example files )
//udiDeleteError1:=SysFileDelete(szFileName:=sFirstF ileName );
//udiDeleteError2:=SysFileDelete(szFileName:=sThirdF ileName );
( delete the directory )
//udiDirDeleteError:= SysDirDelete(szDir:= sDirName);
( create a new directory )
udiCreateError := SysDirCreate(szDir:= sDirName);
( two files are created and stored into the directory)
udiFileHandle := SysFileOpen(szFile:=sFirstFileName, am:=AM_WRITE_PLUS, pResult:=ADR(ErrorCode));
IF udiFileHandle <> RTS_INVALID_HANDLE THEN
SysFileClose(hFile:=udiFileHandle);
END_IF
udiFileHandle := SysFileOpen(szFile:=sSecondFileName, am:=AM_WRITE_PLUS, pResult:=ADR(ErrorCode));
IF udiFileHandle <> RTS_INVALID_HANDLE THEN
SysFileClose(hFile:=udiFileHandle);
END_IF
( open the directory
the handle is returned and the first directory entry. Normally the first entry is "." and the second "..")
udiDirHandle := SysDirOpen(szDir:= sDirName, szDirEntry:= sDirEntry, diMaxDirEntry:= 1024,
pDirInfo:= ADR(stDirInfo), pResult:= udiResult);
( Iterate through all directory entries and count them. The implicit entries with points are not count.
when the last entry is reached the SysDirRead always delivers the last entry.)
iFilesCount := 0;
programcount := 1;
REPEAT
IF FIND(sDirEntry, '.') <> 1 THEN
iFilesCount := iFilesCount +1;
END_IF
udiReadError:= SysDirRead(hDir:= udiDirHandle, szDirEntry:= sDirEntry, diMaxDirEntry:= 1024, pDirInfo:=ADR(stDirInfo) );
// SysDirRead is used to Directory Info
// Here, Im using SysDirRead to Find Folder Names within a Directory
// If stDirInfo.diDirectory is Hex 2 , then the Directory is a folder, otherwise Hex 0 is a File
IF stDirInfo.diDirectory = 16#2 AND Find(sDirEntry,'.') <> 1 THEN
programnames[programcount]:=sDirEntry;
programcount:=programcount+1;
END_IF
UNTIL
udiReadError = CmpErrors.Errors.ERR_END_OF_OBJECT
END_REPEAT
( The two created files must be read.)
//IF iFilesCount <> 2 THEN
// xError := TRUE;
//END_IF
( Close the directory )
udiCloseError := SysDirClose(hDir:= udiDirHandle);
( Rename a file )
udiRenameError:=SysFileRename(szOldFileName:= sSecondFileName, szNewFileName:= sThirdFileName);
( the test is set to done, if no error occured )
IF udiCreateError = 0 AND udiCloseError = 0 AND udiRenameError = 0 AND xError = FALSE THEN
xTestDone := TRUE;
ELSE
xError := TRUE;
END_IF
xStartTest := FALSE;
END_IF
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
For your information:
There is a "Use Case" library "File access". This contains the CAA File library in which there are function blocks for opening, listing and closing libraries.
In functionality it is pretty much similar to the SysLib library, but it is made according to the V3 CODESYS library guidelines.
A difference is that it is not blocking, which means that in your case if you have a long list of directories, you will not have the problem of having long scan times.
In the code you should call the FB's with Execute set to TRUE. When the result is done or error you can call the next FB or do some error handling.
When finished, call the FB's with Execute set to FALSE.
In the CODESYS help you can find some examples (see Libraries => System Libraries => CAA Libraries => CAA_File.library).
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hello All,
Im new to Codesys. I have a Festo PLC.
What I would like to do is go to a known file path on my PLC and read the names of the subfolders found under a Parent folder.
Parent Folder (C:/Temp)
---> Subfolder 1
---> Subfolder 2
---> Subfolder 3
My Result should be a list : Name of Subfolder1,Name of Subfolder2, Name of Subfolder3
Please provide code AND any pertinent explanation.....thanks
JL
SOLVED :
The key was using SysDirRead and Directory_Info
Structure DIRECTORY_INFO :
---->This structure (system library SysLibDir.lib contains information on a directory, which is read via
function SysDirRead.
If the directory_info object ,"stDirInfo.diDirectory" , is Hex 2 (16#2), then the Directory is a folder, otherwise if "stDirInfo.diDirectory" is
Hex 0 (16#0) ,then the object is a File.
The Code for looping to get folder names is toward the middle on the code below: The result folder names are put into an array
programnames[]
NOTE : You will need to manually put arbitrary folder names in your PLC directory 1st. (This code will autogenerate the file names).
When the code executes,the filter will be on folder names (directories only) and only directory names will populate programnames[]
VAR
sDirName : STRING;
sFirstFileName : STRING;
sSecondFileName : STRING;
sThirdFileName : STRING;
iFilesCount : INT;
sDirEntry : STRING;
stDirInfo : DirInfo;
udiResult : __XWORD;
udiDirHandle : RTS_IEC_HANDLE;
udiFileHandle : RTS_IEC_HANDLE;
udiReadResult : UDINT;
xStartTest : BOOL:= FALSE; ( true, if a button is pressed )
xTestDone : BOOL:= FALSE;
xError : BOOL;
ErrorCode : RTS_IEC_RESULT;
udiCreateError: UDINT;
udiReadError: UDINT;
udiCloseError: UDINT;
udiRenameError: UDINT;
udiDeleteError1: UDINT;
udiDeleteError2: UDINT;
udiDirDeleteError: UDINT;
programnames: ARRAY[1..32] OF String;
programcount: int;
END_VAR
( This program uses the synchronous functions for directory modification)
IF xStartTest THEN
( create the complete file pathes)
( The file names can be adapted )
sDirName := '/SystemDirExample';
sFirstFileName := '/firstTest.txt';
sSecondFileName := '/secondTest.txt';
sThirdFileName := '/thirdTest.txt';
xError := FALSE;
xTestDone := FALSE;
sDirName := CONCAT(g_sMainDirectory, sDirName);
sFirstFileName := CONCAT(sDirName, sFirstFileName);
sSecondFileName := CONCAT(sDirName, sSecondFileName);
sThirdFileName := CONCAT(sDirName, sThirdFileName);
( Clean up existing example files)
( Delete existing example files )
//udiDeleteError1:=SysFileDelete(szFileName:=sFirstF ileName );
//udiDeleteError2:=SysFileDelete(szFileName:=sThirdF ileName );
( delete the directory )
//udiDirDeleteError:= SysDirDelete(szDir:= sDirName);
( create a new directory )
udiCreateError := SysDirCreate(szDir:= sDirName);
( two files are created and stored into the directory)
udiFileHandle := SysFileOpen(szFile:=sFirstFileName, am:=AM_WRITE_PLUS, pResult:=ADR(ErrorCode));
IF udiFileHandle <> RTS_INVALID_HANDLE THEN
SysFileClose(hFile:=udiFileHandle);
END_IF
udiFileHandle := SysFileOpen(szFile:=sSecondFileName, am:=AM_WRITE_PLUS, pResult:=ADR(ErrorCode));
IF udiFileHandle <> RTS_INVALID_HANDLE THEN
SysFileClose(hFile:=udiFileHandle);
END_IF
( open the directory
the handle is returned and the first directory entry. Normally the first entry is "." and the second "..")
udiDirHandle := SysDirOpen(szDir:= sDirName, szDirEntry:= sDirEntry, diMaxDirEntry:= 1024,
pDirInfo:= ADR(stDirInfo), pResult:= udiResult);
( Iterate through all directory entries and count them. The implicit entries with points are not count.
when the last entry is reached the SysDirRead always delivers the last entry.)
iFilesCount := 0;
programcount := 1;
REPEAT
IF FIND(sDirEntry, '.') <> 1 THEN
iFilesCount := iFilesCount +1;
END_IF
udiReadError:= SysDirRead(hDir:= udiDirHandle, szDirEntry:= sDirEntry, diMaxDirEntry:= 1024, pDirInfo:=ADR(stDirInfo) );
// SysDirRead is used to Directory Info
// Here, Im using SysDirRead to Find Folder Names within a Directory
// If stDirInfo.diDirectory is Hex 2 , then the Directory is a folder, otherwise Hex 0 is a File
IF stDirInfo.diDirectory = 16#2 AND Find(sDirEntry,'.') <> 1 THEN
programnames[programcount]:=sDirEntry;
programcount:=programcount+1;
END_IF
UNTIL
udiReadError = CmpErrors.Errors.ERR_END_OF_OBJECT
END_REPEAT
( The two created files must be read.)
//IF iFilesCount <> 2 THEN
// xError := TRUE;
//END_IF
( Close the directory )
udiCloseError := SysDirClose(hDir:= udiDirHandle);
( Rename a file )
udiRenameError:=SysFileRename(szOldFileName:= sSecondFileName, szNewFileName:= sThirdFileName);
( the test is set to done, if no error occured )
IF udiCreateError = 0 AND udiCloseError = 0 AND udiRenameError = 0 AND xError = FALSE THEN
xTestDone := TRUE;
ELSE
xError := TRUE;
END_IF
xStartTest := FALSE;
END_IF
Thank you for sharing this.
For your information:
There is a "Use Case" library "File access". This contains the CAA File library in which there are function blocks for opening, listing and closing libraries.
In functionality it is pretty much similar to the SysLib library, but it is made according to the V3 CODESYS library guidelines.
A difference is that it is not blocking, which means that in your case if you have a long list of directories, you will not have the problem of having long scan times.
In the code you should call the FB's with Execute set to TRUE. When the result is done or error you can call the next FB or do some error handling.
When finished, call the FB's with Execute set to FALSE.
In the CODESYS help you can find some examples (see Libraries => System Libraries => CAA Libraries => CAA_File.library).