0

Ich schreibe eine Windows-Dienstanwendung in Visual Studio (VB), die einen Google Kalender für alle Ereignisse abfragt, die innerhalb der nächsten 5 Minuten stattfinden.Ich benutze Google Kalender-API von Windows-Dienst

Idealerweise möchte ich, dass mein Dienst die Anmeldeinformationen generiert, aber ich glaube nicht, dass ein Windows-Dienst eine Browserseite zum Authentifizieren von Personen öffnen kann. Derzeit erstelle ich die Anmeldeinformationen an einem bestimmten Ort über eine Konsolenanwendung, die einen Browser aufrufen kann und der Dienst an diesem Ort nach Anmeldeinformationen sucht. Ich möchte die Konsolen-App ganz loswerden, aber wenn es notwendig ist, werde ich sie einfach in der Batch-Datei ausführen, die den Dienst installiert.

Das große Problem, das ich habe, ist die Credentials-Datei (sekundäre Bedenken) zu generieren, und noch wichtiger, es zu aktualisieren, so dass es nicht nach einer Stunde abläuft (primäre Sorge).

Hier ist mein Windows-Dienst-Code (das funktioniert für die Stunde völlig in Ordnung, nachdem ich meine Konsole app laufen und den Zugang zu meinem Kalender erlauben):

Dim Scopes As String() = {CalendarService.Scope.CalendarReadonly} 
Dim ApplicationName As String = "Google Calendar API .NET Quickstart" 

Private Sub writeUpdateTimerEvent(source As Object, e As ElapsedEventArgs) 

    Dim credential As UserCredential 

    Try 

     Using stream = New FileStream("FILE PATH TO client_secret.json", FileMode.Open, FileAccess.Read) 

      Dim credPath As String = "FILE PATH TO WHERE MY CONSOLE APP IS STORING THE CREDENTIALS FILE" 
      credPath = Path.Combine(credPath, ".credentials/calendar-dotnet-quickstart.json") 

      credential = GoogleWebAuthorizationBroker.AuthorizeAsync(GoogleClientSecrets.Load(stream).Secrets, Scopes, "user", CancellationToken.None, New FileDataStore(credPath, True)).Result 

      If credential Is Nothing Then 
       credential.RefreshTokenAsync(CancellationToken.None) 
      End If 

     End Using 

     ' Create Google Calendar API service. 
     Dim service = New CalendarService(New BaseClientService.Initializer() With { 
      .HttpClientInitializer = credential, 
      .ApplicationName = ApplicationName 
     }) 

     ' Define parameters of request. 
     Dim request As EventsResource.ListRequest = service.Events.List("primary") 
     request.TimeMin = DateTime.Now 
     request.TimeMax = DateTime.Now.AddMinutes(5) 
     request.ShowDeleted = False 
     request.SingleEvents = True 
     request.OrderBy = EventsResource.ListRequest.OrderByEnum.StartTime 

     ' List events. 
     Dim eventsString As String = "" 
     Dim events As Events = request.Execute() 

     If events.Items IsNot Nothing AndAlso events.Items.Count > 0 Then 
      'This is where I do my operations on events occuring in the next 5 minutes 
      EventLog1.WriteEntry("Event occuring within 5 minutes") 
     Else 
      EventLog1.WriteEntry("No event occuring within 5 minutes") 
     End If 
    Catch ex As Exception 
     EventLog1.WriteEntry("error grabbing events." & Environment.NewLine & ex.message) 
    End Try 
End Sub 

Hier meine Konsole app-Code ist (so ziemlich das gleiche wie oben):

Module Module1 

Dim Scopes As String() = {CalendarService.Scope.CalendarReadonly} 
Dim ApplicationName As String = "Google Calendar API .NET Quickstart" 

Sub Main() 
    Dim credential As UserCredential 

    Using stream = New FileStream("client_secret.json", FileMode.Open, FileAccess.Read) 
     Dim credPath As String = "SAME FILE PATH AS IN MY SERVICE" 
     credPath = Path.Combine(credPath, ".credentials/calendar-dotnet-quickstart.json") 

     credential = GoogleWebAuthorizationBroker.AuthorizeAsync(GoogleClientSecrets.Load(stream).Secrets, Scopes, "user", CancellationToken.None, New FileDataStore(credPath, True)).Result 
     Console.WriteLine(Convert.ToString("Credential file saved to: ") & credPath) 
    End Using 

    ' Create Google Calendar API service. 
    Dim service = New CalendarService(New BaseClientService.Initializer() With { 
      .HttpClientInitializer = credential, 
      .ApplicationName = ApplicationName 
     }) 

    ' Define parameters of request. 
    Dim request As EventsResource.ListRequest = service.Events.List("primary") 
    request.TimeMin = DateTime.Now 
    request.ShowDeleted = False 
    request.SingleEvents = True 
    request.MaxResults = 10 
    request.OrderBy = EventsResource.ListRequest.OrderByEnum.StartTime 

    ' List events. 
    Dim events As Events = request.Execute() 
    Console.WriteLine("Upcoming events:") 
    If events.Items IsNot Nothing AndAlso events.Items.Count > 0 Then 
     For Each eventItem As Object In events.Items 
      Dim [when] As String = eventItem.Start.DateTime.ToString() 
      If [String].IsNullOrEmpty([when]) Then 
       [when] = eventItem.Start.[Date] 
      End If 
      Console.WriteLine("{0} ({1})", eventItem.Summary, [when]) 
     Next 
     Console.WriteLine("You may now close this window.") 
     System.Environment.Exit(0) 
    Else 
     Console.WriteLine("No upcoming events found.") 
    End If 
    Console.Read() 

End Sub 

End Module 
+0

Nicht sicher, ob das hilft, aber haben Sie überprüft [NET Quickstart] (https://developers.google.com/google-apps/calendar/quickstart/dotnet)? – noogui

+0

Nach dem .NET Quickstart habe ich mich an diesen Punkt gewendet, mein Code ist im Wesentlichen direkt von diesem Handbuch, konvertiert von CSharp zu VB. – JonW

+0

Ich glaube, dass Sie ein Dienstkonto verwenden sollten. https://developers.google.com/identity/protocols/OAuth2#serviceaccount –

Antwort

0

Jetzt funktioniert es, mit einem Dienstkonto anstelle eines Benutzerkontos. Sie müssen sich nicht mit dem Generieren von Anmeldeinformationen oder dem Aktualisieren des Tokens befassen.

Dim serviceAccountEmail As [String] = ConfigurationManager.AppSettings("ServiceAcct") 

Dim certificate = New X509Certificate2("key.p12", "notasecret", X509KeyStorageFlags.Exportable) 


Dim credential1 As New ServiceAccountCredential(New ServiceAccountCredential.Initializer(serviceAccountEmail) With { 
     .Scopes = Scopes 
    }.FromCertificate(certificate)) 


Dim service = New CalendarService(New BaseClientService.Initializer() With { 
     .HttpClientInitializer = credential1, 
     .ApplicationName = ApplicationName 
    })