Question Status

Verified
Vincent Verweij asked a question on 19 Nov 2012 12:35 AM

Hello everyone,

 

I have a class that queries for data with direct SQL. I execute a query and do a while-loop on my resultset.
In the while-loop itself I fill a file which needs to be stored on a specific location.

I am working for a couple months in AX so I still need to learn many things.

I started with the following code:
...

FileIoPermission    filepermission;
FileName    tempGeneratedFile;
AsciiIo    tempFile;
str    output;
;

filepermission = new FileIoPermission(tempGeneratedFile, 'w');
filepermission.assert();

tempFile = new AsciiIo(tempGeneratedFile, 'w');

... some logic / sql statement ...

while(resultSet.next())
{
    ... some logic for the lines that will be written in the file ...
    tempFile.write(output);
}

CodeAccessPermission::revertAssert();

...

Now when I compile this code above, i get the best practice: TwC: Assert usage of API AsciiIo.new because it is protected by Code Access Security.

I search on google for a solutions, but I can't make it disappear. I thought the CodeAccessPermission::revertAssert would do the thing, but it didn't.
I have 2 other classes that use similar coding and what I do extra there is set tempFile = null after the while-loop (I have read it somewhere) but that didn't help as well.

This best practice is not the worst thing to happen, but when I execute one of these classes in batch I get the following error (and batch status error) after full execution:
Request for the permission of type 'FileIoPermission' failed.
(S)\Classes\FileIoPermission\demand
(S)\Classes\WinAPIServer\getTempPath - line 13
...

So I search for this error, but I couldn't find a proper solution.

Does anyone has experienced this before and provide me a working solution ?

 

Thanks in advance,

Vincent

Reply
Martin Dráb responded on 19 Nov 2012 2:33 AM

The error is in getTempPath() and that is not shown in your example. Be sure that you assert the permissions before calling getTempPath().

By the way, when you know that the permissions are handled correctly, you can suppress the BP error by adding // BP validation documented comment just above the line with new AsciiIo().

Martin "Goshoom" Dráb | Freelancer | Goshoom.NET Dev Blog

Reply
Vincent Verweij responded on 19 Nov 2012 2:46 AM

#define.maxPath(260)
public server static str getTempPath()
{
    FileIOPermission fileIOPerm;
    InteropPermission interopPerm;
    str tempPath;

     // check file I/O permission
    fileIOPerm = new FileIOPermission('','r');
    fileIOPerm.demand();

    // get dll interop permission
    interopPerm = new InteropPermission(InteropKind::ClrInterop);
    interopPerm.assert();

    tempPath = System.IO.Path::GetTempPath();
    return tempPath;
}

This is the getTempPath method. It is on line 13 (which in my code editor is the line in bold).

Since I didn't implement the code access permission before, I don't know if it is handled correctly, so suppressing it would be bad :-)
Just before the getTempPath method is called there is a line: filepermission.assert(); so the permission is asserted before calling getTempPath().

Thanks for answering, but do you have any suggestion what I am doing wrong now ?


Kind regards,
Vincent

Reply
Martin Dráb responded on 19 Nov 2012 3:26 AM

Sorry, that's not what I meant. Can you should the code where you actually call getTempPath()? You say that you have the assertion there, but if everything was correct, it would work.

Martin "Goshoom" Dráb | Freelancer | Goshoom.NET Dev Blog

Reply
Vincent Verweij responded on 19 Nov 2012 3:44 AM

This is a class where I need to extend from, so this should be right (at least I hope so).

    SysMailer           sysMailer;
    FCS_DateTimeString  randomFileName;

    FileIoPermission    filepermission;
    InteropPermission   interopPermission;
    Set                 permissionSet;

    str                 tempPath;

    str                 txt;
    UtcDateTime         utcSendTime;
    ;

    interopPermission = new InteropPermission(InteropKind::ComInterop);
    interopPermission.assert();
    sysMailer = new SysMailer();
    CodeAccessPermission::revertAssert();

    randomFileName = FCS_DateTimeAPI::value2displayFormat(FCS_DateTimeAPI::now(), 'yyyy-MM-dd_HHmm-ss');

    // RND_00002872_223 - WinAPIServer vs WinAPI
    filepermission = new FileIoPermission(fileName, 'r');
    filepermission.assert();

    // BP Deviation Documented
    tempPath = isRunningOnServer() ? WinAPIServer::getTempPath() : WinAPI::getTempPath();
    CodeAccessPermission::revertAssert();
    // End
    ...

Again the bold line is where it calls for getTempPath().

Reply
Martin Dráb responded on 19 Nov 2012 4:50 AM

The problem is that you set FileIoPermissions for the file defined in fileName variable, but getTempFileName() expects permissions for an empty string.

You code should really looks this way:

filepermission = new FileIoPermission('', 'r');

Martin "Goshoom" Dráb | Freelancer | Goshoom.NET Dev Blog

Reply
Vincent Verweij responded on 19 Nov 2012 5:12 AM

Ok I agree with your suggestion that the first parameter should be empty in this case.

When I execute and look at the content of variable fileName, then I see: filename = "".

So if filename is empty it will have the syntax like you provide with the only exception that the first param '' is now filled with an empty string variable.

Thanks for helping me, still ideas ?

Reply
Martin Dráb responded on 19 Nov 2012 5:31 AM

Please, don't try to debug all code in the same time. Test getTempPath() in a separate class just asserting permissions and obtaining the file name. It works for me and it should work for you as well.

Martin "Goshoom" Dráb | Freelancer | Goshoom.NET Dev Blog

Reply
Vincent Verweij responded on 19 Nov 2012 5:41 AM

It works when I execute it myself. From the moment that I execute the class in batch, it fails.

Did you try it in batch too ?

Reply
Martin Dráb responded on 19 Nov 2012 6:32 AM

This batch class does work for me without any problems (in AX2009). Try it yourself.

Martin "Goshoom" Dráb | Freelancer | Goshoom.NET Dev Blog

Reply
Vincent Verweij responded on 19 Nov 2012 7:40 AM

I will try this asap. I am also working in AX2009 for the current project.

So if this is working, then the fileName var should be replaced by '', as you stated above ?

Reply
Verified Answer
Vincent Verweij responded on 28 Nov 2012 7:43 AM

Your solution didn't work for me.

The problem was that batch (user) didn't have enough access to the temp directory.

By replacing it from temp to a networkshare were it has access to, the problem was solved.

Thanks for your effort, I hope this helps other people too.

Kind regards,

Vincent

Reply
Martin Dráb responded on 28 Nov 2012 8:43 AM

Correct code access permissions are not enough if you don't have file access permissions, of course.

Martin "Goshoom" Dráb | Freelancer | Goshoom.NET Dev Blog

Reply
Verified Answer
Vincent Verweij responded on 28 Nov 2012 7:43 AM

Your solution didn't work for me.

The problem was that batch (user) didn't have enough access to the temp directory.

By replacing it from temp to a networkshare were it has access to, the problem was solved.

Thanks for your effort, I hope this helps other people too.

Kind regards,

Vincent

Reply