[英]Decompress a GZip Stream in Dynamics AX X++
我正在尝试在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);
}
您是否可以在代码周围添加try catch以查看得到的确切消息,因为Ax中有2个错误并不能真正告诉您发生了什么:
第一个是.net在.NET类型的构造函数中遇到问题,并且可能有多种原因,因此异常详细信息应该能够为您提供帮助。
第二个可能更困难,因为它可能是找不到的程序集。 但是在那种情况下,您可能会了解正在寻找什么文件的信息,并且应该将您带到Axe期望它们所在的位置。 (因此,将您的程序集放入“全球程序集”案例中无疑是一个好主意。
要从异常中获取更多信息,您可以执行以下操作:
catch (Exception::CLRError)
{
ex = ClrInterop::getLastException();
if (ex != null)
{
ex = ex.get_InnerException();
while (ex != null)
{
error(ex.ToString());
ex = ex.get_InnerException();
}
}
}
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();
}
}
让我知道这是否对您有用。
干杯
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.