What's new

FREE C++ Windows App Source Code to database backup & restore tool if anyone is interested

Return(0)

Trial Member
9
2025
0
Easy MYSQL Backup & Restore Tool - Version 1.30

FREE TO USE

Screenshot_28.png


Paste into Visual Studio and compile it.

Just need to add 3 EXE dependencies from MariaDB or MySql to the root of this Backup Tools EXE location. You can find these 3 in the bin folder of the install of the database install.

mysql
mysqladmin
mysqldump

This gives you a nice GUI backup and restore tool that has command shell instructions to pass all that could be done in command shell call to MariaDB or Mysql. When backing up a database it grabs all databases and makes a dump file of all databases with todays date and time appended to the file name such as alldatabases_05242025_124351, and when wanting to restore a database from a dump file backup you can navigate to the dump file you want to restore from and select it and push the dump file to overwrite the current database from an older dump file backup.

NOTE: This will call a system call to command shell from within the Windows App and when doing so you will see a command shell window appear. Its critical that this is not interrupted when its running. As you can see in the source code shared here there is nothing malicious in the code and so it is completely safe for this window to appear as its running instructions to the database service.

Additionally the first time you use this you can create a DBTconfig.txt file so that the next time you launch this tool it automatically populates with all the info for your database and so you then just need to select to backup or restore the database.

Its best to backup and restore the database when only the database service is running so that the database is in an idle state vs when its active with read/write requests.

I compiled this with Visual Studio 2022 with C++ 2020 in the preferences. It may compile with C++ 2014 and C++ 2017 if you have an older install of Visual Studio. I used the free community edition.

NOTE: If you have a few different projects that use different versions of databases you will want to create seperate folders and keep the pairing of the 3 EXEs from those databases bin folders with this tools EXE so that its the correct version of these 3 EXE's referencing the running database service. For example MySQL 5.45 and 8.0 reference differently and so if your running the 5.45 service you will want to run the EXE with the paired 3 EXEs that pertain to 5.45 for 5.45 and not have the 3 EXEs from a mismatched version calling to the active database service.

The manual that I created for this program is down below this source code. Free for all to use at your own risk.

#include <windows.h>
#include <commdlg.h>
#include <shlwapi.h>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
#include <regex>

#pragma comment(lib, "comdlg32.lib")
#pragma comment(lib, "shlwapi.lib")

#define ID_BACKUP 1
#define ID_RESTORE 2
#define ID_CLOSE 3
#define ID_SAVE_CONFIG 4
#define ID_TEST_CONN 5

HWND hUser, hPassword, hIP, hPort;

bool IsValidIP(const std::wstring& ip) {
std::wregex ipRegex(LR"(^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$)");
return std::regex_match(ip, ipRegex);
}

bool IsValidPort(const std::wstring& portStr) {
if (!std::all_of(portStr.begin(), portStr.end(), ::iswdigit)) return false;
int port = std::stoi(portStr);
return port >= 0 && port <= 65535;
}

void LoadConfig(HWND hwnd) {
std::wifstream infile(L"DBTconfig.txt");
std::wstring user, password, ip, port;
if (infile) {
std::getline(infile, user);
std::getline(infile, password);
std::getline(infile, ip);
std::getline(infile, port);

SetWindowTextW(hUser, user.c_str());
SetWindowTextW(hPassword, password.c_str());

if (IsValidIP(ip)) {
SetWindowTextW(hIP, ip.c_str());
}
else {
MessageBox(hwnd, L"IP address missing or corrupt in DBTconfig.txt", L"Error", MB_OK | MB_ICONERROR);
SetWindowTextW(hIP, L"127.0.0.1");
}

if (IsValidPort(port)) {
SetWindowTextW(hPort, port.c_str());
}
else {
MessageBox(hwnd, L"Invalid Port Number in DBTconfig.txt", L"Error", MB_OK | MB_ICONERROR);
SetWindowTextW(hPort, L"3306");
}
}
}

void SaveConfig(HWND hwnd) {
wchar_t user[101], password[101], ip[100], port[10];
GetWindowTextW(hUser, user, 101);
GetWindowTextW(hPassword, password, 101);
GetWindowTextW(hIP, ip, 100);
GetWindowTextW(hPort, port, 10);

if (!IsValidIP(ip)) {
MessageBox(hwnd, L"IP Address Incorrect .. Please enter a Valid IP Address", L"Error", MB_OK | MB_ICONERROR);
return;
}
if (!IsValidPort(port)) {
MessageBox(hwnd, L"Port Number Incorrect .. Please enter a Valid Port Number", L"Error", MB_OK | MB_ICONERROR);
return;
}

std::wofstream outfile(L"DBTconfig.txt");
if (outfile) {
outfile << user << L"\n" << password << L"\n" << ip << L"\n" << port << L"\n";
}
}

void TestConnection(HWND hwnd) {
wchar_t user[101], password[101], ip[100], port[10];
GetWindowTextW(hUser, user, 101);
GetWindowTextW(hPassword, password, 101);
GetWindowTextW(hIP, ip, 100);
GetWindowTextW(hPort, port, 10);

if (!IsValidIP(ip)) {
MessageBox(hwnd, L"IP Address Incorrect .. Please enter a Valid IP Address", L"Error", MB_OK | MB_ICONERROR);
return;
}

if (!IsValidPort(port)) {
MessageBox(hwnd, L"Port Number Incorrect .. Please enter a Valid Port Number", L"Error", MB_OK | MB_ICONERROR);
return;
}

std::wstringstream cmd;
cmd << L"mysqladmin -u" << user << L" -p" << password << L" -h" << ip << L" -P" << port << L" version >nul 2>&1";

int result = _wsystem(cmd.str().c_str());

if (result == 0) {
MessageBox(hwnd, L"Connection Successful", L"Success", MB_OK | MB_ICONINFORMATION);
}
else {
MessageBox(hwnd, L"Unable to connect, check credentials and configuration settings.", L"Connection Failed", MB_OK | MB_ICONERROR);
}
}

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
case WM_COMMAND:
switch (LOWORD(wParam)) {
case ID_SAVE_CONFIG:
SaveConfig(hwnd);
break;
case ID_TEST_CONN:
TestConnection(hwnd);
break;
case ID_BACKUP:
case ID_RESTORE: {
wchar_t user[101], password[101], ip[100], port[10];
GetWindowTextW(hUser, user, 101);
GetWindowTextW(hPassword, password, 101);
GetWindowTextW(hIP, ip, 100);
GetWindowTextW(hPort, port, 10);

if (!IsValidIP(ip)) {
MessageBox(hwnd, L"IP Address Incorrect .. Please enter a Valid IP Address", L"Error", MB_OK | MB_ICONERROR);
return 0;
}
if (!IsValidPort(port)) {
MessageBox(hwnd, L"Port Number Incorrect .. Please enter a Valid Port Number", L"Error", MB_OK | MB_ICONERROR);
return 0;
}

std::wstringstream cmd;

if (LOWORD(wParam) == ID_BACKUP) {
if (MessageBox(hwnd, L"Are you sure you want to backup databases?", L"Confirm Backup", MB_OKCANCEL | MB_ICONQUESTION) == IDCANCEL)
return 0;

SYSTEMTIME st;
GetLocalTime(&st);
wchar_t filename[256];
swprintf(filename, 256, L"alldatabases_%02d%02d%04d_%02d%02d%02d.sql",
st.wMonth, st.wDay, st.wYear, st.wHour, st.wMinute, st.wSecond);

cmd << L"mysqldump -u" << user << L" -p" << password << L" -h" << ip << L" -P" << port << L" --all-databases > \"" << filename << L"\"";
_wsystem(cmd.str().c_str());
MessageBox(hwnd, L"Backup Completed", L"Info", MB_OK | MB_ICONINFORMATION);
}
else {
OPENFILENAME ofn = { 0 };
wchar_t szFile[260] = { 0 };
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = hwnd;
ofn.lpstrFilter = L"SQL Files (*.sql)\0*.sql\0";
ofn.lpstrFile = szFile;
ofn.nMaxFile = sizeof(szFile) / sizeof(szFile[0]);
ofn.lpstrTitle = L"Select SQL Backup File";
ofn.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST;

if (GetOpenFileName(&ofn)) {
if (MessageBox(hwnd, L"Are you sure you want to restore databases?", L"Confirm Restore", MB_OKCANCEL | MB_ICONQUESTION) == IDCANCEL)
return 0;
cmd << L"mysql -u" << user << L" -p" << password << L" -h" << ip << L" -P" << port << L" < \"" << szFile << L"\"";
_wsystem(cmd.str().c_str());
MessageBox(hwnd, L"Restore Completed", L"Info", MB_OK | MB_ICONINFORMATION);
}
}
break;
}
case ID_CLOSE:
PostQuitMessage(0);
break;
}
return 0;

case WM_CREATE:
CreateWindowW(L"STATIC", L"Username:", WS_VISIBLE | WS_CHILD, 20, 20, 80, 20, hwnd, NULL, NULL, NULL);
hUser = CreateWindowW(L"EDIT", L"", WS_VISIBLE | WS_CHILD | WS_BORDER, 110, 20, 150, 20, hwnd, NULL, NULL, NULL);

CreateWindowW(L"STATIC", L"Password:", WS_VISIBLE | WS_CHILD, 20, 50, 80, 20, hwnd, NULL, NULL, NULL);
hPassword = CreateWindowW(L"EDIT", L"", WS_VISIBLE | WS_CHILD | WS_BORDER | ES_PASSWORD, 110, 50, 150, 20, hwnd, NULL, NULL, NULL);

CreateWindowW(L"STATIC", L"IP Address:", WS_VISIBLE | WS_CHILD, 20, 80, 80, 20, hwnd, NULL, NULL, NULL);
hIP = CreateWindowW(L"EDIT", L"127.0.0.1", WS_VISIBLE | WS_CHILD | WS_BORDER, 110, 80, 150, 20, hwnd, NULL, NULL, NULL);

CreateWindowW(L"STATIC", L"Port:", WS_VISIBLE | WS_CHILD, 20, 110, 80, 20, hwnd, NULL, NULL, NULL);
hPort = CreateWindowW(L"EDIT", L"3306", WS_VISIBLE | WS_CHILD | WS_BORDER, 110, 110, 150, 20, hwnd, NULL, NULL, NULL);

CreateWindowW(L"BUTTON", L"Save Config", WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, 20, 150, 100, 30, hwnd, (HMENU)ID_SAVE_CONFIG, NULL, NULL);
CreateWindowW(L"BUTTON", L"Test Connection", WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, 130, 150, 130, 30, hwnd, (HMENU)ID_TEST_CONN, NULL, NULL);

CreateWindowW(L"BUTTON", L"Backup Database", WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, 50, 200, 200, 40, hwnd, (HMENU)ID_BACKUP, NULL, NULL);
CreateWindowW(L"BUTTON", L"Restore Database", WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, 270, 200, 200, 40, hwnd, (HMENU)ID_RESTORE, NULL, NULL);
CreateWindowW(L"BUTTON", L"Close", WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, 480, 250, 100, 30, hwnd, (HMENU)ID_CLOSE, NULL, NULL);

LoadConfig(hwnd);
return 0;

case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, PWSTR, int nCmdShow) {
const wchar_t CLASS_NAME[] = L"DatabaseBackupRestoreApp";

WNDCLASSW wc = {};
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = CLASS_NAME;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);

RegisterClassW(&wc);

HWND hwnd = CreateWindowExW(
0, CLASS_NAME, L"Easy MySQL Backup & Restore Tool Version 1.30 - Dave Lembke - 5/12/2025", WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX,
CW_USEDEFAULT, CW_USEDEFAULT, 650, 340,
NULL, NULL, hInstance, NULL
);

if (hwnd == NULL) return 0;

ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);

MSG msg = {};
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}

Here is the instruction manual I made for this program in plain text for all to see without having to download as well:

---------------------------------------------------------------------------------------------------
[ Easy MySQL Database Backup & Restore Tool ]
---------------------------------------------------------------------------------------------------
[ Version 1.30 ]
---------------------------------------------------------------------------------------------------
[ Programmed by Dave Lembke - 5/12/2025 ]
---------------------------------------------------------------------------------------------------
[ Features ]
---------------------------------------------------------------------------------------------------
1.) One Time Configuration option:
Upon Launch of Program it checks for DBTconfig.txt and if it exists with valid data in it,
it will automatically populate the fields of User, Password, IP, and Port Number.

If any of the fields change for User, Password, IP, or Port Number you can make the change
and click on the (Save Config) Button which will overwrite the previous DBTconfig.txt file.

2.) Date/Time Stamped DUMP FILES:
Dump file is named with Date/Time stamp such as alldatabases_05112025_204351.sql for a
backup that was run to create the dump file of alldatabases at 204351 which is 20:43:51 =
20h 43m 51s aka 8:43pm and 51 seconds on 05/11/2025.

3.) Database Restore Navigation:
Clicking on (Restore Database) will open up Windows Explorer to allow for you to navigate
to the location of your dump file. You then select the file you want to use to overwrite
all data on your database.

4.) Warning System:
Each function of Backup and Restore have a verification process that you must accept for it
to carry out the action. You will see a Confirm Backup with a OK/Cancel (or) Restore Database
with an OK/Cancel option. If you select OK it will carry out the operation. If you select
Cancel it will end the request and bring you back to the program.

5.) Close Program:
You can either click on (CLOSE) or the [X] at top right of the window to exit the program.
NOTE: The window size is fixed to 650 x 340 so the maximize window feature is disabled.

6.) Password field accepts password and stars out the characters to protect password from being
viewed by others in view of your screen.
Note: The password however is stored as clear ascii text in the DBTconfig.txt, if you should
chose to save the configuration using this autoload feature as described in ( 1.)
AND so while you see the password as ********** in the program its clear text as
Hell0w0rld1$ within the DBTconfig.txt file if your password was Hell0w0rld1$ .

WARNING:
If someone other than yourself has physical access to the computer this is run at
they could open the DBTconfig.txt file to read and compromise your password!!!

---------------------------------------------------------------------------------------------------
[ Instructions ]
---------------------------------------------------------------------------------------------------

#1 <Optional> Skip to #2 if your not going to create a config file.

Create a Config File so that additional use of this program automatically populates
the fields for User, Password, IP Address, and Port Number.

1.) Populate the fields for User, Password, IP Address, and Port Number.
2.) Click on (Save Config)
3.) Close Program
4.) Launch Program and all fields should populate with correct data
5.) *IF something is incorrect you can change it and Click (Save Config) to
over-write the prior DBTconfig.txt file with correct data.
6.) Launch Program and all fields should populate with correct data

#2 <Populate Fields> Skip to #3 if you have fields populated automatically via the DBTconfig.txt

1.) Enter the USER for the database
2.) Enter the PASSWORD for the database
3.) Change the IP from 127.0.0.1 to IP of the Database Server if the server is
not local to the computer that this program is running on - or - if
permissions on the database prevent 127.0.0.1 locally and it requires
its static IP Address ( ex. 192.168.1.125 )
4 ) Change the PORT from (3306) to whichever port the database is listening
for connection at.
5.) If you came this far and have not saved your configuration to DBTconfig.txt
and wish to do so Click on the (Save Config) button and it will write the
configuration data to DBTconfig.txt

#3 <Backup Database> Skip to #4 if you want to Restore a Database

1.) If you have all fields populated for User, Password, IP Address, and Port Number
carry out instruction ( 2.)
2.) Click on (Backup Database)

Note: A pop up box will appear with
"Confirm Backup" - (?) Are you sure you want to backup alldatabases?

3.) Select [OK] if you want it to run -or- [Cancel] if you accidentally
started the backup function.

Note: Upon selecting [OK] a Shell Window will appear with no information
"DO NOT CLOSE THIS"
When Process is complete it will close itself
*Depending on size of Database and rate at which the Backup can write
from the database the DUMP File, it can take seconds or minutes.

WARNING: If the backup is "very fast" like 1 second and done, it could be
that the credentials supplied to this program are incorrect or
user is not privileged enough in the database to be granted the
privilege of performing backups. *See Database Administrator!

4.) Verify that the database backup file is larger than 0 KB in size.

Note: The location that this program is run from the backup files are written
to this same location. *IF you see that the alldatabases backup file
is in fact 0 KB in size it means that either the credentials were
incorrect or the backup process was interrupted. Verify correct
credentials and try again.

#4 <Restore Database> Skip to elsewhere of your choice if here and not wanting to be here ;)

1.) If you have all fields populated for User, Password, IP Address, and Port Number
carry out instruction ( 2.)
2.) Click on (Restore Database)

Note: Windows Explorer will now allow for you to navigate to the database you want
to restore from.
3.) Select Database and Click [OPEN]

Note: A pop up box will appear with
"Confirm Restore" - (?) Are you sure you want to restore alldatabases?

3.) Select [OK] if you want it to run -or- [Cancel] if you accidentally
started the restore function.

Note: Upon selecting [OK] a Shell Window will appear with no information
"DO NOT CLOSE THIS"
When Process is complete it will close itself
*Depending on size of Database and rate at which the Restore can write
to the database it can take seconds or minutes.

WARNING: If the restore is "very fast" like 1 second and done, it could be
that the credentials supplied to this program are incorrect or
user is not privileged enough in the database to be granted the
privilege of performing restores. *See Database Administrator!

4.) Verify that the database restore was successful- If it was super fast see Warning!

*Whatever problem that the database had that caused you to have to restore it
should be corrected assuming it didn't exist as a problem upon the backup.

**IF credentials were incorrect the problem will still remain -additionally-
if the problem was written to this backup you may have to restore from
an even earlier backup -or- cut your losses and manually repair the database
for the problem to avoid loss of data that was written to the database
between the backup checkpoints.

---------------------------------------------------------------------------------------------------
[ Troubleshooting ]
---------------------------------------------------------------------------------------------------

Program Crashes and doesn't appear:

This program was written in Visual Studio 2022 as a Windows App in C++ 2020 standard
* You may be missing a C++ Redistributable Package that supports the program.
- Verify that you have the latest C++ Redist Packages installed.

This program was designed and tested on Windows 10 and 11 64-bit operation
* You may be running this on an incompatible version of Windows to its instruction set.
- Find a computer with a newer Windows OS to run this from -or- upgrade to Windows
10 64-bit -or- 11 64-bit

This Program while lightweight for resource requirements does have its needs
* System its running on does not have enough resources to execute the program ( Unlikely )
- Free up HDD or SSD space
- Add more RAM

Computer is in need of a rebuild with a fresh OS install as its corrupt somehow
* Either Malware or some other corruption exists within Windows OS
- Backup all data to external drive or the cloud and reinstall the OS
- Pray that its not a HDD or SSD thats about to crash that caused the issue to begin with
Note: I suggest CrystalDiskInfo for scanning HDD and SSD for drive health if its in
question. This is a free utility online and comes as a stand alone EXE or
you can install the MSI if you don't want the portable EXE version of this.
Both operate the same, however the MSI installed version of it allows you to
call to it from Windows vs having to target the specific EXE to launch it.

---------------------------------------------------------------------------------------------
Use at own Risk and if anyone has any bugs with this please report them back to me and I will work on fixing them, but this appears to be solid when testing it and using it for my needs.
 

Attachments

  • Screenshot_27.png
    Screenshot_27.png
    10.4 KB · Views: 49
Last edited:
Top