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

Axeには2つのエラーがあり、実際に何が起こっているのかを教えてくれないため、コードの周りにtry catchを追加して、表示される正確なメッセージを確認できますか?

  • 呼び出しのターゲットによって例外がスローされました
  • CLRObjectを作成できませんでした

1つ目は、.NETタイプのコンストラクターで問題が発生している.netであり、さまざまな理由が考えられるため、例外の詳細が役立つはずです。

2つ目は、見つからないアセンブリである可能性があるため、より困難になる可能性があります。しかし、その場合、どのファイルが検索されているかについての情報を持っている可能性があり、Axeがそれらを期待する場所にあなたを導くはずです。(そのため、アセンブリをグローバルアセンブリケースに入れることから始めることは確かに良い考えです。

例外からより多くの情報を取得するには、次のようにします。

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 エラーが、Exception::CLRError をキャッチするように指定されているにもかかわらず、Dynamics AX X++ の catch 句を突破するレベルにあることです。ファイルの移動/削除などの System.IO メソッドを使用しているときに、これに遭遇したことがあります。

エラーをよりよく確認する 1 つの方法 (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 に答える