我有一个应该以特定间隔运行的Windows服务(目前设置为1分钟用于测试目的)并从我们的数据库中获取数据,然后将信息上传到我们的Google日历。在调试模式下,一切运行正常,但是当Windows服务在我的PC上独立运行时,它似乎停留在内部StartGoogleCalendar" EventLog条目。为什么它在Debug模式下运行得很好但在生产模式下会停止?难道我做错了什么?以下是代码。
protected override void OnStart(string[] args)
{
EventLog.WriteEntry("Service Started: " + DateTime.Now.ToLongDateString());
_timer = new System.Timers.Timer(1 * 60 * 1000);
_timer.Elapsed += new System.Timers.ElapsedEventHandler(fireGoogle);
_timer.Start();
}
protected override void OnStop()
{
EventLog.WriteEntry("Service Stopped: " + DateTime.Now.ToLongDateString());
}
private void fireGoogle(object sender, System.Timers.ElapsedEventArgs e)
{
EventLog.WriteEntry("Firing Google: " + DateTime.Now.ToLongDateString());
StartGoogleCalendar();
}
public void StartGoogleCalendar()
{
try
{
EventLog.WriteEntry("Inside StartGoogleCalendar");
authorization Auth = new authorization();
EventLog.WriteEntry("Done with Auth");
calendar ipamCal = new calendar();
EventLog.WriteEntry(Auth.EventLogEvent());
EventLog.WriteEntry("GAPI Calendar Schedule complete");
}
catch (Exception ex)
{
EventLog.WriteEntry(ex.Data.ToString() + ": INNER EXCEPTION: " + ex.InnerException.ToString() + " - GENERAL MESSAGE: " + ex.Message.ToString() + " - SOURCE: " + ex.Source.ToString() );
}
}
这是"授权"代码(client_secrets.json确实存在,因为它在调试模式下工作):
private static EventLog _el = new EventLog();
public authorization()
{
globals.scopes = new List<string>();
_authCredentials();
}
private void _authCredentials()
{
globals.scopes.Add("https://www.googleapis.com/auth/calendar");
try
{
_el.WriteEntry("Inside _authcredentials");
using (FileStream _stream = new FileStream("client_secrets.json", FileMode.Open, FileAccess.Read))
{
_el.WriteEntry("Attempting to get credentials");
globals.userCredentials = GoogleWebAuthorizationBroker.AuthorizeAsync(GoogleClientSecrets.Load(_stream).Secrets, globals.scopes, "Today-at-IPAM", CancellationToken.None, new FileDataStore("calendar_new.dat")).Result;
_el.WriteEntry(globals.userCredentials.Token.ToString());
}
_el.WriteEntry( "Google Authorization - SUCCESS");
}
catch (Exception ex)
{ _el.WriteEntry( "Google Authorization - FAILED\r\n\tReason: " + ex.InnerException.Message); }
}
public String EventLogEvent()
{ return globals.eventLogEvents; }
答案 0 :(得分:2)
在调试模式下运行服务时,它将查找服务可执行文件的bin文件夹中的文件。但是当您在发布模式下运行它时,即作为已安装的服务运行时,它通过服务控制管理器运行,其工作文件夹是system32。你应该做的第一件事是把你的秘密文件的路径放在.config文件中,然后读取该路径,通过文件的绝对路径加载文件(client_secrets.json)。
其次我不建议在Windows事件日志中写入所有内容。您应该考虑使用log4net或类似方法进行应用程序日志记录。
最后你的计时器是asyn计时器,想象一下如果你的进程花费的时间长于你的计时器间隔,它将在第一个完成之前执行另一个请求。你应该考虑让你的计时器同步
答案 1 :(得分:1)
你必须测试几件事: 1 /当您在Windows系统中添加服务时,您已指定了整个执行路径 请参考命令行。 SC CREATE&#34; ServiceName&#34; DisplayName =&#34;显示服务名称&#34; binpath =&#34; C:\ User \ Service.exe&#34; start = auto obj =&#34; NT AUTHORITY \ LocalService&#34;
2 /您用于启动服务的帐户是什么,权限是对的? 请参考上一个例子中的参数obj。
3 /目录和文件&#34; client_secrets.json&#34;的权限是什么?
答案 2 :(得分:1)
人们建议查看与您的服务相关的权限看起来有效。 我想补充一点,你的两个catch语句都会失败。如果没有innerException会发生什么? :)
我不熟悉谷歌的身份验证模块 - 但是如果您可以首先定位更具体的例外,这可能有助于您了解服务失败的原因。
答案 3 :(得分:0)
我可以想到两件事:
a)检查运行该服务的帐户是否有足够的权限访问互联网。
b)我会创建一个单独的线程并在那里完成工作。例如:
public partial class Service1 : ServiceBase
{
private Thread _thread;
public Service1()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
_thread = new Thread(DoWork);
_thread.Start();
}
private void DoWork()
{
// Write your code here...
File.WriteAllText(@"C:\Test123.txt","hello world!");
}
protected override void OnStop()
{
}
}
基本上,我们不应该在OnStart()中执行长时间运行的任务。我希望这会有所帮助。
答案 4 :(得分:0)
只是一个想法,它可能与您的问题无关。 我看到你每分钟都在创建你的授权对象,并为它添加相同的范围URL。我不知道你的全局对象是否被清除,你可能有某种线程问题打开web请求连接。 同样如此,您正在重复添加相同的凭据。
将您的授权对象转换为单身,看看它是否有效或不使用全局变量并在超出范围时清理对象。
我有一些类似的问题,从窗口(不是窗口服务)的一些自动调用web,它有线程引发问题,并将挂起。
2c,通常从对象构造函数调用任何函数不是一个好主意。
答案 5 :(得分:0)
此问题与.dat文件因谷歌身份验证而变为无效有关。