普段、Dynamics CRM の sdk で提供される dll を使用して CrmService を使用しているため、出くわさなかったのですが、先日、crmservice.asmx から取得できる wsdl から作成したCrmService のプロキシクライアント経由で CrmService にアクセス使用とすると次のエラーが発生したため、その対処方法を記載します。

1.問題の発生した環境

問題の発生した環境とエラー内容は次のとおりです。

  • Windows Server 2003 R2 64bit Dynamics CRM オールインワン環境
  • wsdl から CrmService プロキシクライアントを作成して CrmService にアクセスするプログラムを実行

作成したプログラムをCRMと同じサーバ上から実行すると次のエラーが発生しました

一時クラスを生成できません (result=1)
error CS0001: 内部コンパイルエラー (0xc00000fd)
error CS0003:メモリが不足しています

 場所 System.Xml.Serialization.Compiler.Compile(Assembly ...

いろいろ調べてみると(というかググって見ると) 64bit 環境で発生する sgen のバグらしいです。通常、wsdlからクライアントプロキシクラスを作成した場合、sgenを使用して事前にプロキシクラス用のdllを作成していないと、実行時に.NET が プロキシクラスからWebサービス呼び出し用のクラスをsgen を使用して生成、コンパイルします。そのときにエラーが発生しているそうです。

2. 解決方法

あらかじめ、sgen.exe を使用して 実行時に作成されていたWebサービス用のクライアントをWsdlを使用して作成したプロキシクラスから事前に作成しておけば問題ないようです。プログラムを作成した環境は32bit 環境だったので, Visual Studio 2008 コマンドプロンプトを起動し、次のコマンドを入力して、事前のコンパイル済みのプロキシクラスの dll を作成しました。

sgen /a:TestService.exe /p

ここで、TestService.exe はwsdl から作成したプロキシクラスを含むアセンブリです。作成が成功すると、TestService.XmlSerializer.dll が作成されます。アセンブリ名の名前はコマンドラインの/a オプションで指定したアセンブリ名に依存します。

sgen によって作成されたdllとexe を同階層に配置し、 2003 R2 64 bit の環境でプログラムを実行するとエラーが発生せずプログラムが実行できました。

3. まとめ

今回の説明は以上です。

wsdlから作成したプロキシクラスはXmlSerializer の事前コンパイルクラスと同じものだと勘違いして理解していたため、実行時にXmlSerializer 用のクラスが生成されていると知り、勉強になりました。CrmService に限らず、 XmlSerializer が内部的に使用されたり、シリアライズに利用する場合に、sgen を使用してXmlSerializer 用のクラスのプリコンパイルを生成することはよいプラクティスであるということは知っていたのですが。

間違い、指摘点などありましたらご連絡ください。