Announcements
Hi Experts.
I get error while deleting the file using system.io delete during batch job. however get no error & fiile get successfuly deleted when running same code as non btach.
Please suggest fix for following
1. How do i get to delete the file in batch & non batch mode
2. How do i get to move the file in batch & non batch mode.
3. Currently it does not capture the details of why the batch job failed, what can i do to improvise my catch block so that it capture the details of generic failures i.e. exception from info cllass's add exception .
Here is the complete code. Thanks in advance.
public void run() { str fileNameString,fileNamePath; MyCustom msg; System.IO.DirectoryInfo directory,processedDirectory; System.IO.FileInfo[] files; System.IO.FileInfo file; //Set permissionSet; InteropPermission permission; counter filesCount; FilePath processedFilePath,processedFileCompletePath; Filename filename,filepath,fileType; Filename tmpFilePath; Filename tmpFileNameShort; Filename tmpFileExt; counter loop; str fileNameOnly,fileNameTemp; filetype type; boolean skipZeroTrans; boolean wrongFileFormat = false; #FILE try { permission = new InteropPermission(InteropKind::ClrInterop); permission.assert(); select myCustomTable; skipZeroTrans = myCustomTable.skipZeroTransVal; directory = new System.IO.DirectoryInfo(@myCustomTable.FilePath); filepath = @myCustomTable.myCustomTablelFilePath; processedDirectory = new System.IO.DirectoryInfo(@myCustomTable.ProcessedFilePath); processedFilePath = @myCustomTable.ProcessedFilePath; files = directory.GetFiles("*.csv*"); filesCount = files.get_Length(); for (loop = 0; loop < filesCount; loop ) { file = files.GetValue(loop); fileNameTemp = file.get_FullName(); filename = fileNameTemp; info(strFmt("filename: %1",filename)); if (strLen(fileNameTemp) > 0) { [tmpFilePath, tmpFileNameShort, tmpFileExt] = fileNameSplit(fileNameTemp); fileNameString= tmpFileNameShort tmpFileExt; info(strFmt('Import filename=%1', fileNameTemp)); if(tmpFilePath && tmpFileNameShort && tmpFileExt == #csv) { msg = this.processFile(fileNameTemp,skipZeroTrans); } else { if (strLen(tmpFilePath) == 0) { error("Filepath not specified"); } wrongFileFormat = true; Error (strFmt("%1 unsupported fileType", tmpFileExt)); } if ( strScan(msg,"Error",0,strLen(msg))) { throw error("Error encountered while processing file"); } this.myWriteMessage(tmpFilePath,tmpFileNameShort,msg); info(msg); System.IO.File::Delete(filename); //TODO 1 RUNS FINE IN NON BATCH MODE BUT ERRORS IN BATCH MODE ONCE FIXED USE either DELETE or MOVE // CHECK FILE MOVE CODE /* // processedFilePath = processedFilePath "\n\\" tmpFileNameShort; //permissionSet = new Set(Types::Class); //permissionSet.add(new FileIOPermission(filename, #io_write)); //permissionSet.add(new FileIOPermission(processedFilePath, #io_write)); //permissionSet.add(new InteropPermission(InteropKind::ClrInterop)); //CodeAccessPermission::assertMultiple(permissionSet); // CodeAccessPermission::revertAssert(); //processedFileCompletePath = processedFilePath "\n\\" tmpFileNameShort tmpFileExt; //System.IO.File::Move(filename,processedFileCompletePath); //System.IO.File::Move(fileName, newFileName); */ //TODO 2 ERRORS IN BOTH BATCH & NON BATCH MODE } }// for ends } // Try ends catch { if (wrongFileFormat == true) { this.myWriteMessage(tmpFilePath,tmpFileNameShort,msg); throw Error (strFmt("%1 Unsupported file type", fileType)); } else if (Exception::Error && Exception::CLRError) { this.myWriteMessage(tmpFilePath,tmpFileNameShort,msg); throw Error (msg "Exception" ); //TODO 3 Explore how can you replace "Exception" with exception from info add exception so as to capture the details of geneic failures. } else if (Exception::DuplicateKeyException && Exception::DuplicateKeyExceptionNotRecovered) { this.myWriteMessage(tmpFilePath,tmpFileNameShort,msg); throw error(strFmt("Error encountered while processng the file. \n Read log at %1 path for details",tmpFilePath)); } } }//Run method ends
Thanks
Mav
Thanks all for responding this mystr = directory + @"\"+mystr+@".txt"; fixed my moving file issue.
Hi Martin,
Thank you for great comments and the rich-format makes the code looks better.
Mav, \ is a special character - notice that you also use it for \n. You need \\ to represent \, or use a verbatim string (e.g. str path = @'c:\temp\file.txt').
Leo.Wang, please use Insert > Insert Code (in the rich-formatting view) to paste source code. This is the result:
Boolean res = true; System.Text.UTF8Encoding encode; System.IO.FileStream fs; System.Byte [] info; System.String fileName; System.IO.StreamWriter sw; str mystr; System.Exception ex; try { new InteropPermission(InteropKind::ClrInterop).assert(); encode = new System.Text.UTF8Encoding(true); info = encode.GetBytes("Create test content"); mystr = System.Guid::NewGuid().ToString("N"); mystr = directory @"\" mystr @".txt"; fileName = mystr; fs = System.IO.File::Create(fileName); fs.Write(info, 0, info.get_Length()); fs.Close(); fs.Dispose(); sw = System.IO.File::AppendText(fileName); sw.Write("Modify test content"); sw.Close(); sw.Dispose(); System.IO.File::Delete(fileName); CodeAccessPermission::revertAssert(); } catch(Exception::CLRError) { ex = ClrInterop::getLastException(); if (ex != null) { ex = ex.get_InnerException(); if (ex != null) { error(ex.ToString()); } } CodeAccessPermission::revertAssert(); res = false;
A few comments to this code:
I think i found the issue which is that my processedFilePath does not contain "\" this in end which leads my
processedFileCompletePath to something like "C:\myFiles\ Processed file myFile1.xls"
where as objective is to get values like below C:\myFiles\Processed file \ myFile1.xls (Which is correct path)
For processedFilePath i have tried using both below approach but none of below approach helped me in getting "\" after the filepath.
processedDirectory = new System.IO.DirectoryInfo(@myCustomTable.myProcessedFilePath);
processedFilePath = @myCustomTable.myProcessedFilePath;
& if i forcefully add "\" by using code
processedFileCompletePath = processedFilePath+"\n\\"+tmpFileNameShort+ tmpFileExt;
I get illegal value in path error.
Can you please suggest a fix.
Here is an demo to catch the error information when using .net:
Boolean res = true;
System.Text.UTF8Encoding encode;
System.IO.FileStream fs;
System.Byte [] info;
System.String fileName;
System.IO.StreamWriter sw;
str mystr;
System.Exception ex;
;
try
{
new InteropPermission(InteropKind::ClrInterop).assert();
encode = new System.Text.UTF8Encoding(true);
info = encode.GetBytes("Create test content");
mystr = System.Guid::NewGuid().ToString("N");
mystr = directory + @"\"+mystr+@".txt";
fileName = mystr;
fs = System.IO.File::Create(fileName);
fs.Write(info, 0, info.get_Length());
fs.Close();
fs.Dispose();
sw = System.IO.File::AppendText(fileName);
sw.Write("Modify test content");
sw.Close();
sw.Dispose();
System.IO.File::Delete(fileName);
CodeAccessPermission::revertAssert();
}
catch(Exception::CLRError)
{
ex = ClrInterop::getLastException();
if (ex != null)
{
ex = ex.get_InnerException();
if (ex != null)
{
error(ex.ToString());
}
}
CodeAccessPermission::revertAssert();
res = false;
}
I am able to delete the fils via system IO using myTextIO.finalize()
However when trying to move the file from 1 folder to other i keep getting the below error message even when there is no file in the destination folder
System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.IO.IOException: Cannot create a file when that file already exists.
at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
at System.IO.File.InternalMove(String sourceFileName, String destFileName, Boolean checkHost)
at Dynamics.Ax.Application.myclass.run.() in myclass.run.xpp:line 105
--- End of inner exception stack trace --
Change made to code shared earlier for moving file to different folder.
//System.IO.File::Delete(filename); commented delete action processedFileCompletePath = processedFilePath tmpFileNameShort tmpFileExt; // Uncommented these 2 lines for moving the file System.IO.File::Move(filename,processedFileCompletePath);
I think this may go away by using Text IO .finalize(). Will try & use .finalize() to see if it helps & update this thread.
Hi Martin after using CLRInterop::getLastException().ToString(); i got this in error message
System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.IO.IOException: The process cannot access the file 'Filepath\myCSVFILE1.csv' because it is being used by another process.
at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
at System.IO.File.InternalDelete(String path, Boolean checkHost)
at Dynamics.Ax.Application.myClass.Run() in myClass.run.xpp:line 96 (LINE 96 is System.IO.File::Delete(filename))
--- End of inner exception stack trace ---
Thanks
Mav
Thanks Martin, will look in into your suggestion.
BTW Captured this in my event viewer
"Object Server 01:
Microsoft.Dynamics.Ax.Xpp.BreakException: Exception of type 'Microsoft.Dynamics.Ax.Xpp.BreakException' was thrown. at Microsoft.Dynamics.Ax.MSIL.Interop.throwException(Int32 ExceptionValue) at Microsoft.Dynamics.Ax.MSIL.cqlClassIL.create(Int32 classId, Object[] parameters, Type[] types, Object[] varargs, Type[] varargsTypes, Object ILObject) at Microsoft.Dynamics.Ax.Xpp.XppObjectBase.createKernelClass(Object[] parameters, Type[] paramTypes, Object[] varargs) at Dynamics.Ax.Application.SkipAOSValidationPermission.new() at Dynamics.Ax.Application.SkipAOSValidationPermission..ctor() at Dynamics.Ax.Application.BatchRun.serverFinishTask(Int64 batchId, Boolean isErrorCaught, Exception exception, BatchRunType batchRunType, Int32 infoCnt, Boolean , Boolean ) in BatchRun.serverFinishTask.xpp:line 10 at Dynamics.Ax.Application.BatchRun.@serverFinishTask(Int64 batchId, Boolean isErrorCaught, Exception exception, BatchRunType batchRunType, Boolean ) at Dynamics.Ax.Application.BatchRun.serverFinishTask(Int64 batchId, Boolean isErrorCaught, Exception exception) at BatchRun::serverFinishTask(Object[] ) at Microsoft.Dynamics.Ax.Xpp.ReflectionCallHelper.MakeStaticCall(Type type, String MethodName, Object[] parameters) at BatchIL.taskThreadEntry(Object threadArg)
"
Thanks
Mav
I would focus on the code in question; the status in AX doesn't sound relevant to me. If you have problem with debugging, try recompiling code and generating full CIL. And review your debugging setup in Visual Studio (e.g. "Enable just my code").
Regarding your catch clause, I have no idea what you hope to achieve by conditions like if (Exception::Error && Exception::CLRError). It makes no sense to me.
To catch CLR exceptions, use something like this:
catch (Exception::CLRError) { throw error(AifUtil::getClrErrorMessage()); } catch { ... }
getClrErrorMessage() gives you just a message of the inner exception. If you want more details, use CLRInterop::getLastException().ToString().
I don't know what code you have in myWriteMessage(), but I suggest removing it for now, because it may be throwing an exception when you're trying to handle other exceptions.
André Arnaud de Cal...
293,311
Super User 2025 Season 1
Martin Dráb
232,183
Most Valuable Professional
nmaenpaa
101,158
Moderator