添加HTTPS绑定时的NullReferenceException在Microsoft.Web.Administration [英] NullReferenceException in Microsoft.Web.Administration when adding https binding
问题描述
我试图以编程方式添加绑定到我的默认网站但是我始终得到Microsoft.Web.Administration DLL中的空引用异常。本来我想与绑定一起分配证书。我能够查询,我想这个证书:
VAR店=新的X509Store(StoreName.Root,StoreLocation.LocalMachine );
store.Open(OpenFlags.OpenExistingOnly | OpenFlags.ReadWrite);
变种证书= store.Certificates.Find(X509FindType.FindByIssuerName,
TEST_SELF_SIGNED,真)
.OfType&所述; x509证书>()FirstOrDefault();
这正常给我我想要的证书,这是为非空,并且有我的预期的信息。
网站网站= GetSite(默认Web站点);
变种结合= site.Bindings.Add(*:443,certificate.GetCertHash(),HTTPS);
既然没有我的变量或在示例代码中任何其他项目都是空(包括GetCertHash返回20字节数组)我很困惑,为什么我在这里得到一个空。我甚至尝试以下过载:
site.Bindings.Add(*:443,https开头);
和我仍然得到同样的空REF堆栈:
System.NullReferenceException了未处理
消息=对象未设置为一个对象的实例引用。
来源= Microsoft.Web.Administration
堆栈跟踪:
在Microsoft.Web.Administration.Configuration.SetDirty()
在Microsoft.Web.Administration.ConfigurationElement.SetDirty()
。在Microsoft.Web.Administration.ConfigurationElement.SetAttributeValue(字符串的attributeName,对象的值)
在Microsoft.Web.Administration.Binding.SetBindingProperty(字符串的attributeName,字符串值)
在Microsoft.Web。 Administration.BindingCollection.Add(字符串bindingInformation,字节[] certificateHash,字符串certificateStoreName)
在TestApp.Program.Main(字串[] args)在C:\Projects\Cube\trunk\src\ AutoUpdate\TestApp\Program.cs:行33
在System.AppDomain._nExecuteAssembly(RuntimeAssembly组装,字串[] args)
在System.AppDomain.ExecuteAssembly(字符串assemblyFile,证据assemblySecurity,字符串[ ]参数)
在Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
在System.Threading.ThreadHelper.ThreadStart_Context(对象状态)
在System.Threading.ExecutionContext.Run(ExecutionContext中的ExecutionContext ,ContextCallback回调,对象状态,布尔ignoreSyncCtx)
在System.Threading.ExecutionContext.Run(ExecutionContext中的ExecutionContext,ContextCallback回调,对象状态)在System.Threading.ThreadHelper.ThreadStart()
的InnerException:
下面是一个完整的测试应用程序,demonstartes问题,与我用来生成样品证书selfssl命令行参数一起:
selfssl.exe / T / N:CN = TEST_SELF_SIGNED / K:512 / V:9999 / Q
类节目
{
静态无效的主要(字串[] args)
{$ b $使用b
(ServerManager的经理=新ServerManager的())
{
变种店=新的X509Store(StoreName.Root,StoreLocation.LocalMachine);
store.Open(OpenFlags.OpenExistingOnly | OpenFlags.ReadWrite);
变种证书= store.Certificates.Find(X509FindType.FindByIssuerNameTEST_SELF_SIGNED,真).OfType&所述; x509证书>()FirstOrDefault();
位的网站= GetSite(默认Web站点);
site.Bindings.Add(*:443,certificate.GetCertHash(),store.Name);
store.Close();
manager.CommitChanges();
}
}用
公共静态网站GetSite(字符串站点名称)
{
(VAR ServerManager的=新ServerManager的())
{
返回serverManager.Sites.Where(p值=> p.Name.ToLower()== siteName.ToLower())FirstOrDefault();
}
}
}
只是为了掩饰我的基地, IIS的安装和手动分配证书的作品就好了。
于是我找到了答案通过反编译的Microsoft.Web.Administration DLL并通过烟囱戳。事实证明,如果你得到一个网站具有辅助功能的它不设置该网站上的内部ServerManager的属性。
这导致问题该DLL函数这Microsoft.Web.Administration ::配置
内部空间使用setDirty()
{
如果( this._hasBeenCommitted || this._configurationManager.Owner.ReadOnly)
抛出新的InvalidOperationException异常(Resources.ObjectHasBeenCommited);
this._isDirty = TRUE;
}
这本来是空在这里要么 _configurationManager
或 _configurationManager.Owner
。我查了一下所有者
是,这是一个 ServerManager的
这通风报信我送行,我也许应该查询网站
。一旦我做到了零裁判走了,一切正常。这是不幸的,他们没有检查空的,但也许假设是没有人会采取行动,而不服务器管理器上下文站点对象上。
不管怎样,下面是更新代码:
类节目
{
静态无效的主要(字串[] args)
{使用(VAR ServerManager的=新ServerManager的())
{
VAR selfSignedCnName =TEST_SELF_SIGNED
;
VAR websiteName =默认Web站点;
变种站点= serverManager.Sites.Where(p值=> p.Name.ToLower()== websiteName.ToLower())FirstOrDefault();
变种店=新的X509Store(StoreName.Root,StoreLocation.LocalMachine);
store.Open(OpenFlags.OpenExistingOnly | OpenFlags.ReadWrite);
无功证书= store.Certificates.Find(X509FindType.FindByIssuerName,selfSignedCnName,真).OfType<&x509证书GT;()FirstOrDefault()。
site.Bindings.Add(*:443:,certificate.GetCertHash(),store.Name);
store.Close();
serverManager.CommitChanges();
}
}
}
这也是从我最初的职位,包裹在服务器管理器中的整个代码块并不意味着什么明确的,他们没有级联。你必须采取行动,从它来自服务器管理网站上。
I'm trying to programmatically add a binding to my default website however I am consistently getting a null reference exception within the Microsoft.Web.Administration dll. Originally I wanted to assign a certificate along with the binding. I was able to query the certificate that I wanted with this:
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();
This properly gave me the certificate I wanted, it was non-null and had the information I expected.
Site site = GetSite("Default Web Site");
var binding = site.Bindings.Add("*:443", certificate.GetCertHash(), "https");
Given that none of my variables or any other items in the sample code are null (including GetCertHash which returns a 20 byte array) I'm confused as to why I'm getting a null here. I even tried the following overload:
site.Bindings.Add("*:443", "https");
And I still get the same null ref stack:
System.NullReferenceException was unhandled Message=Object reference not set to an instance of an object. Source=Microsoft.Web.Administration StackTrace: at Microsoft.Web.Administration.Configuration.SetDirty() at Microsoft.Web.Administration.ConfigurationElement.SetDirty() at Microsoft.Web.Administration.ConfigurationElement.SetAttributeValue(String attributeName, Object value) at Microsoft.Web.Administration.Binding.SetBindingProperty(String attributeName, String value) at Microsoft.Web.Administration.BindingCollection.Add(String bindingInformation, Byte[] certificateHash, String certificateStoreName) at TestApp.Program.Main(String[] args) in C:\Projects\Cube\trunk\src\AutoUpdate\TestApp\Program.cs:line 33 at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args) at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args) at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() at System.Threading.ThreadHelper.ThreadStart_Context(Object state) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Threading.ThreadHelper.ThreadStart() InnerException:
Here is a full test-app that demonstartes the issue, along with the selfssl command line arguments I used to generate the sample certificate:
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();
}
}
}
Just to cover my bases, Iis is installed and manually assigning the certificate works just fine.
So I found the answer by decompiling the Microsoft.Web.Administration dll and poking through the stack. It turns out that if you get a Site with a helper function it doesn't set the internal ServerManager property on the site.
The function the dll that caused the issue was this in Microsoft.Web.Administration::Configuration
internal void SetDirty()
{
if (this._hasBeenCommitted || this._configurationManager.Owner.ReadOnly)
throw new InvalidOperationException(Resources.ObjectHasBeenCommited);
this._isDirty = true;
}
The only thing that could have been null here was either _configurationManager
or _configurationManager.Owner
. I checked what Owner
was and it was a ServerManager
which tipped me off that I should probably query the Site
from within a using block of server manager. Once I did that the null ref went away and everything worked. It's unfortunate that they aren't checking for null's but maybe the assumption is nobody would ever act on a site object without the server manager context.
Anyways, here is the updated code:
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();
}
}
}
It's also clear from my initial post that wrapping the entire code block in a server manager doesn't mean anything, they aren't cascaded. You have to act on the site from the server manager it came from.
这篇关于添加HTTPS绑定时的NullReferenceException在Microsoft.Web.Administration的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!