InternalsVisibleToAttribute Generator 作成途中

InternalsVisibleTo の指定(フレンド アセンブリ)の続き。サイトからなくなってしまった InternalsVisibleToAttribute Generator を自力で作成してみているところ。InternalsVisibleTo を指定する文字列を作るところまでできた。

using System;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;

namespace ConsoleApplication1
{
    public class CheckAssembly
    {
        private readonly char[] CommaCharArray = ",".ToCharArray();

        /// <summary>
        /// ファイル名で指定されたアセンブリの PublicKey (320文字)を取得する。sn.exe -Tp で出力されるもの。
        /// </summary>
        /// <param name="filename"></param>
        /// <returns></returns>
        public string GetInternalsVisibleTo(string filename)
        {
            Assembly asm = Assembly.ReflectionOnlyLoadFrom(filename);
            byte[] keyblob = CallStrongNameTokenFromAssemblyEx(filename);
            if (keyblob != null) return buildInternalsVisibleTo(keyblob, asm);
            return null;
        }

        /// <summary>
        /// StrongNameTokenFromAssemblyEx を呼ぶ処理(後始末を含む)
        /// </summary>
        /// <param name="filename"></param>
        /// <returns></returns>
        private static byte[] CallStrongNameTokenFromAssemblyEx(string filename)
        {
            byte[] keyblob = null;
            IntPtr ppbStrongNameToken = IntPtr.Zero;
            IntPtr ppbKeyBlob = IntPtr.Zero;
            try
            {
                ulong pcbStrongNameToken;
                ulong pcbKeyBlob;
                if (StrongNameTokenFromAssemblyEx(
                    filename,
                    out ppbStrongNameToken,
                    out pcbStrongNameToken,
                    out ppbKeyBlob,
                    out pcbKeyBlob))
                {
                    keyblob = new byte[pcbKeyBlob];
                    Marshal.Copy(ppbKeyBlob, keyblob, 0, (int) pcbKeyBlob);
                }
            }
            finally
            {
                if (ppbStrongNameToken != IntPtr.Zero)
                    StrongNameFreeBuffer(ppbStrongNameToken);
                if (ppbKeyBlob != IntPtr.Zero)
                    StrongNameFreeBuffer(ppbKeyBlob);
            }
            return keyblob;
        }

        private string buildInternalsVisibleTo(byte[] keyblob, Assembly asm)
        {
            StringBuilder s = new StringBuilder();
            string[] assemblyNameArr = asm.FullName.Split(CommaCharArray);
            s.AppendFormat("[assembly: InternalsVisibleTo(\"{0}, ", assemblyNameArr[0]);
            s.Append("PublicKey=");
            // PublicKey
            foreach (byte b in keyblob)
            {
                s.AppendFormat("{0:x2}", b);
            }
            s.Append("\")]");
            return s.ToString();
        }

        /// <summary>
        ///   BOOLEAN StrongNameTokenFromAssemblyEx (
        ///        [in]  LPCWSTR   wszFilePath,
        ///        [out] BYTE      **ppbStrongNameToken,
        ///        [out] ULONG     *pcbStrongNameToken,
        ///        [out] BYTE      **ppbPublicKeyBlob,
        ///        [out] ULONG     *pcbPublicKeyBlob
        ///  );
        /// </summary>
        /// <param name="wszFilePath"></param>
        /// <param name="ppbStrongNameToken"></param>
        /// <param name="pcbStrongNameToken"></param>
        /// <param name="ppbKeyBlob"></param>
        /// <param name="pcbKeyBlob"></param>
        /// <returns>true if succeeded</returns>
        [DllImport("mscoree.dll")]
        private static extern bool StrongNameTokenFromAssemblyEx(
            [MarshalAs(UnmanagedType.LPWStr)] string wszFilePath,
            [Out] out IntPtr ppbStrongNameToken,
            [Out] out ulong pcbStrongNameToken,
            [Out] out IntPtr ppbKeyBlob,
            [Out] out ulong pcbKeyBlob
            );

        /// <summary>
        /// Free the buffer allocated by strong name functions
        /// VOID StrongNameFreeBuffer ( 
        ///      [in] BYTE   *pbMemory
        ///);
        /// </summary>
        /// <param name="pbMemory">address of memory to free</param>
        [DllImport("mscoree.dll")]
        public static extern void StrongNameFreeBuffer(IntPtr pbMemory);
    }
}

コードのほとんどはP/Invokeを実現するためのコードだな。やりたかったことは BuildInternalsVisibleTo メソッドの中身だけなのに。

WindowsFormsアプリを作るのでは芸がないので、VisualStudioプラグインとして実装するのがいいかなあと思っているところ。コンソールアプリで十分な気もするが。

InternalsVisibleToAttribute Generator 作成途中」への1件のフィードバック

  1. Unknown より:

    Welcome to enter (wow gold) and (wow power leveling) trading site, (Rolex) are cheap, (World of Warcraft gold) credibility Very good! Quickly into the next single! Key words directly to the website click on transactions!

コメントを残す