backup and restore

alphons <alphons@heijden.com> 19 May 2025, 09:31
bfb380d343b95496b5e27f3e2ac10191bff7ff97
3 files changed
  • BackupMongoDb/BackupMongoDb.csproj
  • BackupMongoDb/Helper.cs
  • BackupMongoDb/Program.cs
diff --git a/BackupMongoDb/BackupMongoDb.csproj b/BackupMongoDb/BackupMongoDb.csproj
index f106e5b..8c3cd26 100644
--- a/BackupMongoDb/BackupMongoDb.csproj
+++ b/BackupMongoDb/BackupMongoDb.csproj
@@ -1,15 +1,29 @@
<Project Sdk="Microsoft.NET.Sdk">
- <PropertyGroup>
- <OutputType>Exe</OutputType>
- <TargetFramework>net8.0</TargetFramework>
- <ImplicitUsings>enable</ImplicitUsings>
- <Nullable>enable</Nullable>
- </PropertyGroup>
-
- <ItemGroup>
- <PackageReference Include="AlphaVSS" Version="2.0.3" />
- <PackageReference Include="MongoDB.Driver" Version="3.4.0" />
- </ItemGroup>
+ <PropertyGroup>
+ <OutputType>Exe</OutputType>
+ <TargetFramework>net8.0</TargetFramework>
+ <ImplicitUsings>enable</ImplicitUsings>
+ <Nullable>enable</Nullable>
+ <RuntimeIdentifier>win-x64</RuntimeIdentifier>
+ <PlatformTarget>x64</PlatformTarget>
+ <PublishSingleFile>true</PublishSingleFile>
+ <IncludeNativeLibrariesForSelfExtract>false</IncludeNativeLibrariesForSelfExtract>
+ <IncludeAllContentForSelfExtract>false</IncludeAllContentForSelfExtract>
+ </PropertyGroup>
+
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
+ <NoWarn>1701;1702;CA1416</NoWarn>
+ </PropertyGroup>
+
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
+ <NoWarn>1701;1702;CA1416</NoWarn>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <PackageReference Include="AlphaVSS" Version="2.0.3" />
+ <PackageReference Include="MongoDB.Driver" Version="3.4.0" />
+ <PackageReference Include="System.ServiceProcess.ServiceController" Version="8.0.1" />
+ </ItemGroup>
</Project>
diff --git a/BackupMongoDb/Helper.cs b/BackupMongoDb/Helper.cs
index 128ff29..32da36a 100644
--- a/BackupMongoDb/Helper.cs
+++ b/BackupMongoDb/Helper.cs
@@ -3,7 +3,9 @@ using MongoDB.Bson;
using MongoDB.Driver;
using System.Diagnostics;
using System.IO.Compression;
+using System.Security.AccessControl;
using System.Security.Principal;
+using System.ServiceProcess;
namespace BackupMongoDb;
@@ -14,11 +16,9 @@ public class Helper
{
try
{
-#pragma warning disable CA1416 // Validate platform compatibility
using var identity = WindowsIdentity.GetCurrent();
var principal = new WindowsPrincipal(identity);
return principal.IsInRole(WindowsBuiltInRole.Administrator);
-#pragma warning restore CA1416 // Validate platform compatibility
}
catch (Exception ex)
{
@@ -144,7 +144,7 @@ public class Helper
}
}
- public static async Task<bool> BackupAsync(string backupDir, string connectionString = "mongodb://localhost:27017")
+ public static async Task<bool> BackupAsync(string backupDir, string connectionString)
{
MongoClient? client;
IMongoDatabase? database = null;
@@ -239,4 +239,145 @@ public class Helper
}
}
}
+
+ public static async Task<bool> RestoreAsync(string zipFilePath, string connectionString)
+ {
+ MongoClient? client = null;
+ var sw = Stopwatch.StartNew();
+
+ try
+ {
+ // Controleer of de applicatie als administrator draait
+ if (!IsRunningAsAdministrator())
+ {
+ Console.WriteLine("This application must be run as an administrator to perform a MongoDB restore.");
+ return false;
+ }
+
+ // Valideer ZIP-bestand
+ if (string.IsNullOrWhiteSpace(zipFilePath) || !File.Exists(zipFilePath))
+ {
+ Console.WriteLine($"ZIP file '{zipFilePath}' is invalid or does not exist.");
+ return false;
+ }
+
+ // Maak MongoDB-client en haal datadirectory op
+ client = new MongoClient(connectionString);
+ var database = client.GetDatabase("admin");
+ var command = new BsonDocument { { "getCmdLineOpts", 1 } };
+ var result = await database.RunCommandAsync<BsonDocument>(command);
+ string? dataDirectory = result["parsed"]?["storage"]?["dbPath"]?.AsString;
+
+ if (string.IsNullOrEmpty(dataDirectory))
+ {
+ Console.WriteLine("Failed to retrieve MongoDB data directory (dbPath).");
+ return false;
+ }
+
+ // Controleer of de datadirectory bestaat, zo niet, maak deze aan
+ if (!Directory.Exists(dataDirectory))
+ {
+ Directory.CreateDirectory(dataDirectory);
+ }
+
+ // Stop de MongoDB-service
+ Console.WriteLine("Stopping MongoDB service...");
+ using (var serviceController = new ServiceController("MongoDB"))
+ {
+ if (serviceController.Status != ServiceControllerStatus.Stopped)
+ {
+ serviceController.Stop();
+ serviceController.WaitForStatus(ServiceControllerStatus.Stopped, TimeSpan.FromSeconds(30));
+ }
+ }
+ Console.WriteLine("MongoDB service stopped successfully.");
+
+ // Maak een back-up van de huidige datadirectory (optioneel)
+ string backupCurrentDir = Path.Combine(Path.GetDirectoryName(dataDirectory) ?? throw new InvalidOperationException("Invalid data directory path"), $"mongodb_data_backup_{DateTime.Now:yyyyMMdd_HHmmss}");
+ if (Directory.Exists(dataDirectory) && Directory.GetFiles(dataDirectory).Length > 0)
+ {
+ Console.WriteLine($"Backing up current data directory to '{backupCurrentDir}'...");
+ Directory.Move(dataDirectory, backupCurrentDir);
+ Directory.CreateDirectory(dataDirectory); // Maak lege datadirectory aan
+ }
+
+ // Extraheer de ZIP naar de datadirectory
+ Console.WriteLine($"Extracting ZIP file '{zipFilePath}' to '{dataDirectory}'...");
+ using (var zip = ZipFile.OpenRead(zipFilePath))
+ {
+ foreach (var entry in zip.Entries)
+ {
+ string destinationPath = Path.Combine(dataDirectory, entry.FullName);
+ // Zorg dat de directorystructuur bestaat
+ string? destinationDir = Path.GetDirectoryName(destinationPath);
+ if (!string.IsNullOrEmpty(destinationDir))
+ {
+ Directory.CreateDirectory(destinationDir);
+ }
+ // Extraheer het bestand
+ entry.ExtractToFile(destinationPath, overwrite: true);
+ }
+ }
+ Console.WriteLine("ZIP file extracted successfully.");
+
+ // Stel bestandsrechten in (optioneel, afhankelijk van je setup)
+ // Bijv. geef SYSTEM en Administrators volledige rechten
+ try
+ {
+ var directoryInfo = new DirectoryInfo(dataDirectory);
+ var security = directoryInfo.GetAccessControl();
+ security.AddAccessRule(new FileSystemAccessRule(
+ new SecurityIdentifier(WellKnownSidType.LocalSystemSid, null),
+ FileSystemRights.FullControl,
+ InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit,
+ PropagationFlags.None,
+ AccessControlType.Allow));
+ directoryInfo.SetAccessControl(security);
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"Warning: Failed to set file permissions: {ex.Message}");
+ }
+
+ // Start de MongoDB-service
+ Console.WriteLine("Starting MongoDB service...");
+ using (var serviceController = new ServiceController("MongoDB"))
+ {
+ serviceController.Start();
+ serviceController.WaitForStatus(ServiceControllerStatus.Running, TimeSpan.FromSeconds(30));
+ }
+ Console.WriteLine("MongoDB service started successfully.");
+
+ // Controleer of de database toegankelijk is
+ Console.WriteLine("Verifying database access...");
+ var dbs = await (await client.ListDatabasesAsync()).ToListAsync();
+ Console.WriteLine($"Databases found: {string.Join(", ", dbs.Select(db => db["name"].AsString))}");
+
+ Console.WriteLine($"Restore completed successfully in {sw.Elapsed}");
+ return true;
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"Restore failed: {ex.Message}");
+ return false;
+ }
+ finally
+ {
+ // Zorg dat de MongoDB-service draait, zelfs bij een fout
+ try
+ {
+ using var serviceController = new ServiceController("MongoDB");
+ if (serviceController.Status != ServiceControllerStatus.Running)
+ {
+ serviceController.Start();
+ serviceController.WaitForStatus(ServiceControllerStatus.Running, TimeSpan.FromSeconds(30));
+ Console.WriteLine("MongoDB service restarted after error.");
+ }
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"Error restarting MongoDB service: {ex.Message}");
+ }
+ }
+ }
}
diff --git a/BackupMongoDb/Program.cs b/BackupMongoDb/Program.cs
index a9c5786..b8a00e0 100644
--- a/BackupMongoDb/Program.cs
+++ b/BackupMongoDb/Program.cs
@@ -1,4 +1,25 @@

using BackupMongoDb;
-await Helper.BackupAsync(args.Length == 0 ? @"c:\temp" : args[0]);
+string connection = args.Length > 2 ? args[2] : "mongodb://localhost:27017";
+
+if (args.Length < 2)
+{
+ Console.WriteLine("Usage:");
+ Console.WriteLine($"\tBackupMongoDb -backup <backupdir> [{connection}]");
+ Console.WriteLine($"\tBackupMongoDb -restore <backupfile.zip> [{connection}]");
+
+ Environment.Exit(0);
+}
+
+if (args[0] == "-backup")
+{
+ await Helper.BackupAsync(args[1], connection);
+}
+
+if (args[0] == "-restore")
+{
+ await Helper.RestoreAsync(args[1], connection);
+}
+
+