Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / desktop / WPF

GDrive Explorer - For Google Drive

4.88/5 (64 votes)
16 Sep 2013CPOL8 min read 168.4K   15.9K  
Browse your Google Drive and integrate your windows explorer with a Google's storage Cloud

Introduction

Cloud storage has cleverly become a good selling point for many solutions. Though the term 'Cloud' is a bit over-rated (totally personal opinion) it eats up most of the legacy problems. At least a bunch of people are at peace as the complexity of management (be it storage or any other thing) is left to the best brains at an affordable cost. For example, the obvious drawbacks of maintaining redundant storage media are not handled anymore. And thus businesses like Google Drive and Sky Drive have rocketed many folds in such short span of times in consumer to SMBs to large business solutions. 

To make things more flexible or professional these days we get free development APIs from these providers. Such APIs not only make private applications integrate-able but also brings in possibilities for seamlessly consuming cloud services with just one click of a mouse for the end-user.

This brings me to the point of end-user. Many a times such 'robots', so fascinated by cloud or rain, are in dire need for solutions that can be dumb-proof and also 'Cloud oriented' (I consciously use the term 'Cloud Oriented' in a smaller scope from what it can actually mean). I have personally spoken to a bunch of folks at different conferences (some related to Cloud Computing) who understand the need and actually need 'on-demand-cloud-storage-with-one-click' that is integrate-able with their legacy (or not so legacy) enterprise storage solutions. Some of them are good with corporate clouds, some to their private ones. But the most interesting ones are talking of already available cloud solutions. In short they need their existing storage frameworks to be seamlessly replaced by Google drive or sky drive or box or dropbox or etc or etc. The reasons they talk of are also quite logical. They don't want to buy hard-drives every month. They also don't want to risk their data by not maintaining automatically replicating scheduled scripts. In even shorter term, they want to leave the hair-loosing thoughts to the people who have already lost them :)

Image 1

Figure 0: Main Explorer UI 

Background

It was one such 'daily 6 hours travel for office' that I met a sufferer of data-loss fear. And he too demanding the same thing, brought me to the page where I decided to do a POC with one of the free-public storage APIs. After trying hands on a few I found Google's API to be more 'fluid' than the others and decided to GO at it.

After a few initial tries, I got a good bite at the still maturing Google Drive 2 API. Having past experience in exposing storage data servers APIs, I wondered, how similar all of them could be and just how comfortable client applications expects to be :) The POC soon bubbled up to a semi-handsome store box for the Windows-7 desktop PC. Drive2's C# sdk had been the biggest bet with some presentation and queue implementations I could bundle this tiny app in a week. Still far from perfect and needs more improvements, I decided to write up my article for reviews and sharing some functional code for those who are still deciding to consume Google Drive2 API SDK.

Using the application 

Hey, so here is "My GDrive Explorer" or "GDrive Explorer" (incidentally these are the release and dev version names respectively). 

What the user can do with the application? 

  • Asks for authcode by directing the user to a 'grant-access' URL
  • On getting access it shows some user info on the left panel
  • On getting another access it shows the drive contents on the right panel
  • Lets authorized user browse your drive similar to windows explorer (back/forward/home/refresh)
  • Lets authorized user create new folders
  • Lets authorized user upload/download files
  • Lets authorized user delete/rename files/folders
  • Presently Word/Excel/PowerPoint/text/PDF file uploading are supported (Google drive supports files of types https://support.google.com/drive/answer/2423485?hl=en)
  • Downloading of all user files are supported (Google doesn't let users download files created with GoogleDocs)
  • Upload multiple files in parallel (with upload progress notification)
  • Download multiple files in parallel (with download progress notification)
  • Search files/folders within the current Drive folder (free text search)
  • Trash files (not folders) to bin 
  • Trash view and able to restore/permanently-delete trashed documents
  • Send documents directly from explorer to GoogleDrive by right clicking on a file-item (only single selection is supported. The context menu item works on windows 7 and should be visible till the application is running)
  • Send documents directly from MS Office Applications (Word, Excel, PowerPoint, and Outlook) by installing additional Office COM AddIn (developed using NetOffice - MS Office in .NET  - http://netoffice.codeplex.com/

Usage hints: 

The application works with oauth2 authentication mechanism and would prompt the user to grant access to the Files and About mechanism. The user has to click "Accept" button for both requests. The page is displayed in a popup-webbrowser control. Post success the response message is scraped and the authtoken is used to access. If scraping fails a fallback authtoken dialog is shown for manual authentication.

There would be 2 dialogs here one for "About" and one for "Files". Both have to be allowed for further access.

My experience here is that the user has to click couple of three times on each of the two authorization dialogs to activate it. It is a known issue and work is in progress. 

Figure 1: Authorization Dialog 

Image 2 

Figure 2: Authorization Fallback Dialog 

Image 3

On Fail, application will not allow to continue and will shutdown.

Safety Concerns: The entire code is made available with this article and the application does not do any mischievous things with you account. You may choose to walk through the whole code-base to guarantee your safety.

On Successful login, user should see a explorable screen as below. The features are tool-tipped and self explanatory. For a detailed usage guidelines, please download the user manual attached with this article.

Figure 3: Upload/Download Progress Indication 

Image 4

When the application is active, users can direct send a selected file to the application. These files will directly be queued for uploading to Google drive in the currently selected folder.

Figure 4: Integration with Windows Explorer 

Image 5

Installing MS Office Addins 

Download "MicrosoftOfficeAddIns.zip" attached at the top of this article. These addins are office COM AddIns for office 2007 and 2010 developed using NetOffice - MS Office in .NET (http://netoffice.codeplex.com/).

Once downloaded, you can use the standard "regasm" command from the command prompt to install or uninstall. The commands are attached in 'bat' files with the download.

To install use:

regasm GDrive.Explorer.MSOfficeAddIn.dll

To uninstall use: 

regasm GDrive.Explorer.MSOfficeAddIn.dll /unregister

If everything works well here is what you should see after restarting the office applications. And once you click the 'send' button the document should directly get uploaded to your Google Drive Cloud Storage Space.

Please note, that the send to Google Drive would only work when the GDrive Explorer application is active and running. 

The source can be compiled by including necessary binaries from http://netoffice.codeplex.com/

Image 6

How does it work?

GDrive.Framework

A little delve into the code. The code GoogleDrive API is wrapped in an Framework called as GDrive.Framework. The framework acts as a Facade for access to the storage APIs. 

There is a authentication mechanism which goes through oAuth 2 and an authCode has to be received from a grant-access mechanism. This is routed through a webbrowser control in the GDriveAuthentication class. The code is same as mentioned here [https://developers.google.com/drive/quickstart-cs]

The attached code has dependencies on these binaries and would only compile when they are referenced. 

Other Links: 

Drive2 API 

Google APIs 

C#
public class GDriveAuthentication
{
     public DriveService GetDriveService()
     {
        string CLIENT_ID = "CLIENT ID";
        string CLIENT_SECRET = "CLIENT SECRET";

        // Register the authenticator and create the service
        var provider = new NativeApplicationClient(
            GoogleAuthenticationServer.Description, CLIENT_ID, CLIENT_SECRET);
        var auth = new OAuth2Authenticator<NativeApplicationClient>(provider, GetAuthorization);
        var service = new DriveService(new BaseClientService.Initializer()
        {
            Authenticator = auth
        });

        return service;
    }

    private IAuthorizationState GetAuthorization(NativeApplicationClient arg)
    {
        // Get the auth URL:
        IAuthorizationState state = 
          new AuthorizationState(new[] { DriveService.Scopes.Drive.GetStringValue() });
        state.Callback = new Uri(NativeApplicationClient.OutOfBandCallbackUrl);
        Uri authUri = arg.RequestUserAuthorization(state);

        // Request authorization from the user (by opening a browser window):

        //Process.Start(authUri.ToString());
        //Console.Write("  Authorization Code: ");
        //string authCode = Console.ReadLine();
        //Console.WriteLine();

        var authCode = AuthorizationWindow.GetToken(authUri.ToString());

        if (string.IsNullOrEmpty(authCode))
            authCode = Interaction.InputBox("We did not find authcode. " + 
              "Please enter here to continue", "Authorization Code", string.Empty);

        // Retrieve the access token by using the authorization code:
        return arg.ProcessUserAuthorization(authCode ?? string.Empty, state);
    }
}

The main Facade class for exploring the drive (called as GDriveExplorer) provides generic implementations for the methods of use.

C#
public class GDriveExplorer
{
    private DriveService service;

    public GDriveExplorer()
    {
        service = new GDriveAuthentication().GetDriveService();
    }

    public GDriveFilesResponse GetFiles(string parentId = "root", string search = null,
        string pageToken = null, int? perpage = null, SortOrder order = SortOrder.LastModifiedDesc)
    {
       ...
    }

    public GDriveFilesResponse GetTrashedFiles(string search = null, 
              string pageToken = null, int? perpage = null)
    {
       ...
    }

    public bool TrashFile(string id)
    {
        ...
    }

    public bool UnTrashFile(string id)
    {
       ...
    }

    public bool DeleteFile(string id)
    {
        ...
    }

    public GDriveAbout GetInfo()
    {
       ...
    }

    public object UploadFileAsync(UploadQueueItem item, ProgressChange progressCallback)
    {
        ...
    }

    public bool UploadFile(UploadQueueItem item)
    {
        ...
    }

    public GDriveFile CreateFolder(GDriveFile folder, string parent)
    {
        ...
    }

    public GDriveFile Update(GDriveFile file)
    {
        ...
    }

    public object DownloadFile(DownloadQueueItem item, ProgressChange progressCallback)
    {
        ...              
    }
}

GDrive.Explorer

This is a WPF Application using MVVM. The entire code is MVVMd by practice so there is absolutely no code in the code-behind. The strictest MVVM is hard and sometimes not practical. So many people use it as a guideline rather than a practice. My personal experience with MVVM is also rudimentary and to call it a practice I have to toil harder. However, this is just a initial practice, so could do without code behind. This is what the code behind contains :)

C#
public partial class MainWindow : Window
{
    public MainWindow()
    {
	InitializeComponent();
    }
}

The main application is a singleton application. Means you cannot start more than one instance of the application. The class for that is App, which follows a standard singleton instance application using Microsoft.VisualBasic.

C#
public class SingleInstanceManager : WindowsFormsApplicationBase
{
    private App application;
    private ReadOnlyCollection<string> commandLine;

    public SingleInstanceManager()
    {
        IsSingleInstance = true;
    }

    protected override bool OnStartup(Microsoft.VisualBasic.ApplicationServices.StartupEventArgs eventArgs)
    {
        // First time _application is launched
        commandLine = eventArgs.CommandLine;
        application = new App();
        application.Run();           

        return false;
    }

    protected override void OnShutdown()
    {
        base.OnShutdown();
    }

    protected override void OnStartupNextInstance(StartupNextInstanceEventArgs eventArgs)
    {
        // Subsequent launches
        base.OnStartupNextInstance(eventArgs);
        //commandLine = eventArgs.CommandLine;
        application.Activate(eventArgs.CommandLine);
    }
}

Upload and download queue implementations are used to implement asynchronous upload/download patterns with progress updater. Somehow the upload notification is only fired at the end of the upload. I am still working on the AsyncUpload function. Downloads functionally deliver in progress notifications. These classes can be found in the attached codebase.

Notification Icon in the taskbar is used to control sending the application in the background. The icon can be double-clicked to show/hide the application window without closing it.

C#
public NotifyIconManager(Window mainwindow)
{
    try
    {
       System.Windows.Forms.NotifyIcon ni = new System.Windows.Forms.NotifyIcon()
       {
           Icon = System.Drawing.Icon.ExtractAssociatedIcon(this.GetType().Assembly.Location),
           ContextMenu = new System.Windows.Forms.ContextMenu(),
           Text = "Doubleclick to Show/Hide Window",
            Visible = true
       };

       ni.ContextMenu.MenuItems.Add(new System.Windows.Forms.MenuItem(
                           "Exit", (o, e) => App.InvokeShutDown()));
       ni.DoubleClick += (s, args) =>
       {
           if (!mainwindow.IsVisible)
           {
               mainwindow.Show();
               mainwindow.Activate();
           }
           else
           {
             mainwindow.Hide();
           }
       };
    }
    catch { }
}

The context menu item with icon in the Windows Explorer can be done using registry tweaks as in the RegistryEntry class.

C#
public class RegistryEntry
{
    public void CreateRegistry(params string[] extensions)
    {
        var filename = Assembly.GetEntryAssembly().Location;

        foreach (var ext in extensions)
        {
            var regmenu = Registry.CurrentUser.CreateSubKey("SOFTWARE\\Classes\\" + ext + "\\shell\\MyGDrive");
            if (regmenu != null)
            {
                regmenu.SetValue("", "Send to My GDrive");
                regmenu.SetValue("icon", "\"" + filename + "\",0");  // icon location - works in win7 and later
                regmenu.SetValue("MultiSelectModel", "Single"); // one by one entry mode - works in win7 and later
                regmenu.SetValue("EditFlags", new byte[] { 0x01, 0x00, 0x00, 0x00 }, RegistryValueKind.Binary);

                var regcmd = regmenu.CreateSubKey("command");
                if (regcmd != null)
                    regcmd.SetValue("", "\"" + filename + "\" \"%1\"");
            }
        }
    }

    public void RemoveRegistry(params string[] extensions)
    {
        foreach (var ext in extensions)
        {
            var key = "SOFTWARE\\Classes\\" + ext + "\\shell\\MyGDrive";
            if (Registry.CurrentUser.OpenSubKey(key) != null)
            {
                Registry.CurrentUser.DeleteSubKeyTree(key);
            }
        }
    }

    public bool IsUserAdministrator
    {
        get
        {
            bool isAdmin = false;
            try
            {
                var principal = new WindowsPrincipal(WindowsIdentity.GetCurrent());
                isAdmin = principal.IsInRole(WindowsBuiltInRole.Administrator);
            }
            catch (UnauthorizedAccessException)
            {
            }
            catch (Exception)
            {
            }
            return isAdmin;
        }
    }
}

The rest of the Presentation layer is divided in the following sections:

  • Commands: RelayCommands used in the viewmodels
  • Controls: A single control used in the application is SearchTextBox
  • Converters: A lot of value bindings use these standard converters for presentation
  • ViewModels: The viewmodels used in the view 
  • Images: Image/Icon resources used in the view

Using the code 

GDrive.Framework can be used as below.

C#
///Getting list of files in a folder

GDriveFilesResponse filesResponse = GetFiles(parentId, searchString, pageToken, perpage, sortorder);
string nextpagetoken = filesResponse.NextPageToken;
filesResponse.Files.ToList().ForEach(f =>
{
  // parse file information
});

/// Getting Trashed files in a folder
GDriveFilesResponse filesresponse = GDriveFilesResponse GetTrashedFiles(searchstring, pageToken, perpage);

/// send a file to trash
bool success =  TrashFile(fileid);

/// restore a file from trash
bool success =  UnTrashFile(fileid);

/// permanently delete a file
bool success = DeleteFile(fileid);

/// getting about info
GDriveAbout aboutinfo = GetInfo();

///upload file async
object result = UploadFileAsync(uploadQueueItem, progressChangeHandler);

///upload file syncronous
bool success = UploadFile(uploadQueueItem);

///creating a folder
GDriveFile folderinfo = CreateFolder(gDriveFileInfo, parentfolderid);

///update filename
GDriveFile fileinfo = Update(gDriveFileInfo);

///download file
object result = DownloadFile(downloadQueueItem, progressChangeHandler);

Known Issues 

  1. Ordering by name etc is not supported by Google yet, there are reported change requests in these areas (presently ordered by date-modified descending is the default).
  2. I haven't tested the upload async yet. The available implementation is with synchronous upload function within a BeginInvoke.
  3. Pagination is not implemented yet (presently only first 100 items are shown). I am looking for a way to do virtualized scrolling following MVVM (no code behind) - suggestions welcome in this area
  4. Some other new functionality development in progress. 

History

  • First post dated - September 3, 2013
  • Added MS Office AddIns - September 6, 2013
  • Build fixes - September 16, 2013 

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)