axaptadynamics-ax-2009ax

Try to use Winapi::findFirstFile running on server


I have a problem trying to run Winapi::findFirstFile running on server. I havve already tried copying the method on the class WinapiServer, and changing some lines, like this:

server static container findFirstFile(str filename)
{
    InteropPermission interopPerm;
    Binary data;
    DLL _winApiDLL;
    DLLFunction _findFirstFile;
    ;

    interopPerm = new InteropPermission(InteropKind::DllInterop);
    interopPerm.assert();

    data = new Binary(592); // size of WIN32_FIND_DATA when sizeof(TCHAR)==2
    _winApiDLL = new DLL(#KernelDLL);
    _findFirstFile = new DLLFunction(_winApiDLL, 'FindFirstFileW');

    _findFirstFile.returns(ExtTypes::DWord);

    _findFirstFile.arg(ExtTypes::WString,ExtTypes::Pointer);

    return [_findFirstFile.call(filename, data),data.wString(#offset44)];
}

But now I have another kind of error The function 'FindFirstFileW' on the library DLL 'KERNEL32' throws an exception.

This is because I'm executing the method on a x64 server. Anyone with an idea for solving this problem?


Solution

  • Here is a sample code that has worked for me in both client side as well as server side. It uses .NET namespaces to fetch the list of files in a given folder path for a given pattern.

    You can modify this to create your own server side version of FindFirstFile method.

    X++ Code

    static container findMatchingFiles(
            str _folderPath
        ,   str _filePattern   = '*.*')
    {
        System.IO.DirectoryInfo     directory;
        System.IO.FileInfo[]        files;
        System.IO.FileInfo          file;
        InteropPermission           permission;
    
        str         fileName;
        counter     filesCount;
        counter     loop;
        container   mathchingFiles;
        ;
    
        permission  = new InteropPermission(InteropKind::ClrInterop);
        permission.assert();
    
        directory   = new System.IO.DirectoryInfo(_folderPath);
        files       = directory.GetFiles(_filePattern);
        filesCount  = files.get_Length();
    
        for (loop = 0; loop < filesCount; loop++)
        {
            file            = files.GetValue(loop);
            fileName        = file.get_FullName();
            mathchingFiles  = conins(mathchingFiles, conlen(mathchingFiles) + 1, fileName);
        }
    
        CodeAccessPermission::revertAssert();
    
        return mathchingFiles;
    }
    

    Test job

    To test the above code, I created the following sample files in the path C:\temp\Files\

    List of files

    I placed the above mentioned method in a sample class named Tutorial_WinApiServer. Then, created a job named fetchFiles with the following code.

    static void fetchFiles(Args _args)
    {
        container   files;
        counter     loop;
        str         fileName;
        ;
    
        files = Tutorial_WinApiServer::findMatchingFiles(@'C:\temp\Files', '*.txt');
    
        for (loop = 1; loop <= conlen(files); loop++)
        {
            fileName = conpeek(files, loop);
            info(fileName);
        }
    }
    

    Executing the job gave the following output.

    Job Output 1

    After changing the file pattern to F*.*, the job produced the following output.

    Job Output 2

    Hope that helps.