无法访问 WCF soap webservice 作为 Windows 服务
WCF soap webservice as Windows service can't be reached
我有一个托管 WCF soap web 服务的 .NET 4.6 应用程序。它非常基本,当我在我自己的用户下的经典 .NET 4.6 桌面应用程序中 运行 它时,它工作正常。
但是我想 运行 它作为服务帐户下的 Windows 服务。
我使用 100% 完全相同的 wcf 代码和服务定义,唯一的区别是它在 windows 服务中,但它不起作用。未返回任何响应。
因此,例如在 .NET 4.6 桌面应用程序中,我可以发送 POST soap 请求并获得回复,然后浏览 http://10.10.10.10:8904/blabla?wsdl 上的定义就好了。
当我 运行 它作为服务帐户下的 Windows 服务时,它没有响应。例如浏览到 http://10.10.10.10:8904/blabla?wsdl 没有给出任何响应(在浏览器中它一直在旋转)。
在 netstat 中,我可以看到 Windows 托管在端口 8904 上。
如果我启用 WCF 跟踪文件,我可以看到这样的日志,所以似乎至少有一些 WCF activity:
<ExtendedData xmlns="http://schemas.microsoft.com/2006/08/ServiceModel/DictionaryTraceRecord">
<ActivityName>Ontvang bytes op verbinding http://10.10.10.10:8904/blabla?wsdl.</ActivityName>
<ActivityType>ReceiveBytes</ActivityType>
</ExtendedData>
我也已经添加了:netsh http add urlacl url=http://+:8904/blabla/ user=Everyone
有什么想法吗?我是否缺少某些用户权限? 运行ning 作为桌面应用程序和 windows 服务之间是否需要 WCF 配置差异?
一般来说,桌面应用程序中的托管代码不同于 windows 服务中的代码片段。我们通常使用 LocalSystem 帐户来 运行 Windows 服务,因为 WCF 服务需要管理员权限才能侦听机器端口。在OnStart方法中,需要开启服务宿主才能监听请求。
这是我的代码段。
public partial class Service1 : ServiceBase
{
public Service1()
{
InitializeComponent();
}
Uri uri = new Uri("http://localhost:1017");
ServiceHost sh = null;
protected override void OnStart(string[] args)
{
BasicHttpBinding binding = new BasicHttpBinding();
binding.Security.Mode = BasicHttpSecurityMode.None;
try
{
sh = new ServiceHost(typeof(MyService), uri);
sh.AddServiceEndpoint(typeof(IService), binding, "");
ServiceMetadataBehavior smb;
smb = sh.Description.Behaviors.Find<ServiceMetadataBehavior>();
if (smb == null)
{
smb = new ServiceMetadataBehavior()
{
HttpGetEnabled = true,
};
sh.Description.Behaviors.Add(smb);
}
Binding mexbinding = MetadataExchangeBindings.CreateMexHttpBinding();
sh.AddServiceEndpoint(typeof(IMetadataExchange), mexbinding, "mex");
sh.Open();
WriteLog($"Service is ready at {DateTime.Now.ToString("hh-mm-ss")}");
}
catch (Exception e)
{
WriteLog($"{DateTime.Now.ToLongDateString()},{DateTime.Now.ToLongTimeString()}-----------------------------------------------------");
WriteLog(e.ToString());
throw;
}
}
protected override void OnStop()
{
if (sh != null && sh.State == CommunicationState.Opened)
{
sh.Close();
WriteLog($"Service is closed at {DateTime.Now.ToString("hh-mm-ss")}");
}
}
public static void WriteLog(string text)
{
using (StreamWriter sw = File.AppendText(@"C:\Mylog.txt"))
{
sw.WriteLine(text);
sw.Flush();
}
}
}
[ServiceContract(Namespace = "mydomain")]
public interface IService
{
[OperationContract]
string SayHello();
}
public class MyService : IService
{
public string SayHello()
{
Service1.WriteLog(string.Format("Wow, I have been called at {0}", DateTime.Now.ToString("hh-mm-ss")));
return $"Hello stranger,Now is {DateTime.Now.ToString()}";
}
}
使用installutil.exe工具安装服务并启动服务后,我们就可以访问服务创建页面了。
https://docs.microsoft.com/en-us/dotnet/framework/windows-services/how-to-install-and-uninstall-services
如果问题仍然存在,请随时告诉我。
解决方案是从一个单独的线程中启动服务,而不是从主线程中启动。否则它会锁定。
我有一个托管 WCF soap web 服务的 .NET 4.6 应用程序。它非常基本,当我在我自己的用户下的经典 .NET 4.6 桌面应用程序中 运行 它时,它工作正常。 但是我想 运行 它作为服务帐户下的 Windows 服务。 我使用 100% 完全相同的 wcf 代码和服务定义,唯一的区别是它在 windows 服务中,但它不起作用。未返回任何响应。
因此,例如在 .NET 4.6 桌面应用程序中,我可以发送 POST soap 请求并获得回复,然后浏览 http://10.10.10.10:8904/blabla?wsdl 上的定义就好了。 当我 运行 它作为服务帐户下的 Windows 服务时,它没有响应。例如浏览到 http://10.10.10.10:8904/blabla?wsdl 没有给出任何响应(在浏览器中它一直在旋转)。
在 netstat 中,我可以看到 Windows 托管在端口 8904 上。
如果我启用 WCF 跟踪文件,我可以看到这样的日志,所以似乎至少有一些 WCF activity:
<ExtendedData xmlns="http://schemas.microsoft.com/2006/08/ServiceModel/DictionaryTraceRecord">
<ActivityName>Ontvang bytes op verbinding http://10.10.10.10:8904/blabla?wsdl.</ActivityName>
<ActivityType>ReceiveBytes</ActivityType>
</ExtendedData>
我也已经添加了:netsh http add urlacl url=http://+:8904/blabla/ user=Everyone
有什么想法吗?我是否缺少某些用户权限? 运行ning 作为桌面应用程序和 windows 服务之间是否需要 WCF 配置差异?
一般来说,桌面应用程序中的托管代码不同于 windows 服务中的代码片段。我们通常使用 LocalSystem 帐户来 运行 Windows 服务,因为 WCF 服务需要管理员权限才能侦听机器端口。在OnStart方法中,需要开启服务宿主才能监听请求。
这是我的代码段。
public partial class Service1 : ServiceBase
{
public Service1()
{
InitializeComponent();
}
Uri uri = new Uri("http://localhost:1017");
ServiceHost sh = null;
protected override void OnStart(string[] args)
{
BasicHttpBinding binding = new BasicHttpBinding();
binding.Security.Mode = BasicHttpSecurityMode.None;
try
{
sh = new ServiceHost(typeof(MyService), uri);
sh.AddServiceEndpoint(typeof(IService), binding, "");
ServiceMetadataBehavior smb;
smb = sh.Description.Behaviors.Find<ServiceMetadataBehavior>();
if (smb == null)
{
smb = new ServiceMetadataBehavior()
{
HttpGetEnabled = true,
};
sh.Description.Behaviors.Add(smb);
}
Binding mexbinding = MetadataExchangeBindings.CreateMexHttpBinding();
sh.AddServiceEndpoint(typeof(IMetadataExchange), mexbinding, "mex");
sh.Open();
WriteLog($"Service is ready at {DateTime.Now.ToString("hh-mm-ss")}");
}
catch (Exception e)
{
WriteLog($"{DateTime.Now.ToLongDateString()},{DateTime.Now.ToLongTimeString()}-----------------------------------------------------");
WriteLog(e.ToString());
throw;
}
}
protected override void OnStop()
{
if (sh != null && sh.State == CommunicationState.Opened)
{
sh.Close();
WriteLog($"Service is closed at {DateTime.Now.ToString("hh-mm-ss")}");
}
}
public static void WriteLog(string text)
{
using (StreamWriter sw = File.AppendText(@"C:\Mylog.txt"))
{
sw.WriteLine(text);
sw.Flush();
}
}
}
[ServiceContract(Namespace = "mydomain")]
public interface IService
{
[OperationContract]
string SayHello();
}
public class MyService : IService
{
public string SayHello()
{
Service1.WriteLog(string.Format("Wow, I have been called at {0}", DateTime.Now.ToString("hh-mm-ss")));
return $"Hello stranger,Now is {DateTime.Now.ToString()}";
}
}
使用installutil.exe工具安装服务并启动服务后,我们就可以访问服务创建页面了。
https://docs.microsoft.com/en-us/dotnet/framework/windows-services/how-to-install-and-uninstall-services
如果问题仍然存在,请随时告诉我。
解决方案是从一个单独的线程中启动服务,而不是从主线程中启动。否则它会锁定。