How to Use TeamViewer

CodeGuru content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More.

Introduction

Don’t you just love technology sometimes? We live in the digital age, and I for one am quite excited about it. It is amazing what apps are out there to improve our otherwise dull lives. I cannot imagine my life without TeamViewer. Giving technical support has never been easier, especially when you are working in a large company with various branches all over the country. It has never been easier. Today, I will introduce you to the TeamViewer API and the various platforms you can make use of to program a TeamViewer enabled app.

What Is TeamViewer?

If you haven’t figured it out yet, based on the introduction of this article, TeamViewer enables you to provide technical support to any PC that is not near you. But how? Well, once you have installed TeamViewer, you cannot simply open it and have a magical skeleton key that opens up all backdoors to all PCs. You are given an ID, just like the PC you are connecting to also has been given an ID. You have to supply the ID of the PC you are connected to, as well as that PC’s given password.

Once you have supplied the given ID and password to connect to the desired PC, you have control over that PC. Note, it is not full control; it’s just enough so that you can try to replicate the given problem or chat with the person on the PC. Let me tell you this: Make use of TeamViewer because not everyone is as tech savvy as you. People you have to give support to speak a different language, so try to understand the basics of their problem.

Getting Started with the TeamViewer API

Just like any other mainstream product, you cannot just jump in haphazardly. Similar to previous apps I have demonstrated (Facebook, Instagram), there is a simple method of making sure your intentions are valid with your app. Keep one thing in mind: Popular brands do not like the fact that their name could possibly be connected with malicious apps, hence destroying their brand’s reputation.

The following screenshots demonstrate all the steps you need to take to make use of the TeamViewer API.

Navigate to the following URL to start the process: https://integrate.teamviewer.com/en/develop/api/get-started/.

The previous link details each step that you have to follow, as seen in the following screenshots:

Team1
Figure 1: Create App

Team2
Figure 2: Create Account

Team3
Figure 3: Create App Menu

Team4
Figure 4: Create Application

Team5
Figure 5: Registration Completed

Team6
Figure 6: Token

Team7
Figure 7: Documentation

Once you have been given a token, you are able to develop an app that integrates with TeamViewer. A word to the wise: Please make sure you download the documentation. It is a step-by-step guide in creating apps that makes use of the TeamViewer API. The documentation can be downloaded from here.

Examples

You can find a list of examples on how to create a basic TeamViewer app from here.

Using the TeamViewer API

First off, your app needs to be authenticated. This confirms (through your app) that you do in fact have the appropriate tokens to make use of the API. Here is a small example on how to get authenticated with the TeamViewer API:

Imports System
Imports System.Net
Imports System.Security.Cryptography
Imports System.Text
Imports CreateSession.CustomException
Imports CreateSession.DataType
Imports CreateSession.Ressources
Imports CreateSession.Views
Imports Newtonsoft.Json

Namespace CreateSession.Helper
   Friend Delegate Sub OauthProcessCompleteHandler()

   Friend Class OAuth
      #Region "internal fields"

   ' TODO: Insert your client id here:
      Friend Const ClientId As String = ""

   ' TODO: Insert your client secret here:
      Friend Const ClientSecret As String = ""

   ' TODO: Insert your redirect uri here:
      Friend Const RedirectUri As String = ""

      #End Region ' internal fields

      #Region "private fields"

      Private Shared s_currentinstance As OAuth
      Private ReadOnly _additionalEntropy() As Byte = _
         Encoding.ASCII.GetBytes("Just a sample")

      Private _webView4Oauth As Webview4Oauth

      #End Region ' private fields

      #Region "constructors"

      Private Sub New()
         Tokens = New Token With {.TokenType = TokenType.AppToken}
         ReadTokens()
      End Sub

      #End Region ' constructors

      #Region "events"

      Friend Event OauthProcessComplete As OauthProcessCompleteHandler

      #End Region ' events

      #Region "properties"

      Friend Shared ReadOnly Property CurrentCurrentinstance() As OAuth
         Get
            If s_currentinstance Is Nothing Then
               s_currentinstance = New OAuth()
            End If
            Return s_currentinstance
         End Get
      End Property

      Private privateTokens As Token
      Friend Property Tokens() As Token
         Get
            Return privateTokens
         End Get
         Private Set(ByVal value As Token)
            privateTokens = value
         End Set
      End Property

      Friend ReadOnly Property TokensAvailable() As Boolean
         Get
            Return (Tokens IsNot Nothing AndAlso Not _
               String.IsNullOrEmpty(Tokens.AccessToken) AndAlso Not _
               String.IsNullOrEmpty(Tokens.RefreshToken))
         End Get
      End Property

      #End Region ' properties

      #Region "internal methods"

      Friend Shared Function ValidateToken(ByVal tokenType As TokenType, _
            ByVal accessToken As String) As String
         If tokenType = CreateSession.Ressources.TokenType.SkriptToken AndAlso _
               Not String.IsNullOrEmpty(accessToken) Then
            Return accessToken
         End If
         If tokenType = CreateSession.Ressources.TokenType.AppToken AndAlso _
               CurrentCurrentinstance.TokensAvailable Then
            If CurrentCurrentinstance.AccessTokenIsExpired() Then
               CurrentCurrentinstance.RefreshAccesToken()
            End If
            Return CurrentCurrentinstance.Tokens.AccessToken
         End If
         Throw New AuthorizationException(Resources.Error_AccessTokenRequired)
      End Function

      ''' <summary>
      '''    Pings the API to validate the access tokens
      ''' </summary>
      ''' <returns></returns>
      Friend Function AccessTokenIsExpired() As Boolean
         Dim rp = New RestProperties With {.Url = TvApiUrls.UrlPing, .Method = _
            WebRequestMethods.Http.Get, .AccessToken = Tokens.AccessToken}

         Dim jsonResultString As String = (New RestConnection(rp)).SendToApi()
         If String.Empty <> jsonResultString Then
            Dim pingResult = New With {Key .token_valid = False}
            pingResult = JsonConvert.DeserializeAnonymousType _
               (jsonResultString, pingResult)
            Return Not pingResult.token_valid
         End If

         Return True
      End Function

      ''' <summary>
      '''    Sets the url and the postdata to get a new access tokens
      '''    from the api
      ''' </summary>
      ''' <param name="code">Authorisierungcode zur Erstellung
      '''    des neuen tokens</param>
      Friend Sub GetNewAccessToken(ByVal code As String)
         If code = String.Empty Then
            Return
         End If

         Dim postData = New StringBuilder()
         postData.Append("grant_type=authorization_code")
         postData.Append("&code=" & code)
         postData.Append("&redirect_uri=" & RedirectUri)
         postData.Append("&client_id=" & ClientId)
         postData.Append("&client_secret=" & ClientSecret)

         RetrieveAndSetTokensFromApi(postData.ToString())
      End Sub

      ''' <summary>
      '''    Opens the webview to authorize the app
      ''' </summary>
      Friend Sub OpenWebviewForNewAccessToken()
         _webView4Oauth = New Webview4Oauth()
         AddHandler _webView4Oauth.WebViewFinished, _
            AddressOf GetNewAccessToken
         _webView4Oauth.ShowDialog()
      End Sub

      ''' <summary>
      '''    Reads the tokens from the encrypted binary files
      '''    and decrypts them
      ''' </summary>
      Friend Sub ReadTokens()
         If My.Settings.Default.AccessToken IsNot Nothing Then
            Try
               Dim encryptedAccessToken() As Byte = _
                  My.Settings.Default.AccessToken
               Dim decryptedAccessToken() As Byte = _
                  ProtectedData.Unprotect(encryptedAccessToken, _
                  _additionalEntropy, DataProtectionScope.CurrentUser)

               Tokens.AccessToken = _
                  Encoding.Default.GetString(decryptedAccessToken)

               Dim encryptedRefreshToken() As Byte = _
                  My.Settings.Default.RefreshToken
               Dim decryptedRefreshToken() As Byte = _
                  ProtectedData.Unprotect(encryptedRefreshToken, _
                  _additionalEntropy, DataProtectionScope.CurrentUser)
               Tokens.RefreshToken = _
                  Encoding.Default.GetString(decryptedRefreshToken)
            Catch e1 As CryptographicException
               Tools.StandardErrorMessage("Error on decrypting
                  the tokens-files!" & ControlChars.Lf & _
                  "Files or tokens seem to be defective ..." _
                  & ControlChars.Lf & ControlChars.Lf & _
                  "New Authorization is acquired!", _
                  "Decryption error")
            End Try
         End If
      End Sub

      ''' <summary>
      '''    Sets the url and the postdata to get a new access tokens
      '''    from the api after the old one is expired
      ''' </summary>
      Friend Sub RefreshAccesToken()
         If Tokens.RefreshToken = String.Empty Then
            Return
         End If

         Dim postData = New StringBuilder()
         postData.Append("grant_type=refresh_token")
         postData.Append("&refresh_token=" & Tokens.RefreshToken)
         postData.Append("&client_id=" & ClientId)
         postData.Append("&client_secret=" & ClientSecret)

         RetrieveAndSetTokensFromApi(postData.ToString())
      End Sub

      ''' <summary>
      '''    Calling the API for the new tokens and save them
      ''' </summary>
      ''' <param name="postData"></param>
      Friend Sub RetrieveAndSetTokensFromApi(ByVal postData As String)
         Dim restProperties = New RestProperties With {.Url = TvApiUrls.UrlToken, _
            .Method = WebRequestMethods.Http.Post, .ContentType = _
            HttpContentTypes.ApplicationXWwwFormUrlEncoded, .PostData = postData}

         Dim jsonResultString As String = _
            (New RestConnection(restProperties)).SendToApi()
         If String.Empty <> jsonResultString Then
            Tokens = JsonConvert.DeserializeObject(Of Token)(jsonResultString)
            SaveTokens()
            ' Check if someone is listening to the OauthProcessComplete-Event
            ' Event to inform the main thread that the OAuth-Process is complete
            ' and that he can use the new tokens to create a new session via
            ' the API
            RaiseEvent OauthProcessComplete()
         End If
      End Sub

      ''' <summary>
      '''    Ecnrypts the tokens and saves them to binary files
      ''' </summary>
      Friend Sub SaveTokens()
         Try
            Dim encryptedAccessToken() As Byte = _
               ProtectedData.Protect(Tools.StringToByteArray(Tokens.AccessToken), _
               _additionalEntropy, DataProtectionScope.CurrentUser)
            My.Settings.Default.AccessToken = encryptedAccessToken

            Dim encryptedRefreshToken() As Byte = _
               ProtectedData.Protect(Tools.StringToByteArray(Tokens.RefreshToken), _
               _additionalEntropy, DataProtectionScope.CurrentUser)
            My.Settings.Default.RefreshToken = encryptedRefreshToken
            My.Settings.Default.Save()
         Catch e As Exception
            Tools.StandardErrorMessage(e.Message)
         End Try
      End Sub

      #End Region ' internal methods
   End Class
End Namespace

This Namespace handles the Authentication. It simply checks to see if you have a valid token, then tries to connect to the corresponding URL as specified through the Webview4Oauth class (it was referenced earlier when we connected to the Authorization page).

Everything Okay?

Namespace CreateSession.Views
   Friend Delegate Sub WebViewFinishedHandler(ByVal code As String)

   Partial Friend Class Webview4Oauth
      Inherits Form

      Friend Event WebViewFinished As WebViewFinishedHandler

      ''' <summary>
      '''    Constructor -> navigates to the defined url on startup
      ''' </summary>
      Friend Sub New()
         InitializeComponent()

         Dim url = New StringBuilder("https://webapi.teamviewer.com")
         url.Append("/api/v1/oauth2/authorize")
         url.Append("?")
         url.Append("response_type=code")
         url.Append("&client_id=" & OAuth.ClientId)
         url.Append("&redirect_uri=" & OAuth.RedirectUri)
         url.Append("&display=popup")

         oauthWebBrowser.Navigate(url.ToString())

         oauthWebBrowser.Select()
         oauthWebBrowser.Focus()
      End Sub

      ''' <summary>
      '''    Url of the webview has changed
      ''' </summary>
      ''' <param name="sender"></param>
      ''' <param name="e"></param>
      Private Sub oauthWebBrowser_Navigated(ByVal sender As Object, _
         ByVal e As WebBrowserNavigatedEventArgs) _
         Handles oauthWebBrowser.Navigated
         ' Checks the changed url corresponds to the final url with the code
         If oauthWebBrowser.Url.Query.Contains("code=") Then
            ' Extract the code from the link
            Dim urlParameters = _
               HttpUtility.ParseQueryString(oauthWebBrowser.Url.Query)
            Dim code As String = urlParameters("code")

            ' Inform asynchronous thread that the new code is available
            ' and deliver it
            If code <> String.Empty Then
               RaiseEvent WebViewFinished(code)
            Else
               MessageBox.Show("Code for the new access-token could not be _
                  retrieved!", "Error", MessageBoxButtons.OK, _
                  MessageBoxIcon.Error)
            End If

            Close()
         End If
      End Sub
   End Class
End Namespace
Namespace CreateSession.Ressources
   Friend Module TvApiUrls
      Public Const UrlCreateSession As String = _
         "https://webapi.teamviewer.com/api/v1/sessions"

      Public Const UrlGetGroupIds As String = _
         "https://webapi.teamviewer.com/api/v1/groups"

      Public Const UrlPing As String = _
         "https://webapi.teamviewer.com/api/v1/ping"

      Public Const UrlToken As String = _
         "https://webapi.teamviewer.com/api/v1/oauth2/token"
   End Module
End Namespace

This class ensures that we are indeed validated and that the resulting URL can be found and be accessed.

Getting the Application Info

Namespace CreateSession.Helper
   Friend Class ApplicationInfo
      ''' <summary>
      '''    get assembly title
      ''' </summary>
      Friend Shared ReadOnly Property AssemblyTitle() As String
         Get
            Dim attributes() As Object = _
               System.Reflection.Assembly.GetExecutingAssembly()._
               GetCustomAttributes(GetType(AssemblyTitleAttribute), False)

            If attributes.Length > 0 Then
               Dim titleAttribute As AssemblyTitleAttribute = _
                  DirectCast(attributes(0), AssemblyTitleAttribute)

                  If titleAttribute.Title <> String.Empty Then
                     Return titleAttribute.Title
                  End If
            End If

            Return Path.GetFileNameWithoutExtension(System.Reflection.Assembly _
               .GetExecutingAssembly().CodeBase)
         End Get
      End Property

      ''' <summary>
      '''    get assembly version
      ''' </summary>
      Friend Shared ReadOnly Property AssemblyVersion() As String
         Get
            Return System.Reflection.Assembly.GetExecutingAssembly() _
               .GetName().Version.ToString()
         End Get
      End Property

      ''' <summary>
      '''    get assembly description
      ''' </summary>
      Friend Shared ReadOnly Property AssemblyDescription() As String
         Get
            Dim attributes() As Object = _
               System.Reflection.Assembly.GetExecutingAssembly() _
               .GetCustomAttributes(GetType(AssemblyDescriptionAttribute), False)

            If attributes.Length = 0 Then
               Return String.Empty
            End If

            Return DirectCast(attributes(0), AssemblyDescriptionAttribute).Description
         End Get
      End Property

      ''' <summary>
      '''    get assembly product
      ''' </summary>
      Friend Shared ReadOnly Property AssemblyProduct() As String
         Get
            Dim attributes() As Object = _
               System.Reflection.Assembly.GetExecutingAssembly() _
               .GetCustomAttributes(GetType(AssemblyProductAttribute), False)

            If attributes.Length = 0 Then
               Return String.Empty
            End If

            Return DirectCast(attributes(0), AssemblyProductAttribute).Product
         End Get
      End Property

      ''' <summary>
      '''    get assembly copyright
      ''' </summary>
      Friend Shared ReadOnly Property AssemblyCopyright() As String
         Get
            Dim attributes() As Object = _
               System.Reflection.Assembly.GetExecutingAssembly() _
               .GetCustomAttributes(GetType(AssemblyCopyrightAttribute), False)

            If attributes.Length = 0 Then
               Return String.Empty
            End If

            Return DirectCast(attributes(0), AssemblyCopyrightAttribute).Copyright
         End Get
      End Property

      ''' <summary>
      '''    get assembly company
      ''' </summary>
      Friend Shared ReadOnly Property AssemblyCompany() As String
         Get
            Dim attributes() As Object = _
               System.Reflection.Assembly.GetExecutingAssembly() _
               .GetCustomAttributes(GetType(AssemblyCompanyAttribute), False)

            If attributes.Length = 0 Then
               Return String.Empty
            End If

            Return DirectCast(attributes(0), AssemblyCompanyAttribute).Company
         End Get
      End Property

      Friend Shared Function RetrieveLinkerTimestamp() As Date
         Dim filePath = System.Reflection.Assembly.GetCallingAssembly().Location
         Const cPeHeaderOffset As Integer = 6
         Const cLinkerTimestampOffset As Integer = 8
         Dim b = New Byte(2047){}
         Dim s As Stream = Nothing

         Try
            s = New FileStream(filePath, FileMode.Open, FileAccess.Read)
            s.Read(b, 0, 2048)
         Finally
            If s IsNot Nothing Then
               s.Close()
            End If
         End Try

         Dim i = BitConverter.ToInt32(b, cPeHeaderOffset)
         Dim secondsSince1970 = _
            BitConverter.ToInt32(b, i + cLinkerTimestampOffset)
         Dim dt = New Date(1970, 1, 1, 0, 0, 0)
         dt = dt.AddSeconds(secondsSince1970)
         dt = dt.AddHours(TimeZone.CurrentTimeZone.GetUtcOffset(dt).Hours)
         Return dt
      End Function
   End Class
End Namespace

API Functionalities

Namespace CreateSession.Helper
   Friend Class ApiFunctions
      Friend Shared Function GetGroupsOfAccount(ByVal tokenType As TokenType, _
            Optional ByVal accessToken As String = Nothing) As Group()
         ' First setting up a new RestProperties and define the attributes
         ' needed for "GET /api/v1/groups (list all available groups)"
         Dim rp4GroupIDs = New RestProperties With {.Url = _
            TvApiUrls.UrlGetGroupIds, .Method = WebRequestMethods.Http.Get, _
            .AccessToken = OAuth.ValidateToken(tokenType, accessToken)}

         ' Set up a new API-Connection
         Dim rc4GroupIDs = New RestConnection(rp4GroupIDs)
         ' Send the newly created RestProperties to the API and retrieve
         ' the JSON string
         Dim resultJsonString = rc4GroupIDs.SendToApi()
         If String.Empty <> resultJsonString Then
            ' Extracting the group names from the JSON-string we got
            ' from the API
            Dim groups = _
               JsonConvert.DeserializeObject(Of Groups)(resultJsonString)
            Return groups.GroupArray
         End If

         Return Nothing
      End Function

      Friend Shared Sub CreateInstantSupportSession(ByRef _
         instantSupportInfo As InstantSupportInfo, ByVal tokenType _
         As TokenType, Optional ByVal accessToken As String = Nothing)
         Dim restProperties = _
            New RestProperties With {.Url = TvApiUrls.UrlCreateSession, _
            .Method = WebRequestMethods.Http.Post, .PostData = _
            JsonConvert.SerializeObject(instantSupportInfo), _
            .AccessToken = OAuth.ValidateToken(tokenType, accessToken)}

         ' Create a new RestConnection with the completed RestProperties
         Dim rc = New RestConnection(restProperties)

         ' Send data to the API and retrieve the JSON data
         Dim resultJsonString = rc.SendToApi()

         ' Extract the session data from the JSON string
         If String.Empty <> resultJsonString Then
            instantSupportInfo = _
               JsonConvert.DeserializeObject(Of InstantSupportInfo)(resultJsonString)
            instantSupportInfo.UnformatedJsonString = resultJsonString
         Else
            instantSupportInfo = Nothing
         End If
      End Sub
   End Class
End Namespace

Conclusion

As you can see, once you know where to find the particular APIs and documentation needed, developing apps with third-party DLLs is quite easy. Until next time, happy coding!.

Hannes DuPreez
Hannes DuPreez
Ockert J. du Preez is a passionate coder and always willing to learn. He has written hundreds of developer articles over the years detailing his programming quests and adventures. He has written the following books: Visual Studio 2019 In-Depth (BpB Publications) JavaScript for Gurus (BpB Publications) He was the Technical Editor for Professional C++, 5th Edition (Wiley) He was a Microsoft Most Valuable Professional for .NET (2008–2017).

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read