2

我正在尝试在 X++ 中对 .NET GZIPStream 进行放气,但遇到了一个错误。创建字符串的 .NET 代码非常简单:

    private string CompressString()
    {
        string stringToCompress = "Some data here";
        string result = string.Empty;

        using (MemoryStream output = new MemoryStream())
        using (GZipStream gzip = new GZipStream(output, CompressionMode.Compress, true))
        using (StreamWriter writer = new StreamWriter(gzip))
        {
            writer.Write(stringToCompress);
            writer.Close();
            result = Convert.ToBase64String(output.ToArray());
        }

        return result;
    }

AX 端将通过一些 Web 服务调用获取压缩字符串。我目前拥有的 X++ 代码如下,但在创建 StreamWriter 时出现错误“无法创建对象 'CLRObject'”。

static void Job2(Args _args)
{
   System.String decodedString;
   System.Byte[] buffer;
   System.IO.Compression.GZipStream gzip;
   System.IO.StreamWriter writer;
   System.IO.MemoryStream output;
   InteropPermission permission;
   CLRObject ex;

   str compressedString ="Compressed data here";
   ;

   ttsBegin;
   permission = new InteropPermission(InteropKind::ClrInterop);
   permission.assert();

   buffer = System.Convert::FromBase64String(compressedString);
   output = new System.IO.MemoryStream(buffer);
   gzip = new System.IO.Compression.GZipStream(output, System.IO.Compression.CompressionMode::Decompress);

   try {
       //Error here: "Object 'CLRObject' could not be created"
       writer = new System.IO.StreamWriter(gzip);
       writer.Write(decodedString);
       writer.Close();

       CodeAccessPermission::revertAssert();
   } 
   catch (Exception::CLRError) {
       //Code never executes past this point 
       ex = CLRInterop::getLastException();

       while(ex != null) {
           error(ex.ToString());
           ex = ex.get_InnerException();
       }
   }

   ttsCommit;
   info(decodedString);
}

编辑:基于@robert-allen 下面的答案,在 AX 中完成此操作的正确代码是:

static void Job2(Args _args)
{
   System.String decodedString;
   System.Byte[] buffer;
   System.IO.Compression.GZipStream gzip;
   System.IO.StreamReader reader; //<-- Reader instead of writer
   System.IO.MemoryStream output;
   InteropPermission permission;
   CLRObject ex;

   str compressedString ="Compressed data here";
   ;

   ttsBegin;
   permission = new InteropPermission(InteropKind::ClrInterop);
   permission.assert();

   buffer = System.Convert::FromBase64String(compressedString);
   output = new System.IO.MemoryStream(buffer);
   gzip = new System.IO.Compression.GZipStream(output, System.IO.Compression.CompressionMode::Decompress);

   try {
       //Reader code changes
       reader = new System.IO.StreamReader(gzip);
       decodedString = reader.ReadToEnd();
       reader.Close();
       //End reader code changes

       CodeAccessPermission::revertAssert();
   } 
   catch (Exception::CLRError) {
       //Code never executes past this point 
       ex = CLRInterop::getLastException();

       while(ex != null) {
           error(ex.ToString());
           ex = ex.get_InnerException();
       }
   }

   ttsCommit;
   info(decodedString);
}
4

2 回答 2

4

您能否在代码周围添加一个 try catch 以查看您得到的确切消息,因为 Ax 中有 2 个错误并不能真正告诉您发生了什么:

  • 调用的目标已引发异常
  • 无法创建 CLRObject

第一个是 .net 在 .NET 类型的构造函数中遇到问题,并且可能有多种原因,因此异常详细信息应该能够帮助您。

第二个可能更困难,因为它可能是无法找到的程序集。但在这种情况下,您可能会获得有关正在查找的文件的信息,并且应该将您带到 Ax 期望它们所在的位置。(出于这个原因,首先将您的程序集放在 Global Assembly 案例中当然是一个好主意。

要从异常中获取更多信息,您可以执行以下操作:

catch (Exception::CLRError)
{
     ex = ClrInterop::getLastException();
     if (ex != null)
     {
        ex = ex.get_InnerException();
        while (ex != null)
        {
            error(ex.ToString());
            ex = ex.get_InnerException();
        }
    }
}
于 2013-01-21T22:10:41.753 回答
3

Kenny Saelen 的方法的问题在于,许多 CLRInterop 错误的级别如此之高,以至于它们会突破 Dynamics AX X++ catch 子句,而不管它是否被指定为捕获 Exception::CLRError。我以前在使用文件移动/删除等 System.IO 方法时遇到过这种情况。

更好地查看错误的一种方法(因为您无法在 X++ 中正确捕获它)是在 .NET 代码中重写您的工作并使用完全能够捕获该错误的 .NET catch 块。在 C# 控制台应用程序中构建对象并重新创建封装在 .NET try/catch 中的相同行为。

像这样的东西:

static void Main(string[] args)
{
    System.String decodedString;
    System.Byte[] buffer;
    System.IO.Compression.GZipStream gzip;
    System.IO.StreamWriter writer;
    System.IO.MemoryStream output;

    string compressedString = "sample";

    buffer = System.Convert.FromBase64String(compressedString);
    output = new System.IO.MemoryStream(buffer);
    gzip = new System.IO.Compression.GZipStream(output, System.IO.Compression.CompressionMode.Decompress);

    try
    {
        writer = new System.IO.StreamWriter(gzip);
        writer.Write(decodedString);
        writer.Close();

        Console.Write(decodedString);
        Console.ReadKey();
    }
    catch (Exception ex)
    {
        Console.Write(ex.Message);
        Console.ReadKey();
    }
}

让我知道这是否适合你 Spankachu。

干杯

于 2013-01-22T20:33:10.573 回答