5

FileVersionInfo.GetVersionInfo()を使用して深刻な問題が発生し、誰かが助けてくれることを期待していました。

この問題の基本は、それぞれのGetVersionInfo()を呼び出すフォルダー内のすべてのファイルを反復処理していることです。約300個のファイルがあります。これは、2つを除くすべてのファイルで問題なく機能します。これらのDLLの場合、GetVersionInfo()から完全に誤った情報が返されます。

他のすべての変数を排除するために、この呼び出しを単純なテストアプリに抽出しましたが、それでも同じ問題が発生しました。ただし、テストアプリをWindowsアプリケーション(最初はコンソールアプリケーション)としてビルドした場合、データは正しく返されました。

明確にするために、コンソールアプリとして実行しているときに返される誤ったデータは、ファイルにバージョンデータが含まれていない場合に得られるような単なるnull情報ではありません。妥当なデータが含まれていましたが、間違ったデータが含まれていました。別のファイルから読み取っているようなものです。一致するバージョンデータを含むファイルを探しましたが、見つかりません。

Windowsアプリケーションではなくコンソールアプリケーションとして構築された場合、この単純な呼び出しの機能が異なるのはなぜですか?

誰かがこれを手伝ってくれるなら、私はとても感謝しています。

Rgds、Andy

-追加されたコード

using System;
using System.Diagnostics;

namespace test
{
    class Program
    {
        static void Main(string[] args)
        {
            string file = "C:\\ProblemFile.dll";
            FileVersionInfo version = FileVersionInfo.GetVersionInfo(file);
            string fileName = version.FileName;
            string fileVersion = version.FileVersion;

            Console.WriteLine(string.Format("{0} : {1}", fileName, fileVersion));
        }
    }
}
4

4 に答える 4

8

この振る舞いは確かに奇妙に思えます。コンソールアプリケーションがWinFormsアプリケーションと同じ場所からDLLをロードしない可能性がありますか?これは、GetVersionInfoWin32以外のAPIを使用することを意味しますCreateFile(おそらく、DLLリゾルバーメカニズムを並べて実行するなど)。version.dll裏で、CLR自体ではなく、リクエストを実行することを忘れないでください。

リフレクターポイントを別の方向に見てみFileVersionInfoましょう。

public static unsafe FileVersionInfo GetVersionInfo(string fileName)
{
    // ...
    int fileVersionInfoSize = UnsafeNativeMethods.GetFileVersionInfoSize(fileName, out num);
    FileVersionInfo info = new FileVersionInfo(fileName);
    if (fileVersionInfoSize != 0)
    {
        byte[] buffer = new byte[fileVersionInfoSize];
        fixed (byte* numRef = buffer)
        {
            IntPtr handle = new IntPtr((void*) numRef);
            if (!UnsafeNativeMethods.GetFileVersionInfo(fileName, 0, fileVersionInfoSize, new HandleRef(null, handle)))
            {
                return info;
            }
            int varEntry = GetVarEntry(handle);
            if (!info.GetVersionInfoForCodePage(handle, ConvertTo8DigitHex(varEntry)))
            {
                int[] numArray = new int[] { 0x40904b0, 0x40904e4, 0x4090000 };
                foreach (int num4 in numArray)
                {
                    if ((num4 != varEntry) && info.GetVersionInfoForCodePage(handle, ConvertTo8DigitHex(num4)))
                    {
                        return info;
                    }
                }
            }
        }
    }
    return info;
}

ご覧のとおり、コードページで興味深いダンスが行われています。検査したDLLにいくつかのバージョン情報リソースが添付されている場合はどうなりますか?を呼び出すプログラムの文化によってはGetVersionInfo、コードページ関連の呼び出しが他の結果を返す可能性があると思いますか?

時間をかけてDLLのリソースをチェックし、バージョン情報の言語/コードページが1つしかないことを確認してください。それはあなたに解決策を示すかもしれません、私は願っています。

于 2010-02-10T06:11:00.957 に答える
0

確かに、表示されている「ファイル」はそうではありません。と .. ?すべてのファイルを反復処理すると、のエントリが常に表示されます。(現在のディレクトリ)および..(アップディレクトリ)。GetVersion Infoは、これらに対して何かを返す可能性があります。これらのエントリを名前で手動で除外する必要があります。

于 2010-02-08T13:01:08.860 に答える
0

ファイルバージョンとアセンブリバージョンは2つの異なるものです。

あなたは他を期待していないと確信していますか?

于 2010-02-08T13:47:17.927 に答える
0

更新:これを試しました。動作しませんでした。

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace test
{
    class Program
    {
        [DllImport("COMCTL32")]
        private static extern int InitCommonControls(int nExitCode);

        static void Main(string[] args)
        {
            InitCommonControls(0);

            string file = "C:\\ProblemFile.dll";
            FileVersionInfo version = FileVersionInfo.GetVersionInfo(file);
            string fileName = version.FileName;
            string fileVersion = version.FileVersion;

            Console.WriteLine(string.Format("{0} : {1}", fileName, fileVersion));
        }
    }
}
于 2010-02-08T16:17:17.343 に答える