2

問題を特定するためのテストコードは次のとおりです。

open Microsoft.FSharp.Metadata
[<EntryPoint>]
let main args =
  let core = FSharpAssembly.FromFile @"C:\Program Files\FSharp-2.0.0.0\\bin\FSharp.Core.dll"
  let core2 = FSharpAssembly.FSharpLibrary
  let core3 = System.AppDomain.CurrentDomain.GetAssemblies() 
              |> Seq.find (fun a -> a.FullName.Contains "Core") 
              |> FSharpAssembly.FromAssembly

  core.Entities |> Seq.iter (printfn "%A")
  0

3つすべてletが同じFSharpAssemblyを提供するはずです。代わりに、3つすべてがFSharp.CoreがF#アセンブリではないという例外をスローします(詳細は以下、読みやすくするために再フォーマットされています)。さらに2つの手がかり:

  1. このcore3メソッドを使用すると、テストF#アセンブリ自体にも同じエラーが発生します
  2. を実行した後、FSIでエラーが発生しません#r "@C:\Program Files...\FSharp.Powerpack.Metadata.dll"

何か案は?古いXPVMでVisualStudio2008、F#2.0、およびF#Powerpack 2.0.0.0(2010年5月20日)リリースを使用していますが、SP3に更新されていると思います。

(今朝、Powerpack 1.9.9.9でエラーが発生したので、2.0.0.0にアップグレードしました。1.9.9.9がF#の2.0.0.0のアセンブリを認識しない場合は、Powerpack2.0.0.0のバグ修正が役立つと思いました。 。)

Unhandled Exception: System.TypeInitializationException: 
  The type initializer for 'Microsoft.FSharp.Metadata.AssemblyLoader' threw an
    exception. 
  ---> System.TypeInitializationException: The type initializer for
    '<StartupCode$FSharp-PowerPack-Metadata>.$Metadata' threw an exception. 
  ---> System.ArgumentException: could not produce an FSharpAssembly 
    object for the assembly 'FSharp.Core' because 
    this is not an F# assembly
Parameter name: name
   at Microsoft.FSharp.Metadata.AssemblyLoader.Add(String name,Assembly assembly)
   at <StartupCode$FSharp-PowerPack-Metadata>.$Metadata..cctor()
   --- End of inner exception stack trace ---
   at Microsoft.FSharp.Metadata.AssemblyLoader..cctor()
   --- End of inner exception stack trace ---
   at Microsoft.FSharp.Metadata.AssemblyLoader.Get(Assembly assembly)
   at Microsoft.FSharp.Metadata.FSharpAssembly.FromAssembly(Assembly assembly)
   at Program.main(String[] args) in 
     C:\Documents an...\FSMetadataTest\Program.fs:line 11
Press any key to continue . . .
4

3 に答える 3

3

CodeplexのPowerpackソースを読んで、問題の直接の原因を見つけました。Powerpack.Metadataは、常にFSharp.Coreを他のアセンブリの前にロードするため、壊れている場合は残りをブロックします。

私の調査によると、他のほとんどのF#アセンブリは、「FSharpSignatureData。Package.Name」という名前のマニフェストリソースストリームでメタデータを伝送します。これは、メタデータライブラリが最初に表示される場所です。しかし、FSharp.Coreはそうではありません。(少なくとも、私のXP VMでは、VS 2008の2.0.0.0ダウンロードは行いません。)したがって、Powerpackメタデータは、FSharp.Core.dllを見つけるのと同じディレクトリでFSharp.Core.sigdataというファイルを探します。

コードは、このディレクトリ名を4か所探します。

  1. ConfigurationSettings.AppSettings。["fsharp-core-referenceassembly-location"]。
  2. レジストリキー@"SOFTWARE\Microsoft\.NETFramework\" + MSCorLibRunningRuntimeVersion + @"\AssemblyFoldersEx\Microsoft Visual F# 4.0"。MSCorLibRunningRuntimeVersionはリフレクションによって決定されます。私の場合は「v2.0.50727」です。これは、VS 2010、つまりF#4.0を使用している場合にのみ当てはまると思います
  3. レジストリキー@"Software\Microsoft\.NETFramework\AssemblyFolders\Microsoft.FSharp-" + FSharpTeamVersionNumber。FSharpTeamVersionNumberは、少なくともコードプレックスバージョンでは、「1.9.9.9」としてハードコードされています。2010年5月リリースのソースが自分のマシンにインストールされていません。
  4. System.AppDomain.CurrentDomain.BaseDirectory。fsiを使用していない限り、これはローカルプロジェクトの「bin/Debug」ディレクトリです。次に、C:\ Program Files \ FSharp-2.0.0.0\binのバリアントです。

私にとって、4つすべてが失敗します:

  1. アプリの設定ファイルがありません。.NETエコシステムについてはよくわからないので、作成方法がわかりません。
  2. VS2010をインストールしていません。
  3. 適切な場所に「Microsoft.FSharp-2.0.0.0」キーがありますが、「Microsoft.FSharp-1.9.9.9」キーがありません。
  4. 私のローカルプロジェクトでは、bin/DebugディレクトリにFSharp.Core.sigdataのコピーがありません。

何が起こっているのかがわかったので、いくつかの修正があります(約1か月で修正する予定の古いVMの代わりに実際のWindowsマシンを使用する以外に)。とにかく、ある時点で.NETの構成ファイルについて学ぶ必要があるので、それがおそらく最良の中期的な解決策です。レジストリキー「Microsoft.FSharp-1.9.9.9」を作成するか、FSharp.Core.sigdataをbin / Debugディレクトリにコピーすることは、非常に簡単な短期間の修正です。

このバグが広まっているのか、それともVS 2005-> 2008からのアップグレードと複数のF#プレビューが原因であるのかはまだわかりません。コードプレックスのソースを読んだところ、FSharpTeamVersionNumberが1.9.9.9としてハードコードされており、レジストリキー2.0.0.0に一致するように更新されていないため、VS2010を持たない他の人もこの問題を抱えているようです。しかし、F#2.0とF#Powerpack 2.0にアップグレードした順序が誤って混ざり合って、この状態が発生した可能性があります。または、メタデータライブラリを使用してバグを公開するのに十分な人がいない可能性があります。

于 2010-06-01T16:59:38.407 に答える
3

ネイサン、すばらしい調査です。バージョン番号は2010年5月の元のリリースでは実際に更新されていません。http://fsharppowerpack.codeplex.com/workitem/4548を参照してください 。バージョン番号が修正されたバイナリをアップロードしました。

于 2010-06-04T08:21:56.313 に答える
1

これは本当に紛らわしいです-私はあなたが説明した正確なシナリオ(Visual Studio 2008のF#2.0、CodePlexの最新のPowerPack 2.0)を使用してコードを実行しようとしましたが、例外なく動作します。

FSharp.Core.dllロードするのはと互換性がある必要があるため、Visual Studio 2008用のF#の最新リリース(Visual Studio 2010の最終バージョンの直後にリリースされたもの)を使用していることを確認することもできますFSharp.PowerPack.Metadata.dll。また、ライブラリは、現在のバージョンのF#コンパイラでコンパイルしたMetadata他のライブラリをロードできdllますか?

編集 これが機能しない場合は、(私が思うに)MetadataライブラリがF#コンパイラと同期していない可能性があります。

let a = System.Reflection.Assembly.GetExecutingAssembly()
     |> FSharpAssembly.FromAssembly
printf "%A" a.Entities.Count

以下が機能しない場合、それは本当に混乱するでしょう-バージョンに関係なく、ライブラリはそれ自体を読み取ることができるはずです!

let a = FSharpAssembly.FromFile @"C:\...\bin\FSharp.PowerPack.Metadata.dll"
printf "%A" a.Entities.Count
于 2010-05-27T14:35:05.847 に答える