Programmatisch den Google-Drive-Ordner ermitteln

Im Artikel „Programmatisch den Dropbox-Ordner ermitteln“ habe ich beschrieben, wie Ihr den lokalen Dropbox-Ordner auf Eurem PC per Code ermitteln könnt. Und im Artikel „Programmatisch den OneDrive-Ordner ermitteln“ habe ich das gleiche für OneDrive beschrieben.

Fehlt noch der Dienst von Google, Google Drive. Auch dort ist es möglich, den lokalen Speicherort zu ermitteln, allerdings bedarf es SQLite-Routinen, um ihn auszulesen.

private static string checkGetGoogleDriveLocation()
{
    var appDataPath = Environment.GetFolderPath(
                          Environment.SpecialFolder.LocalApplicationData);
    var dbPath = Path.Combine(appDataPath, 
                     @"Google\Drive\user_default\sync_config.db");

    if (!File.Exists(dbPath)) return getFallBackLocation();

    var tmp = dbPath + Guid.NewGuid();
    File.CopyFile(dbPath, tmp);
    try
    {
        var folderPath = tryGetFolderFromGoogleDriveDB(tmp);
        if (string.IsNullOrEmpty(folderPath) || !Directory.Exists(folderPath)) 
            return getFallBackLocation();
    }
    finally
    {
        File.Delete(tmp);
    }

    return folderPath;
}

Die Funktion tryGetFolderFromGoogleDriveDB verwendet das SQLite-NuGet-Paket „sqlite-net“, das auch auf GitHub verfügbar ist:

private static string tryGetFolderFromGoogleDriveDB(string dbFilePath)
{
    using (var conn = new SQLiteConnection(dbFilePath, SQLiteOpenFlags.ReadOnly))
    {
        var cmd = conn.CreateCommand(
            @"select data_value from data where entry_key='local_sync_root_path'");
        return cmd.ExecuteScalar<string>();
    }
}

Die Fallback-Lösung geht schlicht auf den Ordner selbst:

private static string getFallBackLocation()
{
    var pers = Path.Combine(
        Environment.GetFolderPath(Environment.SpecialFolder.UserProfile),
        @"Google Drive");

    return Directory.Exists(pers) ? pers : null;
}

Wichtig ist, dass Ihr im Order, in dem Eure EXE-Programmdatei liegt, die unmanaged sqlite3.dll-Datei liegen habt, da sqlite-net dies via P/Invoke anspricht.

Auch diesen Code habe ich angelehnt an einen Stack-Overflow-Artikel aufgebaut.