Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

ezRemote, Remote Desktop Connection Manager

0.00/5 (No votes)
23 Nov 2012 1  
Easy Remote Desktop Using C#.net

Introduction  

ezRemote makes Remote Desktop Work more easy and fast. 

Background  

Remote Desktop is very useful for managing remote computers. I have decided to expand remote desktop to a level where user can do multiple remote machine in one application.

In the article we are going to integrate remote desktop in windows application using C#. To use finicality of remote desktop we are going to use Microsoft Terminal Services Control Type Library. The purpose of this application to manage all remote desktop connections at one place and have facility to work with multiple connection from one application, provide easy to maintain list of remote connection, search and delete options. 

Points of Interest   

  • Can store all remote machine details at one place 
  • Search feature 
  • Tabbed look, can have multiple connection in one application same time
  • Full screen feature
  • Copy paste data
  • Easy to use
  • Can share connections with other, (From C:\autoremote, give your connection to other person so it reduces recreating)
  • Encrypted connection files

External Library 

To connect with remote machine I have used COM Component Microsoft Terminal Services Control Type Library. You can add the com to toolbar from right click on toolbar->Chose Items->Com Components (tab from new window). Now search for Terminal Services Control Type Library, double click to add to toolbar.

Implementation

Add New Remote Machine: To connect with any remote machine ip, username and password is necessary. To save this information and use further in the software here a UI is created. The main thing here is to save this information independently as well as provide security. The information is saved as text file with .rtm extension in C:\autoremote folder. The data is encrypted. The class used to encrypt decrypt is as under.   

using System; 
using System.Collections.Generic;
using System.Linq;
using System.Text; 
using System.IO;
using System.Security.Cryptography;
namespace AutoRemote.BAL
{static public class Crypto
  {
     private static readonly byte[] salt = Encoding.ASCII.GetBytes("TrendMicro");
     public static string Encrypt(string textToEncrypt)
     {
       string encryptionPassword = "IG";
       var algorithm = GetAlgorithm(encryptionPassword);
       byte[] encryptedBytes;
       using (ICryptoTransform encryptor = algorithm.CreateEncryptor(algorithm.Key, algorithm.IV))
       {
         byte[] bytesToEncrypt = Encoding.UTF8.GetBytes(textToEncrypt);
         encryptedBytes = InMemoryCrypt(bytesToEncrypt, encryptor);
       }
       return Convert.ToBase64String(encryptedBytes);
     }
     public static string Decrypt(string encryptedText)
     {
       string encryptionPassword = "IG";
       var algorithm = GetAlgorithm(encryptionPassword);
       byte[] descryptedBytes;
       using (ICryptoTransform decryptor = algorithm.CreateDecryptor(algorithm.Key, algorithm.IV))
       {
         byte[] encryptedBytes = Convert.FromBase64String(encryptedText);
         descryptedBytes = InMemoryCrypt(encryptedBytes, decryptor);
       } 
       return Encoding.UTF8.GetString(descryptedBytes);
     }
     // Performs an in-memory encrypt/decrypt transformation on a byte array.
     private static byte[] InMemoryCrypt(byte[] data, ICryptoTransform transform)
     {
       MemoryStream memory = new MemoryStream();
       using (Stream stream = new CryptoStream(memory, transform, CryptoStreamMode.Write))
       {
         stream.Write(data, 0, data.Length);
       }
       return memory.ToArray();
     }
     // Defines a RijndaelManaged algorithm and sets its key and Initialization Vector (IV) 
     // values based on the encryptionPassword received.
     private static RijndaelManaged GetAlgorithm(string encryptionPassword)
     { 
       // Create an encryption key from the encryptionPassword and salt.
       var key = new Rfc2898DeriveBytes(encryptionPassword, salt);
       // Declare that we are going to use the Rijndael algorithm with the key that we've just got.
       var algorithm = new RijndaelManaged();
       int bytesForKey = algorithm.KeySize / 8;
       int bytesForIV = algorithm.BlockSize / 8;
       algorithm.Key = key.GetBytes(bytesForKey);
       algorithm.IV = key.GetBytes(bytesForIV);
       return algorithm;
     } 
   } 
}

Connect With Remote Machines:

To provide multiple remote connections on single application, tab control is used in application. For each new connection request it search for already open connection; if not found it create a new tab page and open new connection with the use of UserControl "CtlRemote". CtlRemote provides remote desktop connection facility as well zoom and close facility.

private void dg_DoubleClick(object sender, EventArgs e)
     {
       if (dg.SelectedRows.Count > 0)
       { 
         ManageTabs(dg.SelectedRows[0].Cells[0].Value.ToString(), dg.SelectedRows[0].Cells[1].Value.ToString(), dg.SelectedRows[0].Cells[2].Value.ToString(), dg.SelectedRows[0].Cells[0].Tag.ToString());
       }
     }
public void ManageTabs(string ip, string title, string username, string password)
     {
       try
       {
         panel2.Visible = false;
         for (int i = 0; i <= tab1.TabPages.Count - 1; i++)
         {
           if (tab1.TabPages[i].Tag == ip)
           {
             tab1.TabPages[i].Select();
             tab1.SelectedTab = tab1.TabPages[i];
             return;
           }
         }
         TabPage page = new TabPage();
         CtlRemote remote = new CtlRemote();
         page.Tag = ip;
         page.ImageIndex = 0;
         tab1.TabPages.Add(page);
         page.Text = title + "[" + ip + "]";
         remote.lblname.Text = title + "[" + ip + "]";
         page.Controls.Add(remote);
         remote.Visible = true;
         remote.Dock = DockStyle.Fill;
         tab1.TabPages[tab1.TabPages.Count - 1].Select();
         tab1.SelectedTab = page;
         remote.remote1.Server = ip;
         remote.remote1.UserName = username;
         IMsTscNonScriptable secured = (IMsTscNonScriptable)remote.remote1.GetOcx();
         secured.ClearTextPassword = password;
         remote.remote1.Connect();
         remote.username = username;
         remote.password = password;
         remote.ip = ip;
         
       }
       catch (System.Exception ex)
       {
         AppUtils.Error(ex.ToString());
       }
     }

Manage Remote Connections:  The software loads all the connection made by user from the directory "C:\autoremote". When user crates or deletes any new connection file is created or deleted. RemoteMachin class is used for search operation.  

private void ListRemoteMachine()
     {
       try
       {
         RemoteMachine.list.Clear();
         dg.Rows.Clear();
         if (Directory.Exists(AppUtils.datapath) == false)
         {
           Directory.CreateDirectory(AppUtils.datapath);
         }
         DirectoryInfo dir = new DirectoryInfo(AppUtils.datapath);
         FileInfo[] rf = dir.GetFiles();
         for (int i = 0; i <= rf.Length - 1; i++)
         {
           if (Path.GetExtension(rf[i].FullName) == ".rmt")
           {
             string str = File.ReadAllText(rf[i].FullName);
             string strnew = Crypto.Decrypt(str);
             string[] tmp = Regex.Split(strnew, "<<<<999999<<<<");
             string[] tmp2 = { tmp[0], tmp[1], tmp[2] };
             dg.Rows.Add(tmp2);
             dg.Rows[dg.Rows.Count - 1].Tag = rf[i].FullName;
             dg.Rows[dg.Rows.Count - 1].Cells[0].Tag = tmp[3];
             dg.Rows[dg.Rows.Count - 1].Cells[1].Tag = tmp[4];
             RemoteMachine.list.Add(new RemoteMachine(tmp[0], tmp[1], tmp[2], tmp[4], tmp[5], rf[i].FullName));
           }
         }
       }
       catch (System.Exception ex)
       {
         AppUtils.Error(ex.ToString());
       }
     }
  private void txtsearch_TextChanged(object sender, EventArgs e)
     {
       if (txtsearch.Text == "")
       {
         ListRemoteMachine();
       }
       else
       {
         dg.Rows.Clear();
         List<RemoteMachine> list = RemoteMachine.GetList(txtsearch.Text);
         for (int i = 0; i <= list.Count - 1; i++)
         {
           if (Path.GetExtension(list[i].FilePath) == ".rmt")
           {
             string[] tmp2 = { list[i].IP, list[i].Title, list[i].Username };
             dg.Rows.Add(tmp2);
             dg.Rows[dg.Rows.Count - 1].Tag = list[i].FilePath;
             dg.Rows[dg.Rows.Count - 1].Cells[0].Tag = list[i].Password;
             dg.Rows[dg.Rows.Count - 1].Cells[1].Tag = list[i].Description;
           }
         }
       }
     }
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace AutoRemote.BAL
{
   class RemoteMachine
   {
     public static List<RemoteMachine> list = new List<RemoteMachine>();
     public string IP, Title, Username, Password, Description, FilePath;
     public RemoteMachine()
     {
     }
     public RemoteMachine(string _IP, string _Title, string _Username, string _Password, string _Description, string _FilePath)
     {
       IP = _IP;
       Title = _Title;
       Username = _Username;
       Password = _Password;
       Description = _Description;
       FilePath = _FilePath;
     }
     public static List<RemoteMachine> GetList(string search)
     {
       if (search == "")
       {
         return list;
       }
       search = search.ToLower();
       var qry=from c in list
           where c.IP.ToLower().Contains(search) ||  c.Title.ToLower().Contains(search)
           select c;
       return  qry.ToList();
     }
   } 
}

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here