8

プログラムでデフォルトのWebサイトにバインディングを追加しようとしていますが、Microsoft.Web.Administrationdll内で常にnull参照例外が発生しています。もともと私はバインディングと一緒に証明書を割り当てたかったのです。これで、必要な証明書を照会できました。

var store = new X509Store(StoreName.Root, StoreLocation.LocalMachine);
store.Open(OpenFlags.OpenExistingOnly | OpenFlags.ReadWrite);

var certificate = store.Certificates.Find(X509FindType.FindByIssuerName,
                                                  "TEST_SELF_SIGNED", true)
                                                  .OfType<X509Certificate>().FirstOrDefault();

これは私が望む証明書を適切に私に与えました、それはnullではなく、私が期待した情報を持っていました。

Site site = GetSite("Default Web Site");
var binding = site.Bindings.Add("*:443", certificate.GetCertHash(), "https");

サンプルコード内の変数やその他の項目がnullではないことを考えると(20バイトの配列を返すGetCertHashを含む)、ここでnullを取得する理由について混乱しています。私も次のオーバーロードを試しました:

site.Bindings.Add("*:443", "https");

そして、私はまだ同じnullrefスタックを取得します:

System.NullReferenceExceptionが処理されませんでした
  Message=オブジェクト参照がオブジェクトのインスタンスに設定されていません。
  Source = Microsoft.Web.Administration
  スタックトレース:
       Microsoft.Web.Administration.Configuration.SetDirty()で
       Microsoft.Web.Administration.ConfigurationElement.SetDirty()で
       Microsoft.Web.Administration.ConfigurationElement.SetAttributeValue(String attributeName、Object value)で
       Microsoft.Web.Administration.Binding.SetBindingProperty(String attributeName、String value)で
       Microsoft.Web.Administration.BindingCollection.Add(String bindingInformation、Byte []certificateHash、StringcertificateStoreName)で
       C:\ Projects \ Cube \ trunk \ src \ AutoUpdate \ TestApp \ Program.cs:line33のTestApp.Program.Main(String [] args)で
       System.AppDomain._nExecuteAssembly(RuntimeAssemblyアセンブリ、String [] args)で
       System.AppDomain.ExecuteAssembly(String assemblyFile、Evidence assemblySecurity、String [] args)で
       Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()で
       System.Threading.ThreadHelper.ThreadStart_Context(オブジェクト状態)で
       System.Threading.ExecutionContext.Run(ExecutionContext executeContext、ContextCallbackコールバック、オブジェクト状態、ブール値ignoreSyncCtx)で
       System.Threading.ExecutionContext.Run(ExecutionContextexecutionContext、ContextCallbackコールバック、オブジェクト状態)で
       System.Threading.ThreadHelper.ThreadStart()で
  InnerException:

これは、サンプル証明書の生成に使用したselfsslコマンドライン引数とともに、問題を実証する完全なテストアプリです。

selfssl.exe / T / N:CN = TEST_SELF_SIGNED / K:512 / V:9999 / Q

class Program
{
    static void Main(string[] args)
    {

        using (ServerManager manager = new ServerManager())
        {
            var store = new X509Store(StoreName.Root, StoreLocation.LocalMachine);
            store.Open(OpenFlags.OpenExistingOnly | OpenFlags.ReadWrite);

            var certificate = store.Certificates.Find(X509FindType.FindByIssuerName, "TEST_SELF_SIGNED", true).OfType<X509Certificate>().FirstOrDefault();

            Site site = GetSite("Default Web Site");
            site.Bindings.Add("*:443", certificate.GetCertHash(), store.Name);

            store.Close();

            manager.CommitChanges();
        }
    }

    public static Site GetSite(string siteName)
    {
        using (var serverManager = new ServerManager())
        {
            return serverManager.Sites.Where(p => p.Name.ToLower() == siteName.ToLower()).FirstOrDefault();
        }
    }
}

私の拠点をカバーするために、Iisがインストールされており、証明書を手動で割り当てることは問題なく機能します。

4

1 に答える 1

10

そこで、Microsoft.Web.Administration dll を逆コンパイルし、スタックを突いて答えを見つけました。ヘルパー関数を使用してサイトを取得すると、サイトの内部 ServerManager プロパティが設定されないことがわかります。

問題の原因となった dll の機能は、Microsoft.Web.Administration::Configuration の this でした

internal void SetDirty()
{
  if (this._hasBeenCommitted || this._configurationManager.Owner.ReadOnly)
    throw new InvalidOperationException(Resources.ObjectHasBeenCommited);
  this._isDirty = true;
}

ここで null になる可能性があるのは、 または のいずれ_configurationManagerかだけ_configurationManager.Ownerでした。何Ownerがあったかを確認したところServerManager、おそらくSiteサーバーマネージャーの使用ブロック内からクエリを実行する必要があることがわかりました。それをしたら、null refがなくなり、すべてが機能しました。null をチェックしていないのは残念ですが、サーバー マネージャーのコンテキストがなければ、誰もサイト オブジェクトを操作しないという前提があるのか​​もしれません。

とにかく、更新されたコードは次のとおりです。

class Program
{
    static void Main(string[] args)
    {

        using (var serverManager = new ServerManager())
        {
            var selfSignedCnName = "TEST_SELF_SIGNED";
            var websiteName = "Default Web Site";

            var site = serverManager.Sites.Where(p => p.Name.ToLower() == websiteName.ToLower()).FirstOrDefault(); 
            var store = new X509Store(StoreName.Root, StoreLocation.LocalMachine);
            store.Open(OpenFlags.OpenExistingOnly | OpenFlags.ReadWrite);

            var certificate = store.Certificates.Find(X509FindType.FindByIssuerName, selfSignedCnName, true).OfType<X509Certificate>().FirstOrDefault();

            site.Bindings.Add("*:443:", certificate.GetCertHash(), store.Name);

            store.Close();

            serverManager.CommitChanges();
        }
    }

}

コード ブロック全体をサーバー マネージャーでラップしても何の意味もなく、カスケードされていないことも、私の最初の投稿から明らかです。サーバー マネージャーからサイトを操作する必要があります。

于 2012-04-30T16:20:27.647 に答える