Axapta 在Dynamics AX X+中解压缩GZip流+;
我试图在X++中压缩.NETGzipstream,但遇到了一个bug。创建字符串的.NET代码非常简单:Axapta 在Dynamics AX X+中解压缩GZip流+;,axapta,x++,ax,Axapta,X++,Ax,我试图在X++中压缩.NETGzipstream,但遇到了一个bug。创建字符串的.NET代码非常简单: private string CompressString() { string stringToCompress = "Some data here"; string result = string.Empty; using (MemoryStream output = new MemoryStream())
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);
}
静态无效作业2(Args\u Args)
{
系统。字符串解码字符串;
字节[]缓冲区;
System.IO.Compression.GZipStream gzip;
System.IO.StreamReader;//您能否在代码周围添加一个try catch以查看您得到的确切消息,因为Ax中有两个错误并不能真正告诉您发生了什么:
- 调用的目标已引发异常
- 无法创建CLR对象
第一个是.net在.net类型的构造函数中遇到问题,可能有各种原因,因此异常详细信息应该能够帮助您
第二个可能会更困难,因为它可能是找不到的程序集。但是在这种情况下,您可能有关于正在查找的文件的信息,并且应该将您引导到Ax希望它们位于的位置。(因此,首先将您的程序集放在全局程序集案例中当然是一个好主意。)
要从异常中获取更多信息,可以执行以下操作:
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的方法的问题是,许多CLR互操作错误的级别都会突破Dynamics AX X++catch子句,而不管它被指定用于捕获异常::CLRRERROR。我以前在使用System.IO方法(如文件移动/删除)时遇到过这种情况
更好地查看错误的一种方法(因为在X++中无法正确捕获错误)是在.NET代码中重写作业,并使用完全能够捕获错误的.NET catch块。在C#console应用程序中构建对象,并重新创建封装在.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();
}
}
让我知道这对你是否有效
干杯您的AX的client\bin目录和/或GAC中是否都有合适的DLL?我只能假设我与客户端在同一台计算机上运行Visual Studio。是否有我应该查找的特定内容?抱歉,我猜错误消息不清楚。原因是“无法创建对象'CLROBOCT'”。我将更新该问题以使其更准确。请尝试将适当的DLL与AX32放在同一文件夹中。我公司的另一位开发人员建议,该错误可能是代码访问权限错误,但在添加断言时我看不出有什么不同。我已将调用包装在Try/Catch中(上面更新的代码),但是catch块从未运行。尝试运行writer=new System.IO.StreamWriter(gzip)后,代码立即停止执行;
。我公司的另一位开发人员建议,该错误可能是代码访问权限错误,但我在添加断言时看不出有什么区别。啊,太好了。这正是我所需要的。结果(令人尴尬地)当我应该使用System.IO.StreamWriter
时,我使用了System.IO.StreamWriter
。异常非常明显(不是一个可写流)。将AX代码切换到相同的版本修复了问题。