├── .gitignore
├── LICENSE
├── README.md
├── SalesForceBackup.sln
├── SalesForceBackup
├── App.config
├── AppSettingKeys.cs
├── AppSettings.cs
├── AzureBlobUploader.cs
├── Backup.cs
├── ConsoleErrorHandler.cs
├── DataExportFile.cs
├── Enums.cs
├── Interfaces
│ ├── IAppSettings.cs
│ ├── IDownloader.cs
│ ├── IErrorHandler.cs
│ └── IUploader.cs
├── IoC
│ ├── Bootstrap.cs
│ └── TinyIoC.cs
├── Program.cs
├── Properties
│ ├── AssemblyInfo.cs
│ ├── Settings.Designer.cs
│ └── Settings.settings
├── S3Uploader.cs
├── SalesForce.wsdl
├── SalesForceBackup.csproj
├── SalesForceWebDownloader.cs
├── Web References
│ └── SFDC
│ │ ├── DeleteResult.datasource
│ │ ├── DescribeAppMenuItem.datasource
│ │ ├── DescribeApprovalLayout.datasource
│ │ ├── DescribeAvailableQuickActionResult.datasource
│ │ ├── DescribeCompactLayout.datasource
│ │ ├── DescribeCompactLayoutsResult.datasource
│ │ ├── DescribeDataCategoryGroupResult.datasource
│ │ ├── DescribeDataCategoryGroupStructureResult.datasource
│ │ ├── DescribeFlexiPageResult.datasource
│ │ ├── DescribeGlobalResult.datasource
│ │ ├── DescribeGlobalTheme.datasource
│ │ ├── DescribeLayoutResult.datasource
│ │ ├── DescribeQuickActionResult.datasource
│ │ ├── DescribeSObjectResult.datasource
│ │ ├── DescribeSearchLayoutResult.datasource
│ │ ├── DescribeSearchScopeOrderResult.datasource
│ │ ├── DescribeSoftphoneLayoutResult.datasource
│ │ ├── DescribeSoqlListView.datasource
│ │ ├── DescribeTab.datasource
│ │ ├── DescribeTabSetResult.datasource
│ │ ├── DescribeThemeItem.datasource
│ │ ├── EmptyRecycleBinResult.datasource
│ │ ├── ExecuteListViewResult.datasource
│ │ ├── GetDeletedResult.datasource
│ │ ├── GetServerTimestampResult.datasource
│ │ ├── GetUpdatedResult.datasource
│ │ ├── GetUserInfoResult.datasource
│ │ ├── InvalidateSessionsResult.datasource
│ │ ├── KnowledgeSettings.datasource
│ │ ├── LeadConvertResult.datasource
│ │ ├── LoginResult.datasource
│ │ ├── MergeResult.datasource
│ │ ├── PerformQuickActionResult.datasource
│ │ ├── ProcessResult.datasource
│ │ ├── QueryResult.datasource
│ │ ├── QuickActionTemplateResult.datasource
│ │ ├── Reference.cs
│ │ ├── Reference.map
│ │ ├── ResetPasswordResult.datasource
│ │ ├── SalesForce.wsdl
│ │ ├── SaveResult.datasource
│ │ ├── SearchResult.datasource
│ │ ├── SendEmailResult.datasource
│ │ ├── SetPasswordResult.datasource
│ │ ├── UndeleteResult.datasource
│ │ ├── UpsertResult.datasource
│ │ └── sObject.datasource
└── packages.config
└── azure-pipelines.yml
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.sln.docstates
8 |
9 | # Build results
10 | [Dd]ebug/
11 | [Dd]ebugPublic/
12 | [Rr]elease/
13 | [Rr]eleases/
14 | x64/
15 | x86/
16 | build/
17 | bld/
18 | [Bb]in/
19 | [Oo]bj/
20 |
21 | # Roslyn cache directories
22 | *.ide/
23 |
24 | # MSTest test Results
25 | [Tt]est[Rr]esult*/
26 | [Bb]uild[Ll]og.*
27 |
28 | #NUNIT
29 | *.VisualState.xml
30 | TestResult.xml
31 |
32 | # Build Results of an ATL Project
33 | [Dd]ebugPS/
34 | [Rr]eleasePS/
35 | dlldata.c
36 |
37 | *_i.c
38 | *_p.c
39 | *_i.h
40 | *.ilk
41 | *.meta
42 | *.obj
43 | *.pch
44 | *.pdb
45 | *.pgc
46 | *.pgd
47 | *.rsp
48 | *.sbr
49 | *.tlb
50 | *.tli
51 | *.tlh
52 | *.tmp
53 | *.tmp_proj
54 | *.log
55 | *.vspscc
56 | *.vssscc
57 | .builds
58 | *.pidb
59 | *.svclog
60 | *.scc
61 |
62 | # Chutzpah Test files
63 | _Chutzpah*
64 |
65 | # Visual C++ cache files
66 | ipch/
67 | *.aps
68 | *.ncb
69 | *.opensdf
70 | *.sdf
71 | *.cachefile
72 |
73 | # Visual Studio profiler
74 | *.psess
75 | *.vsp
76 | *.vspx
77 |
78 | # TFS 2012 Local Workspace
79 | $tf/
80 |
81 | # Guidance Automation Toolkit
82 | *.gpState
83 |
84 | # ReSharper is a .NET coding add-in
85 | _ReSharper*/
86 | *.[Rr]e[Ss]harper
87 | *.DotSettings.user
88 |
89 | # JustCode is a .NET coding addin-in
90 | .JustCode
91 |
92 | # TeamCity is a build add-in
93 | _TeamCity*
94 |
95 | # DotCover is a Code Coverage Tool
96 | *.dotCover
97 |
98 | # NCrunch
99 | _NCrunch_*
100 | .*crunch*.local.xml
101 |
102 | # MightyMoose
103 | *.mm.*
104 | AutoTest.Net/
105 |
106 | # Web workbench (sass)
107 | .sass-cache/
108 |
109 | # Installshield output folder
110 | [Ee]xpress/
111 |
112 | # DocProject is a documentation generator add-in
113 | DocProject/buildhelp/
114 | DocProject/Help/*.HxT
115 | DocProject/Help/*.HxC
116 | DocProject/Help/*.hhc
117 | DocProject/Help/*.hhk
118 | DocProject/Help/*.hhp
119 | DocProject/Help/Html2
120 | DocProject/Help/html
121 |
122 | # Click-Once directory
123 | publish/
124 |
125 | # Publish Web Output
126 | *.[Pp]ublish.xml
127 | *.azurePubxml
128 | # TODO: Comment the next line if you want to checkin your web deploy settings
129 | # but database connection strings (with potential passwords) will be unencrypted
130 | *.pubxml
131 | *.publishproj
132 |
133 | # NuGet Packages
134 | *.nupkg
135 | # The packages folder can be ignored because of Package Restore
136 | **/packages/*
137 | # except build/, which is used as an MSBuild target.
138 | !**/packages/build/
139 | # If using the old MSBuild-Integrated Package Restore, uncomment this:
140 | #!**/packages/repositories.config
141 |
142 | # Windows Azure Build Output
143 | csx/
144 | *.build.csdef
145 |
146 | # Windows Store app package directory
147 | AppPackages/
148 |
149 | # Others
150 | .vs/
151 | sql/
152 | *.Cache
153 | ClientBin/
154 | [Ss]tyle[Cc]op.*
155 | ~$*
156 | *~
157 | *.dbmdl
158 | *.dbproj.schemaview
159 | *.pfx
160 | *.publishsettings
161 | node_modules/
162 |
163 | # RIA/Silverlight projects
164 | Generated_Code/
165 |
166 | # Backup & report files from converting an old project file
167 | # to a newer Visual Studio version. Backup files are not needed,
168 | # because we have git ;-)
169 | _UpgradeReport_Files/
170 | Backup*/
171 | UpgradeLog*.XML
172 | UpgradeLog*.htm
173 |
174 | # SQL Server files
175 | *.mdf
176 | *.ldf
177 |
178 | # Business Intelligence projects
179 | *.rdl.data
180 | *.bim.layout
181 | *.bim_*.settings
182 |
183 | # Microsoft Fakes
184 | FakesAssemblies/
185 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Dan Thagard
4 | Copyright (c) 2020 Thomas Werner
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 |
24 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Salesforce-Backup [](https://dev.azure.com/huddeldaddel/huddeldaddel/_build/latest?definitionId=6&branchName=master)
2 |
3 | Performs automated backups of SalesForce.com export data locally or to either AWS or Azure.
4 |
5 | Usage
6 | =====
7 |
8 | You need to edit the App.config settings for your particular needs. The key values are as follows:
9 |
10 | | Key | Description | Default |
11 | | --- | --- | --- |
12 | | **AwsAccessKey** | The access key for the account with permissions to the AWS S3 bucket. | null |
13 | | **AWSRegion** | The region the AWS S3 bucket is located. | us-east-1 |
14 | | **AWSSecretKey** | The secret key for the account with permissions to the AWS S3 bucket. | null |
15 | | **AzureAccountName** | The Azure account name to connect to. | null |
16 | | **AzureBlobEndpoint** | The endpoint for the Azure storage account. | null|
17 | | **AzureContainer** | The Azure container to use for the backup. | monthlybackups |
18 | | **AzureFolder** | The folder to place the backup in inside the Azure container. | salesforce |
19 | | **AzureSharedKey** | The shared key for accessing the Azure storage container. | null |
20 | | **host** | The Salesforce.com host. | na17.salesforce.com |
21 | | **password** | The password for Salesforce.com. | null |
22 | | **S3Bucket** | The bucket to store the backup in AWS S3. | monthlybackups |
23 | | **S3Folder** | The folder to store the backup in AWS S3. | salesforce |
24 | | **scheme** | The schema for connecting to Salesforce.com. | https |
25 | | **uploader** | The uploader to use for the backup. Possible values are 'AWS' or 'Azure'. | Azure |
26 | | **username** | The username for Salesforce.com. | null |
27 |
28 | To run, simply execute the SalesForcebackup.exe at the command prompt. Optionally, you can pass in some arguments at runtime:
29 |
30 | Usage: SalesForceBackup.exe [-hupasyz]
31 |
32 | Options:
33 | ```
34 | --help Displays this help text
35 | -u Username for Salesforce
36 | -p Password for Salesforce
37 | -t Security Token for Salesforce
38 | -h Salesforce hostname for your org
39 | -a AWS access key
40 | -s AWS secret key
41 | -y Azure account name
42 | -z Azure shared key
43 | ```
44 |
--------------------------------------------------------------------------------
/SalesForceBackup.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 2013
4 | VisualStudioVersion = 12.0.31101.0
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SalesForceBackup", "SalesForceBackup\SalesForceBackup.csproj", "{FCBD6BB9-5512-4052-9E6B-2A5BB7DC9B55}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | CD_ROM|Any CPU = CD_ROM|Any CPU
11 | Debug|Any CPU = Debug|Any CPU
12 | DVD-5|Any CPU = DVD-5|Any CPU
13 | Release|Any CPU = Release|Any CPU
14 | SingleImage|Any CPU = SingleImage|Any CPU
15 | EndGlobalSection
16 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
17 | {FCBD6BB9-5512-4052-9E6B-2A5BB7DC9B55}.CD_ROM|Any CPU.ActiveCfg = Release|Any CPU
18 | {FCBD6BB9-5512-4052-9E6B-2A5BB7DC9B55}.CD_ROM|Any CPU.Build.0 = Release|Any CPU
19 | {FCBD6BB9-5512-4052-9E6B-2A5BB7DC9B55}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
20 | {FCBD6BB9-5512-4052-9E6B-2A5BB7DC9B55}.Debug|Any CPU.Build.0 = Debug|Any CPU
21 | {FCBD6BB9-5512-4052-9E6B-2A5BB7DC9B55}.DVD-5|Any CPU.ActiveCfg = Debug|Any CPU
22 | {FCBD6BB9-5512-4052-9E6B-2A5BB7DC9B55}.DVD-5|Any CPU.Build.0 = Debug|Any CPU
23 | {FCBD6BB9-5512-4052-9E6B-2A5BB7DC9B55}.Release|Any CPU.ActiveCfg = Release|Any CPU
24 | {FCBD6BB9-5512-4052-9E6B-2A5BB7DC9B55}.Release|Any CPU.Build.0 = Release|Any CPU
25 | {FCBD6BB9-5512-4052-9E6B-2A5BB7DC9B55}.SingleImage|Any CPU.ActiveCfg = Release|Any CPU
26 | {FCBD6BB9-5512-4052-9E6B-2A5BB7DC9B55}.SingleImage|Any CPU.Build.0 = Release|Any CPU
27 | EndGlobalSection
28 | GlobalSection(SolutionProperties) = preSolution
29 | HideSolutionNode = FALSE
30 | EndGlobalSection
31 | EndGlobal
32 |
--------------------------------------------------------------------------------
/SalesForceBackup/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
41 |
42 |
43 |
44 |
45 |
46 | https://login.salesforce.com/services/Soap/c/32.0
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
--------------------------------------------------------------------------------
/SalesForceBackup/AppSettingKeys.cs:
--------------------------------------------------------------------------------
1 | namespace SalesForceBackup
2 | {
3 | ///
4 | /// Contains the keys that are defined in the App.Config.
5 | ///
6 | internal class AppSettingKeys
7 | {
8 | public const string AwsAccessKey = "AWSAccessKey";
9 | public const string AwsRegion = "AWSRegion";
10 | public const string AwsSecretKey = "AWSSecretKey";
11 | public const string AzureAccountName = "AzureAccountName";
12 | public const string AzureBlobEndpoint = "AzureBlobEndpoint";
13 | public const string AzureContainer = "AzureContainer";
14 | public const string AzureFolder = "AzureFolder";
15 | public const string AzureSharedKey = "AzureSharedKey";
16 | public const string DataExportPage = "DataExportPage";
17 | public const string DownloadPage = "DownloadPage";
18 | public const string FilenamePattern = "FilenamePattern";
19 | public const string Host = "Host";
20 | public const string Password = "Password";
21 | public const string S3Bucket = "S3Bucket";
22 | public const string S3Folder = "S3Folder";
23 | public const string Scheme = "Scheme";
24 | public const string SecurityToken = "SecurityToken";
25 | public const string Uploader = "Uploader";
26 | public const string Username = "Username";
27 | }
28 |
29 | ///
30 | /// Contains all of the possible uploader values in the App.config.
31 | ///
32 | internal class Uploaders
33 | {
34 | public const string Aws = "AWS";
35 | public const string Azure = "Azure";
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/SalesForceBackup/AppSettings.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Configuration;
4 | using SalesForceBackup.Interfaces;
5 | using TinyIoC;
6 |
7 | namespace SalesForceBackup
8 | {
9 | ///
10 | /// Reads the App.Config application settings.
11 | ///
12 | public class AppSettings : IAppSettings
13 | {
14 | private static IErrorHandler _errorHandler;
15 | private static readonly Dictionary ValuePairs = new Dictionary();
16 |
17 | ///
18 | /// Instantiates a new AppSettings object.
19 | ///
20 | public AppSettings()
21 | {
22 | _errorHandler = TinyIoCContainer.Current.Resolve();
23 | ReadAllSettings();
24 | }
25 |
26 | ///
27 | /// Read the application settings from the App.config.
28 | ///
29 | private static void ReadAllSettings()
30 | {
31 | try
32 | {
33 | var appSettings = ConfigurationManager.AppSettings;
34 |
35 | if (appSettings.Count == 0) return;
36 | foreach (var key in appSettings.AllKeys)
37 | {
38 | ValuePairs.Add(key, appSettings[key]);
39 | }
40 | }
41 | catch (ConfigurationErrorsException e)
42 | {
43 | Console.WriteLine("Error reading app settings");
44 | _errorHandler.HandleError(e, (int)Enums.ExitCode.ConfigurationError);
45 | }
46 | catch (Exception e)
47 | {
48 | _errorHandler.HandleError(e);
49 | }
50 | }
51 |
52 | ///
53 | /// Gets the value of an Application Setting based on the key.
54 | ///
55 | /// The application setting to retrieve.
56 | /// The value of the key, or a null string if it doesn't exist.
57 | public string Get(string key)
58 | {
59 | string value;
60 | ValuePairs.TryGetValue(key, out value);
61 | return value;
62 | }
63 |
64 | ///
65 | /// Sets the value of an Application Setting.
66 | ///
67 | /// The key of the application setting.
68 | /// The new value of the key.
69 | /// The key will be created if it does not already exist.
70 | public void Set(string key, string value)
71 | {
72 | if (ValuePairs.ContainsKey(key))
73 | {
74 | ValuePairs.Remove(key);
75 | }
76 | ValuePairs.Add(key, value);
77 | }
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/SalesForceBackup/AzureBlobUploader.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using Microsoft.WindowsAzure.Storage.Auth;
4 | using Microsoft.WindowsAzure.Storage.Blob;
5 | using SalesForceBackup.Interfaces;
6 | using TinyIoC;
7 |
8 | namespace SalesForceBackup
9 | {
10 | ///
11 | /// Uploads backup files to Azure Blob storage.
12 | ///
13 | public class AzureBlobUploader : IUploader
14 | {
15 |
16 | private readonly IAppSettings _appSettings;
17 | private readonly IErrorHandler _errorHandler;
18 |
19 | public AzureBlobUploader()
20 | {
21 | _appSettings = TinyIoCContainer.Current.Resolve();
22 | _errorHandler = TinyIoCContainer.Current.Resolve();
23 | }
24 |
25 | ///
26 | /// Uploads a file to Azure Blob.
27 | ///
28 | /// The full filename and path of the file to upload.
29 | public void Upload(string file)
30 | {
31 | var blobEndpoint = new Uri(_appSettings.Get(AppSettingKeys.AzureBlobEndpoint));
32 | var accountName = _appSettings.Get(AppSettingKeys.AzureAccountName);
33 | var accountKey = _appSettings.Get(AppSettingKeys.AzureSharedKey);
34 | var containerName = _appSettings.Get(AppSettingKeys.AzureContainer);
35 | var blobName = String.Join("/", new[] {_appSettings.Get(AppSettingKeys.AzureFolder), Path.GetFileName(file)});
36 |
37 | try
38 | {
39 | var blobClient = new CloudBlobClient(blobEndpoint, new StorageCredentials(accountName, accountKey));
40 | var container = blobClient.GetContainerReference(containerName);
41 | container.CreateIfNotExists();
42 | var blob = container.GetBlockBlobReference(blobName);
43 | Console.WriteLine("Uploading {0} to Azure...", Path.GetFileName(file));
44 | blob.UploadFromFile(file, FileMode.OpenOrCreate);
45 | }
46 | catch (Exception e)
47 | {
48 | _errorHandler.HandleError(e, (int)Enums.ExitCode.AzureError, "There was an error uploading the file to Azure.");
49 | }
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/SalesForceBackup/Backup.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Globalization;
4 | using System.IO;
5 | using System.Linq;
6 | using SalesForceBackup.Interfaces;
7 |
8 | namespace SalesForceBackup
9 | {
10 | ///
11 | /// Backs up the data from SalesForce.com
12 | ///
13 | public class Backup
14 | {
15 | #region Instance variables
16 |
17 | private readonly IUploader _uploader;
18 | private readonly IDownloader _downloader;
19 | private readonly IErrorHandler _errorHandler;
20 | private readonly List _filesToDelete = new List();
21 |
22 | #endregion // Instance variables
23 |
24 | ///
25 | /// Instantiates a new Backup object.
26 | ///
27 | public Backup(IUploader uploader, IDownloader downloader, IErrorHandler errorHandler)
28 | {
29 | _uploader = uploader;
30 | _downloader = downloader;
31 | _errorHandler = errorHandler;
32 | }
33 |
34 | ///
35 | /// Begins a backup of the current SalesForce.com data.
36 | ///
37 | public void Run()
38 | {
39 | try
40 | {
41 | var files = _downloader.Download();
42 | _filesToDelete.AddRange(files);
43 |
44 | foreach (var file in files.Select(RenameFile))
45 | {
46 | _filesToDelete.Add(file);
47 | _uploader.Upload(file);
48 | }
49 | }
50 | catch (Exception e)
51 | {
52 | _errorHandler.HandleError(e);
53 | }
54 | finally
55 | {
56 | try
57 | {
58 | foreach (var file in _filesToDelete.Where(File.Exists))
59 | {
60 | File.Delete(file);
61 | }
62 | }
63 | catch (Exception e)
64 | {
65 | _errorHandler.HandleError(e);
66 | }
67 | }
68 | }
69 |
70 | ///
71 | /// Renames a file to match the required backup storage pattern.
72 | ///
73 | /// The file to rename.
74 | /// The full name and filepath of the new file.
75 | /// Uses the following pattern: salesforce/YYYY-MM-DD_HH-MM.*
76 | private string RenameFile(string file)
77 | {
78 | var i = -1;
79 | string newFile;
80 |
81 | do
82 | {
83 | newFile = String.Join(Path.DirectorySeparatorChar.ToString(CultureInfo.InvariantCulture),
84 | new[] { Path.GetDirectoryName(file), FormatFileName(Path.GetExtension(file), ++i) });
85 | } while (File.Exists(newFile));
86 |
87 | File.Move(file, newFile);
88 |
89 | return newFile;
90 | }
91 |
92 | ///
93 | /// Formats the name of the file.
94 | ///
95 | /// The extension to apply to the filename.
96 | /// The revision number to apply to the filename.
97 | /// The formatted filename.
98 | /// If the revision is less than or equal to 0, then no revision indicator will be applied.
99 | private string FormatFileName(string extension, int i)
100 | {
101 | var revision = i <= 0 ? String.Empty : String.Format("-{0}", i);
102 | var dateName = String.Format("{0}{1}{2}", GetDatetimeString(), revision, extension);
103 | return dateName;
104 | }
105 |
106 | ///
107 | /// Gets a specially formatted datetime string based on the current UTC datetime.
108 | ///
109 | /// The datetime string.
110 | private string GetDatetimeString()
111 | {
112 | return String.Format("{0}-{1}-{2}_{3}-{4}",
113 | DateTime.UtcNow.Year.ToString("D4"),
114 | DateTime.UtcNow.Month.ToString("D2"),
115 | DateTime.UtcNow.Day.ToString("D2"),
116 | DateTime.UtcNow.Hour.ToString("D2"),
117 | DateTime.UtcNow.Minute.ToString("D2"));
118 | }
119 |
120 | }
121 | }
122 |
--------------------------------------------------------------------------------
/SalesForceBackup/ConsoleErrorHandler.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using SalesForceBackup.Interfaces;
3 |
4 | namespace SalesForceBackup
5 | {
6 | ///
7 | /// Outputs all errors to the console.
8 | ///
9 | public class ConsoleErrorHandler : IErrorHandler
10 | {
11 | ///
12 | /// Handles error logging for the console application.
13 | ///
14 | /// The exception to handle.
15 | /// This will terminate the application with the specified exit code.
16 | public void HandleError(Exception e)
17 | {
18 | HandleError(e, (int) Enums.ExitCode.Unknown);
19 | }
20 |
21 | ///
22 | /// Handles error logging for the console application.
23 | ///
24 | /// The exception to handle.
25 | /// Optionally, the error code to return to the console. Defaults to -1 (unknown).
26 | /// This will terminate the application with the specified exit code.
27 | public void HandleError(Exception e, int exitCode)
28 | {
29 | HandleError(e, exitCode, "Unknown error occured:");
30 | }
31 |
32 | ///
33 | /// Handles error logging for the console application.
34 | ///
35 | /// The exception to handle.
36 | /// Optionally, the error code to return to the console. Defaults to -1 (unknown).
37 | /// Optionally, a descriptive error message to return to the console.
38 | /// This will terminate the application with the specified exit code.
39 | public void HandleError(Exception e, int exitCode, string errorMessage)
40 | {
41 | Console.WriteLine(errorMessage);
42 | Console.WriteLine(e.ToString());
43 | Environment.Exit(exitCode);
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/SalesForceBackup/DataExportFile.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace SalesForceBackup
8 | {
9 | class DataExportFile
10 | {
11 | public DataExportFile(string FileName, string Url)
12 | {
13 | this.FileName = FileName;
14 | this.Url = Url;
15 | }
16 |
17 | public string FileName { get; private set; }
18 | public string Url { get; private set; }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/SalesForceBackup/Enums.cs:
--------------------------------------------------------------------------------
1 | namespace SalesForceBackup
2 | {
3 | ///
4 | /// Contains any enumerations for the application.
5 | ///
6 | public class Enums
7 | {
8 | ///
9 | /// List of possible error codes for the application.
10 | ///
11 | public enum ExitCode
12 | {
13 | Normal = 0,
14 | Unknown = -1,
15 | ConfigurationError = 10,
16 | AwsCredentials = 20,
17 | AwsS3Error =21,
18 | AzureError = 30
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/SalesForceBackup/Interfaces/IAppSettings.cs:
--------------------------------------------------------------------------------
1 | namespace SalesForceBackup.Interfaces
2 | {
3 | public interface IAppSettings
4 | {
5 | string Get(string key);
6 | void Set(string key, string value);
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/SalesForceBackup/Interfaces/IDownloader.cs:
--------------------------------------------------------------------------------
1 | namespace SalesForceBackup.Interfaces
2 | {
3 | public interface IDownloader
4 | {
5 | string[] Download();
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/SalesForceBackup/Interfaces/IErrorHandler.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace SalesForceBackup.Interfaces
4 | {
5 | ///
6 | /// Interface to handle application exceptions.
7 | ///
8 | public interface IErrorHandler
9 | {
10 | void HandleError(Exception e);
11 | void HandleError(Exception e, int exitCode);
12 | void HandleError(Exception e, int exitCode, string errorMessage);
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/SalesForceBackup/Interfaces/IUploader.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace SalesForceBackup.Interfaces
4 | {
5 | ///
6 | /// Interface for uploaders to the backup storage.
7 | ///
8 | public interface IUploader
9 | {
10 | ///
11 | /// Uploads the specified file.
12 | ///
13 | /// The full name and path of the file to upload.
14 | void Upload(String file);
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/SalesForceBackup/IoC/Bootstrap.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Configuration;
3 | using SalesForceBackup.Interfaces;
4 | using TinyIoC;
5 |
6 | namespace SalesForceBackup.IoC
7 | {
8 | public static class Bootstrap
9 | {
10 | public static void Register()
11 | {
12 | TinyIoCContainer.Current.Register(new ConsoleErrorHandler());
13 | TinyIoCContainer.Current.Register(new AppSettings());
14 | TinyIoCContainer.Current.Register(String.Equals(ConfigurationManager.AppSettings[AppSettingKeys.Uploader], Uploaders.Aws,
15 | StringComparison.CurrentCultureIgnoreCase)
16 | ? (IUploader) new S3Uploader()
17 | : new AzureBlobUploader());
18 | TinyIoCContainer.Current.Register(new SalesForceWebDownloader());
19 |
20 | TinyIoCContainer.Current.Register();
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/SalesForceBackup/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Text;
6 | using SalesForceBackup.Interfaces;
7 | using SalesForceBackup.IoC;
8 | using TinyIoC;
9 |
10 | namespace SalesForceBackup
11 | {
12 | ///
13 | /// The main application.
14 | ///
15 | class Program
16 | {
17 |
18 | private static IAppSettings _appSettings;
19 |
20 | ///
21 | /// Initial application method.
22 | ///
23 | /// Array of command line arguments to the application.
24 | static void Main(string[] args)
25 | {
26 | // Register our IoC containers
27 | Bootstrap.Register();
28 |
29 | Console.WriteLine("Reading Settings...");
30 | _appSettings = TinyIoCContainer.Current.Resolve();
31 | AssignValuesFromArguments(args);
32 |
33 |
34 | Console.WriteLine("Starting backup...");
35 | var backup = TinyIoCContainer.Current.Resolve();
36 | backup.Run();
37 |
38 | Environment.Exit((int)Enums.ExitCode.Normal);
39 | }
40 |
41 | #region Private Methods
42 |
43 | ///
44 | /// Processes the command line arguments and assigns them as necessary.
45 | ///
46 | /// The list of arguments passed in from the command line.
47 | private static void AssignValuesFromArguments(IList args)
48 | {
49 | for (var i = 0; i < args.Count(); i++)
50 | {
51 | switch (args[i])
52 | {
53 | case "--help":
54 | DisplayHelp();
55 | Environment.Exit((int)Enums.ExitCode.Normal);
56 | break;
57 | case "-u":
58 | _appSettings.Set(AppSettingKeys.Username, args[++i]);
59 | break;
60 | case "-p":
61 | _appSettings.Set(AppSettingKeys.Password, args[++i]);
62 | break;
63 | case "-t":
64 | _appSettings.Set(AppSettingKeys.SecurityToken, args[++i]);
65 | break;
66 | case "-h":
67 | _appSettings.Set(AppSettingKeys.Host, args[++i]);
68 | break;
69 | case "-a":
70 | _appSettings.Set(AppSettingKeys.AwsAccessKey, args[++i]);
71 | break;
72 | case "-y":
73 | _appSettings.Set(AppSettingKeys.AzureAccountName, args[++i]);
74 | break;
75 | case "-z":
76 | _appSettings.Set(AppSettingKeys.AzureSharedKey, args[++i]);
77 | break;
78 | case "-s":
79 | _appSettings.Set(AppSettingKeys.AwsSecretKey, args[++i]);
80 | break;
81 | }
82 | }
83 | }
84 |
85 | ///
86 | /// Outputs the contents of the help to the console.
87 | ///
88 | private static void DisplayHelp()
89 | {
90 | var file = AppDomain.CurrentDomain.FriendlyName;
91 | var name = System.Reflection.Assembly.GetExecutingAssembly().GetName().Name;
92 | var version = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
93 | var sb = new StringBuilder(1024);
94 | using (var sr = new StringWriter(sb))
95 | {
96 | sr.WriteLine("{0} version {1}", name, version);
97 | sr.WriteLine("");
98 | sr.WriteLine("Usage: {0} [-hupasyz]", file);
99 | sr.WriteLine("");
100 | sr.WriteLine("Options:");
101 | sr.WriteLine("\t-h or --help\tDisplays this help text");
102 | sr.WriteLine("\t-u \t\tUsername for SalesForce");
103 | sr.WriteLine("\t-p \t\tPassword for SalesForce");
104 | sr.WriteLine("\t-a \t\tAWS access key");
105 | sr.WriteLine("\t-s \t\tAWS secret key");
106 | sr.WriteLine("\t-y \t\tAzure account name");
107 | sr.WriteLine("\t-z \t\tAzure shared key");
108 | }
109 | Console.Write(sb.ToString());
110 | }
111 |
112 | #endregion // Private Methods
113 |
114 | }
115 | }
116 |
--------------------------------------------------------------------------------
/SalesForceBackup/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.InteropServices;
3 |
4 | // General Information about an assembly is controlled through the following
5 | // set of attributes. Change these attribute values to modify the information
6 | // associated with an assembly.
7 | [assembly: AssemblyTitle("SalesForceBackup")]
8 | [assembly: AssemblyDescription("Performs automated backups of SalesForce.com data.")]
9 | [assembly: AssemblyConfiguration("")]
10 | [assembly: AssemblyCompany("")]
11 | [assembly: AssemblyProduct("SalesForceBackup")]
12 | [assembly: AssemblyCopyright("Copyright © 2015")]
13 | [assembly: AssemblyTrademark("")]
14 | [assembly: AssemblyCulture("")]
15 |
16 | // Setting ComVisible to false makes the types in this assembly not visible
17 | // to COM components. If you need to access a type in this assembly from
18 | // COM, set the ComVisible attribute to true on that type.
19 | [assembly: ComVisible(false)]
20 |
21 | // The following GUID is for the ID of the typelib if this project is exposed to COM
22 | [assembly: Guid("ba81ba12-d408-4542-a3c9-ade39131901f")]
23 |
24 | // Version information for an assembly consists of the following four values:
25 | //
26 | // Major Version
27 | // Minor Version
28 | // Build Number
29 | // Revision
30 | //
31 | // You can specify all the values or you can default the Build and Revision Numbers
32 | // by using the '*' as shown below:
33 | // [assembly: AssemblyVersion("1.0.*")]
34 | [assembly: AssemblyVersion("1.0.0.0")]
35 | [assembly: AssemblyFileVersion("1.0.0.0")]
36 |
--------------------------------------------------------------------------------
/SalesForceBackup/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.34014
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace SalesForceBackup.Properties {
12 |
13 |
14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "12.0.0.0")]
16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
17 |
18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
19 |
20 | public static Settings Default {
21 | get {
22 | return defaultInstance;
23 | }
24 | }
25 |
26 | [global::System.Configuration.ApplicationScopedSettingAttribute()]
27 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
28 | [global::System.Configuration.SpecialSettingAttribute(global::System.Configuration.SpecialSetting.WebServiceUrl)]
29 | [global::System.Configuration.DefaultSettingValueAttribute("https://login.salesforce.com/services/Soap/c/32.0/0DFo000000004N4")]
30 | public string SalesForceBackup_SFDC_SforceService {
31 | get {
32 | return ((string)(this["SalesForceBackup_SFDC_SforceService"]));
33 | }
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/SalesForceBackup/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | https://login.salesforce.com/services/Soap/c/32.0/0DFo000000004N4
7 |
8 |
9 |
--------------------------------------------------------------------------------
/SalesForceBackup/S3Uploader.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using Amazon;
4 | using Amazon.Runtime;
5 | using Amazon.S3;
6 | using Amazon.S3.Model;
7 | using SalesForceBackup.Interfaces;
8 | using TinyIoC;
9 |
10 | namespace SalesForceBackup
11 | {
12 | ///
13 | /// Uploads files to AWS S3.
14 | ///
15 | public class S3Uploader : IUploader
16 | {
17 | private readonly IAppSettings _appSettings;
18 | private readonly IErrorHandler _errorHandler;
19 |
20 | ///
21 | /// Initializes a new S3Uploader.
22 | ///
23 | public S3Uploader()
24 | {
25 | _appSettings = TinyIoCContainer.Current.Resolve();
26 | _errorHandler = TinyIoCContainer.Current.Resolve();
27 | }
28 |
29 | ///
30 | /// Uploads a file to S3.
31 | ///
32 | /// The full filename and path of the file to upload.
33 | public void Upload(string file)
34 | {
35 | var filename = Path.GetFileName(file);
36 | try
37 | {
38 | var credentials = new BasicAWSCredentials(_appSettings.Get(AppSettingKeys.AwsAccessKey), _appSettings.Get(AppSettingKeys.AwsSecretKey));
39 | var region = RegionEndpoint.GetBySystemName(_appSettings.Get(AppSettingKeys.AwsRegion));
40 | using (var client = new AmazonS3Client(credentials, region))
41 | {
42 | var request = new PutObjectRequest
43 | {
44 | BucketName = _appSettings.Get(AppSettingKeys.S3Bucket),
45 | Key = String.Join("/", new[] { _appSettings.Get(AppSettingKeys.S3Folder), filename }),
46 | FilePath = file
47 | };
48 | Console.WriteLine("Uploading {0} to AWS S3...", filename);
49 | client.PutObject(request);
50 | }
51 | }
52 | catch (AmazonS3Exception e)
53 | {
54 | if (e.ErrorCode != null && (e.ErrorCode.Equals("InvalidAccessKeyId") || e.ErrorCode.Equals("InvalidSecurity")))
55 | {
56 | _errorHandler.HandleError(e, (int)Enums.ExitCode.AwsCredentials, "Check the provided AWS Credentials");
57 | }
58 | else
59 | {
60 | _errorHandler.HandleError(e, (int)Enums.ExitCode.AwsS3Error, String.Format("Error occurred. Message:'{0}' when writing an object", e.Message));
61 | }
62 | }
63 | }
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/SalesForceBackup/SalesForceBackup.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {FCBD6BB9-5512-4052-9E6B-2A5BB7DC9B55}
8 | Exe
9 | Properties
10 | SalesForceBackup
11 | SalesForceBackup
12 | v4.5
13 | 512
14 |
15 |
16 | AnyCPU
17 | true
18 | full
19 | false
20 | bin\Debug\
21 | DEBUG;TRACE
22 | prompt
23 | 4
24 |
25 |
26 | AnyCPU
27 | pdbonly
28 | true
29 | bin\Release\
30 | TRACE
31 | prompt
32 | 4
33 |
34 |
35 |
36 | ..\packages\AWSSDK.2.3.15.0\lib\net45\AWSSDK.dll
37 |
38 |
39 | False
40 | ..\packages\Microsoft.Data.Edm.5.6.2\lib\net40\Microsoft.Data.Edm.dll
41 |
42 |
43 | False
44 | ..\packages\Microsoft.Data.OData.5.6.2\lib\net40\Microsoft.Data.OData.dll
45 |
46 |
47 | False
48 | ..\packages\Microsoft.Data.Services.Client.5.6.2\lib\net40\Microsoft.Data.Services.Client.dll
49 |
50 |
51 | False
52 | ..\packages\Microsoft.WindowsAzure.ConfigurationManager.1.8.0.0\lib\net35-full\Microsoft.WindowsAzure.Configuration.dll
53 |
54 |
55 | False
56 | ..\packages\WindowsAzure.Storage.4.3.0\lib\net40\Microsoft.WindowsAzure.Storage.dll
57 |
58 |
59 | ..\packages\Newtonsoft.Json.5.0.8\lib\net45\Newtonsoft.Json.dll
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 | False
72 | ..\packages\System.Spatial.5.6.2\lib\net40\System.Spatial.dll
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 | True
100 | True
101 | Settings.settings
102 |
103 |
104 |
105 |
106 |
107 | True
108 | True
109 | Reference.map
110 |
111 |
112 |
113 |
114 | Designer
115 |
116 |
117 |
118 | SettingsSingleFileGenerator
119 | Settings.Designer.cs
120 |
121 |
122 |
123 | Reference.map
124 |
125 |
126 | Reference.map
127 |
128 |
129 | Reference.map
130 |
131 |
132 | Reference.map
133 |
134 |
135 | Reference.map
136 |
137 |
138 | Reference.map
139 |
140 |
141 | Reference.map
142 |
143 |
144 | Reference.map
145 |
146 |
147 | Reference.map
148 |
149 |
150 | Reference.map
151 |
152 |
153 | Reference.map
154 |
155 |
156 | Reference.map
157 |
158 |
159 | Reference.map
160 |
161 |
162 | Reference.map
163 |
164 |
165 | Reference.map
166 |
167 |
168 | Reference.map
169 |
170 |
171 | Reference.map
172 |
173 |
174 | Reference.map
175 |
176 |
177 | Reference.map
178 |
179 |
180 | Reference.map
181 |
182 |
183 | Reference.map
184 |
185 |
186 | Reference.map
187 |
188 |
189 | Reference.map
190 |
191 |
192 | Reference.map
193 |
194 |
195 | Reference.map
196 |
197 |
198 | Reference.map
199 |
200 |
201 | Reference.map
202 |
203 |
204 | Reference.map
205 |
206 |
207 | Reference.map
208 |
209 |
210 | Reference.map
211 |
212 |
213 | Reference.map
214 |
215 |
216 | Reference.map
217 |
218 |
219 | Reference.map
220 |
221 |
222 | Reference.map
223 |
224 |
225 | Reference.map
226 |
227 |
228 | Reference.map
229 |
230 |
231 | MSDiscoCodeGenerator
232 | Reference.cs
233 |
234 |
235 | Reference.map
236 |
237 |
238 |
239 | Reference.map
240 |
241 |
242 | Reference.map
243 |
244 |
245 | Reference.map
246 |
247 |
248 | Reference.map
249 |
250 |
251 | Reference.map
252 |
253 |
254 | Reference.map
255 |
256 |
257 | Reference.map
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 | Dynamic
269 | Web References\SFDC\
270 | .\SalesForceBackup\SalesForce.wsdl
271 |
272 |
273 |
274 |
275 | Settings
276 | SalesForceBackup_SFDC_SforceService
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
291 |
--------------------------------------------------------------------------------
/SalesForceBackup/SalesForceWebDownloader.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Globalization;
4 | using System.IO;
5 | using System.Net;
6 | using System.Net.Http;
7 | using System.Text.RegularExpressions;
8 | using SalesForceBackup.Interfaces;
9 | using SalesForceBackup.SFDC;
10 | using TinyIoC;
11 |
12 | namespace SalesForceBackup
13 | {
14 | ///
15 | /// Downloads backup files from the Salesforce website by scraping the web page.
16 | ///
17 | public class SalesForceWebDownloader : IDownloader
18 | {
19 | private readonly IAppSettings _appSettings;
20 | private readonly IErrorHandler _errorHandler;
21 |
22 | ///
23 | /// Initializes a new SalesForceWebDownloader.
24 | ///
25 | public SalesForceWebDownloader()
26 | {
27 | _appSettings = TinyIoCContainer.Current.Resolve();
28 | _errorHandler = TinyIoCContainer.Current.Resolve();
29 |
30 | ServicePointManager.Expect100Continue = true;
31 | ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
32 | }
33 |
34 | ///
35 | /// Downloads the backups from the SalesForce.com website.
36 | ///
37 | /// An array of the paths to the files that were downloaded.
38 | public string[] Download()
39 | {
40 | var files = new List();
41 | var baseAddress = new Uri(String.Format("{0}://{1}", _appSettings.Get(AppSettingKeys.Scheme), _appSettings.Get(AppSettingKeys.Host)));
42 |
43 | try
44 | {
45 | Console.Write("Connecting to SalesForce.com ... ");
46 | var sessionId = LogIn();
47 | Console.WriteLine("\u221A");
48 |
49 | Console.Write("Getting list of export files ... ");
50 | var exportFiles = DownloadListOfExportFiles(sessionId);
51 | Console.WriteLine("\u221A");
52 |
53 | for (int i=0; i DownloadListOfExportFiles(string sessionId)
86 | {
87 | List result = new List();
88 |
89 | var page = DownloadWebpage(_appSettings.Get(AppSettingKeys.DataExportPage), sessionId);
90 | var regex = new Regex(_appSettings.Get(AppSettingKeys.FilenamePattern), RegexOptions.IgnoreCase);
91 | var matches = regex.Matches(page.Content.ReadAsStringAsync().Result);
92 | foreach (Match match in matches)
93 | {
94 | var fileName = match.Groups[1].ToString().Split(new[] { '&' })[0];
95 | var url = String.Format("{0}{1}", _appSettings.Get(AppSettingKeys.DownloadPage), match.ToString().Replace("&", "&"));
96 | result.Add(new DataExportFile(fileName, url.Substring(0, url.Length - 1)));
97 | }
98 | return result;
99 | }
100 |
101 | ///
102 | /// Retrieves a page from Salesforce.
103 | ///
104 | /// The relative URL for the Salesforce page.
105 | /// The current session ID.
106 | /// An HttpResponseMessage for the url.
107 | private HttpResponseMessage DownloadWebpage(string url, string sessionId)
108 | {
109 | var baseAddress = new Uri(String.Format("{0}://{1}", _appSettings.Get(AppSettingKeys.Scheme), _appSettings.Get(AppSettingKeys.Host)));
110 | using (var handler = new HttpClientHandler { UseCookies = false })
111 | using (var client = new HttpClient(handler) { BaseAddress = baseAddress })
112 | {
113 | var message = new HttpRequestMessage(HttpMethod.Get, url);
114 | message.Headers.Add("Cookie", String.Format("sid={0}", sessionId));
115 | return client.SendAsync(message, HttpCompletionOption.ResponseHeadersRead).Result;
116 | }
117 | }
118 |
119 | ///
120 | /// Asynchronously downloads a data export file from Salesforce.
121 | ///
122 | /// file to be downloaded
123 | /// base address of the Salesforce server
124 | /// current session ID.
125 | /// a Task that can be used to monitor the progress
126 | private static async System.Threading.Tasks.Task DownloadExportFile(DataExportFile dataExportFile, Uri baseAddress, string sessionId)
127 | {
128 | using (var handler = new HttpClientHandler { UseCookies = false })
129 | using (var client = new HttpClient(handler) { BaseAddress = baseAddress })
130 | {
131 | var message = new HttpRequestMessage(HttpMethod.Get, dataExportFile.Url);
132 | message.Headers.Add("Cookie", String.Format("sid={0}", sessionId));
133 |
134 | using (HttpResponseMessage response = await client.SendAsync(message, HttpCompletionOption.ResponseHeadersRead))
135 | using (Stream streamToReadFrom = await response.Content.ReadAsStreamAsync())
136 | {
137 | using (Stream fileStream = File.Open(dataExportFile.FileName, FileMode.Create))
138 | {
139 | await streamToReadFrom.CopyToAsync(fileStream);
140 | }
141 | }
142 | }
143 | }
144 |
145 | }
146 | }
147 |
--------------------------------------------------------------------------------
/SalesForceBackup/Web References/SFDC/DeleteResult.datasource:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 | SalesForceBackup.SFDC.DeleteResult, Web References.SFDC.Reference.cs, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
10 |
--------------------------------------------------------------------------------
/SalesForceBackup/Web References/SFDC/DescribeAppMenuItem.datasource:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 | SalesForceBackup.SFDC.DescribeAppMenuItem, Web References.SFDC.Reference.cs, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
10 |
--------------------------------------------------------------------------------
/SalesForceBackup/Web References/SFDC/DescribeApprovalLayout.datasource:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 | SalesForceBackup.SFDC.DescribeApprovalLayout, Web References.SFDC.Reference.cs, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
10 |
--------------------------------------------------------------------------------
/SalesForceBackup/Web References/SFDC/DescribeAvailableQuickActionResult.datasource:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 | SalesForceBackup.SFDC.DescribeAvailableQuickActionResult, Web References.SFDC.Reference.cs, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
10 |
--------------------------------------------------------------------------------
/SalesForceBackup/Web References/SFDC/DescribeCompactLayout.datasource:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 | SalesForceBackup.SFDC.DescribeCompactLayout, Web References.SFDC.Reference.cs, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
10 |
--------------------------------------------------------------------------------
/SalesForceBackup/Web References/SFDC/DescribeCompactLayoutsResult.datasource:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 | SalesForceBackup.SFDC.DescribeCompactLayoutsResult, Web References.SFDC.Reference.cs, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
10 |
--------------------------------------------------------------------------------
/SalesForceBackup/Web References/SFDC/DescribeDataCategoryGroupResult.datasource:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 | SalesForceBackup.SFDC.DescribeDataCategoryGroupResult, Web References.SFDC.Reference.cs, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
10 |
--------------------------------------------------------------------------------
/SalesForceBackup/Web References/SFDC/DescribeDataCategoryGroupStructureResult.datasource:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 | SalesForceBackup.SFDC.DescribeDataCategoryGroupStructureResult, Web References.SFDC.Reference.cs, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
10 |
--------------------------------------------------------------------------------
/SalesForceBackup/Web References/SFDC/DescribeFlexiPageResult.datasource:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 | SalesForceBackup.SFDC.DescribeFlexiPageResult, Web References.SFDC.Reference.cs, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
10 |
--------------------------------------------------------------------------------
/SalesForceBackup/Web References/SFDC/DescribeGlobalResult.datasource:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 | SalesForceBackup.SFDC.DescribeGlobalResult, Web References.SFDC.Reference.cs, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
10 |
--------------------------------------------------------------------------------
/SalesForceBackup/Web References/SFDC/DescribeGlobalTheme.datasource:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 | SalesForceBackup.SFDC.DescribeGlobalTheme, Web References.SFDC.Reference.cs, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
10 |
--------------------------------------------------------------------------------
/SalesForceBackup/Web References/SFDC/DescribeLayoutResult.datasource:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 | SalesForceBackup.SFDC.DescribeLayoutResult, Web References.SFDC.Reference.cs, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
10 |
--------------------------------------------------------------------------------
/SalesForceBackup/Web References/SFDC/DescribeQuickActionResult.datasource:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 | SalesForceBackup.SFDC.DescribeQuickActionResult, Web References.SFDC.Reference.cs, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
10 |
--------------------------------------------------------------------------------
/SalesForceBackup/Web References/SFDC/DescribeSObjectResult.datasource:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 | SalesForceBackup.SFDC.DescribeSObjectResult, Web References.SFDC.Reference.cs, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
10 |
--------------------------------------------------------------------------------
/SalesForceBackup/Web References/SFDC/DescribeSearchLayoutResult.datasource:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 | SalesForceBackup.SFDC.DescribeSearchLayoutResult, Web References.SFDC.Reference.cs, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
10 |
--------------------------------------------------------------------------------
/SalesForceBackup/Web References/SFDC/DescribeSearchScopeOrderResult.datasource:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 | SalesForceBackup.SFDC.DescribeSearchScopeOrderResult, Web References.SFDC.Reference.cs, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
10 |
--------------------------------------------------------------------------------
/SalesForceBackup/Web References/SFDC/DescribeSoftphoneLayoutResult.datasource:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 | SalesForceBackup.SFDC.DescribeSoftphoneLayoutResult, Web References.SFDC.Reference.cs, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
10 |
--------------------------------------------------------------------------------
/SalesForceBackup/Web References/SFDC/DescribeSoqlListView.datasource:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 | SalesForceBackup.SFDC.DescribeSoqlListView, Web References.SFDC.Reference.cs, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
10 |
--------------------------------------------------------------------------------
/SalesForceBackup/Web References/SFDC/DescribeTab.datasource:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 | SalesForceBackup.SFDC.DescribeTab, Web References.SFDC.Reference.cs, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
10 |
--------------------------------------------------------------------------------
/SalesForceBackup/Web References/SFDC/DescribeTabSetResult.datasource:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 | SalesForceBackup.SFDC.DescribeTabSetResult, Web References.SFDC.Reference.cs, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
10 |
--------------------------------------------------------------------------------
/SalesForceBackup/Web References/SFDC/DescribeThemeItem.datasource:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 | SalesForceBackup.SFDC.DescribeThemeItem, Web References.SFDC.Reference.cs, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
10 |
--------------------------------------------------------------------------------
/SalesForceBackup/Web References/SFDC/EmptyRecycleBinResult.datasource:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 | SalesForceBackup.SFDC.EmptyRecycleBinResult, Web References.SFDC.Reference.cs, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
10 |
--------------------------------------------------------------------------------
/SalesForceBackup/Web References/SFDC/ExecuteListViewResult.datasource:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 | SalesForceBackup.SFDC.ExecuteListViewResult, Web References.SFDC.Reference.cs, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
10 |
--------------------------------------------------------------------------------
/SalesForceBackup/Web References/SFDC/GetDeletedResult.datasource:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 | SalesForceBackup.SFDC.GetDeletedResult, Web References.SFDC.Reference.cs, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
10 |
--------------------------------------------------------------------------------
/SalesForceBackup/Web References/SFDC/GetServerTimestampResult.datasource:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 | SalesForceBackup.SFDC.GetServerTimestampResult, Web References.SFDC.Reference.cs, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
10 |
--------------------------------------------------------------------------------
/SalesForceBackup/Web References/SFDC/GetUpdatedResult.datasource:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 | SalesForceBackup.SFDC.GetUpdatedResult, Web References.SFDC.Reference.cs, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
10 |
--------------------------------------------------------------------------------
/SalesForceBackup/Web References/SFDC/GetUserInfoResult.datasource:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 | SalesForceBackup.SFDC.GetUserInfoResult, Web References.SFDC.Reference.cs, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
10 |
--------------------------------------------------------------------------------
/SalesForceBackup/Web References/SFDC/InvalidateSessionsResult.datasource:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 | SalesForceBackup.SFDC.InvalidateSessionsResult, Web References.SFDC.Reference.cs, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
10 |
--------------------------------------------------------------------------------
/SalesForceBackup/Web References/SFDC/KnowledgeSettings.datasource:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 | SalesForceBackup.SFDC.KnowledgeSettings, Web References.SFDC.Reference.cs, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
10 |
--------------------------------------------------------------------------------
/SalesForceBackup/Web References/SFDC/LeadConvertResult.datasource:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 | SalesForceBackup.SFDC.LeadConvertResult, Web References.SFDC.Reference.cs, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
10 |
--------------------------------------------------------------------------------
/SalesForceBackup/Web References/SFDC/LoginResult.datasource:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 | SalesForceBackup.SFDC.LoginResult, Web References.SFDC.Reference.cs, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
10 |
--------------------------------------------------------------------------------
/SalesForceBackup/Web References/SFDC/MergeResult.datasource:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 | SalesForceBackup.SFDC.MergeResult, Web References.SFDC.Reference.cs, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
10 |
--------------------------------------------------------------------------------
/SalesForceBackup/Web References/SFDC/PerformQuickActionResult.datasource:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 | SalesForceBackup.SFDC.PerformQuickActionResult, Web References.SFDC.Reference.cs, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
10 |
--------------------------------------------------------------------------------
/SalesForceBackup/Web References/SFDC/ProcessResult.datasource:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 | SalesForceBackup.SFDC.ProcessResult, Web References.SFDC.Reference.cs, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
10 |
--------------------------------------------------------------------------------
/SalesForceBackup/Web References/SFDC/QueryResult.datasource:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 | SalesForceBackup.SFDC.QueryResult, Web References.SFDC.Reference.cs, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
10 |
--------------------------------------------------------------------------------
/SalesForceBackup/Web References/SFDC/QuickActionTemplateResult.datasource:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 | SalesForceBackup.SFDC.QuickActionTemplateResult, Web References.SFDC.Reference.cs, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
10 |
--------------------------------------------------------------------------------
/SalesForceBackup/Web References/SFDC/Reference.map:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/SalesForceBackup/Web References/SFDC/ResetPasswordResult.datasource:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 | SalesForceBackup.SFDC.ResetPasswordResult, Web References.SFDC.Reference.cs, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
10 |
--------------------------------------------------------------------------------
/SalesForceBackup/Web References/SFDC/SaveResult.datasource:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 | SalesForceBackup.SFDC.SaveResult, Web References.SFDC.Reference.cs, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
10 |
--------------------------------------------------------------------------------
/SalesForceBackup/Web References/SFDC/SearchResult.datasource:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 | SalesForceBackup.SFDC.SearchResult, Web References.SFDC.Reference.cs, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
10 |
--------------------------------------------------------------------------------
/SalesForceBackup/Web References/SFDC/SendEmailResult.datasource:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 | SalesForceBackup.SFDC.SendEmailResult, Web References.SFDC.Reference.cs, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
10 |
--------------------------------------------------------------------------------
/SalesForceBackup/Web References/SFDC/SetPasswordResult.datasource:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 | SalesForceBackup.SFDC.SetPasswordResult, Web References.SFDC.Reference.cs, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
10 |
--------------------------------------------------------------------------------
/SalesForceBackup/Web References/SFDC/UndeleteResult.datasource:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 | SalesForceBackup.SFDC.UndeleteResult, Web References.SFDC.Reference.cs, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
10 |
--------------------------------------------------------------------------------
/SalesForceBackup/Web References/SFDC/UpsertResult.datasource:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 | SalesForceBackup.SFDC.UpsertResult, Web References.SFDC.Reference.cs, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
10 |
--------------------------------------------------------------------------------
/SalesForceBackup/Web References/SFDC/sObject.datasource:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 | SalesForceBackup.SFDC.sObject, Web References.SFDC.Reference.cs, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
10 |
--------------------------------------------------------------------------------
/SalesForceBackup/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/azure-pipelines.yml:
--------------------------------------------------------------------------------
1 | # .NET Desktop
2 | # Build and run tests for .NET Desktop or Windows classic desktop solutions.
3 | # Add steps that publish symbols, save build artifacts, and more:
4 | # https://docs.microsoft.com/azure/devops/pipelines/apps/windows/dot-net
5 |
6 | trigger:
7 | - master
8 |
9 | pool:
10 | vmImage: 'windows-latest'
11 |
12 | variables:
13 | solution: '**/*.sln'
14 | buildPlatform: 'Any CPU'
15 | buildConfiguration: 'Release'
16 |
17 | steps:
18 | - task: NuGetToolInstaller@1
19 |
20 | - task: NuGetCommand@2
21 | inputs:
22 | restoreSolution: '$(solution)'
23 |
24 | - task: VSBuild@1
25 | inputs:
26 | solution: '$(solution)'
27 | platform: '$(buildPlatform)'
28 | configuration: '$(buildConfiguration)'
29 |
30 | - task: VSTest@2
31 | inputs:
32 | platform: '$(buildPlatform)'
33 | configuration: '$(buildConfiguration)'
34 |
--------------------------------------------------------------------------------