Welcome to our new forum
All users of the legacy CODESYS Forums, please create a new account at account.codesys.com. But make sure to use the same E-Mail address as in the old Forum. Then your posts will be matched. Close

How do I list the folder names found in a PLC Directory?

2015-04-30
2015-05-07
  • EnterDownload - 2015-04-30

    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

     
  • EnterDownload - 2015-05-05

    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

     
  • TimvH

    TimvH - 2015-05-07

    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).

     

Log in to post a comment.