mirror of
https://github.com/velopack/velopack.git
synced 2025-10-25 15:19:22 +00:00
Fixing memory violations
This commit is contained in:
@@ -25,7 +25,7 @@ HINSTANCE hInst;
|
||||
const WCHAR szTitle[] = L"Velopack C++ Sample App";
|
||||
const WCHAR szWindowClass[] = L"VeloCppWinSample";
|
||||
|
||||
std::optional<UpdateManager> managerOpt = std::nullopt;
|
||||
std::unique_ptr<UpdateManager> manager;
|
||||
std::optional<UpdateInfo> updInfo = std::nullopt;
|
||||
bool downloaded = false;
|
||||
|
||||
@@ -38,22 +38,36 @@ INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
|
||||
std::wstring Utf8ToWString(std::string const& str);
|
||||
std::string WStringToUtf8(std::wstring const& wstr);
|
||||
|
||||
void handle_vpkc_log(const char* pszLevel, const char* pszMessage)
|
||||
{
|
||||
std::cout << pszLevel << ": " << pszMessage << std::endl;
|
||||
}
|
||||
|
||||
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
|
||||
_In_opt_ HINSTANCE hPrevInstance,
|
||||
_In_ LPWSTR lpCmdLine,
|
||||
_In_ int nCmdShow)
|
||||
{
|
||||
// Redirect StdOut to console window
|
||||
AllocConsole();
|
||||
FILE* fp;
|
||||
_wfreopen_s(&fp, L"CONOUT$", L"w", stdout);
|
||||
_wfreopen_s(&fp, L"CONOUT$", L"w", stderr);
|
||||
_wfreopen_s(&fp, L"CONIN$", L"r", stdin);
|
||||
|
||||
// Initialize Velopack log capture
|
||||
std::cout << "Velopack C++ Sample App" << std::endl;
|
||||
UNREFERENCED_PARAMETER(hPrevInstance);
|
||||
vpkc_set_log(handle_vpkc_log);
|
||||
|
||||
// This should run as early as possible in the main method.
|
||||
// Velopack may exit / restart the app at this point.
|
||||
// See VelopackApp class for more options/configuration.
|
||||
VelopackApp::Build().Run();
|
||||
VelopackApp::Build()
|
||||
.Run();
|
||||
|
||||
try {
|
||||
// If the app is not installed, creating an UpdateManager will throw an exception.
|
||||
managerOpt = UpdateManager(UPDATE_URL);
|
||||
manager = std::make_unique<UpdateManager>(UPDATE_URL);
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
std::wstring what = Utf8ToWString(e.what());
|
||||
@@ -136,14 +150,9 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
case WM_COMMAND:
|
||||
{
|
||||
if (LOWORD(wParam) == BN_CLICKED) {
|
||||
if (!managerOpt.has_value()) {
|
||||
break; // this should not happen because we construct UpdateManager in wWinMain
|
||||
}
|
||||
auto manager = managerOpt.value();
|
||||
|
||||
if ((HWND)lParam == hCheckButton) {
|
||||
try {
|
||||
updInfo = manager.CheckForUpdates();
|
||||
updInfo = manager->CheckForUpdates();
|
||||
if (updInfo.has_value()) {
|
||||
std::string version = updInfo.value().TargetFullRelease.Version;
|
||||
std::wstring message = L"Update available: " + Utf8ToWString(version);
|
||||
@@ -161,7 +170,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
else if ((HWND)lParam == hDownloadButton) {
|
||||
if (updInfo.has_value()) {
|
||||
try {
|
||||
manager.DownloadUpdates(updInfo.value());
|
||||
manager->DownloadUpdates(updInfo.value());
|
||||
downloaded = true;
|
||||
MessageBoxCentered(hWnd, L"Download completed successfully.", szTitle, MB_OK);
|
||||
}
|
||||
@@ -179,7 +188,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
MessageBoxCentered(hWnd, L"Download an update first.", szTitle, MB_OK);
|
||||
}
|
||||
else {
|
||||
manager.WaitExitThenApplyUpdate(updInfo.value());
|
||||
manager->WaitExitThenApplyUpdate(updInfo.value());
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
@@ -192,10 +201,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
HDC hdc = BeginPaint(hWnd, &ps);
|
||||
RECT r{ 0, 5, ps.rcPaint.right, ps.rcPaint.bottom };
|
||||
|
||||
std::string currentVersion = "Not Installed";
|
||||
if (managerOpt.has_value()) {
|
||||
currentVersion = managerOpt.value().GetCurrentVersion();
|
||||
}
|
||||
std::string currentVersion = manager->GetCurrentVersion();
|
||||
auto ver = Utf8ToWString(currentVersion);
|
||||
std::wstring text = L"Welcome to v" + ver + L" of the\nVelopack C++ Sample App.";
|
||||
DrawText(hdc, text.c_str(), -1, &r, DT_BOTTOM | DT_CENTER);
|
||||
|
||||
@@ -5,6 +5,12 @@ VisualStudioVersion = 17.8.34525.116
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VeloCppWinSample", "VeloCppWinSample.vcxproj", "{F9BB1F11-3827-4745-B11B-77FA5DBE1195}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{25F8ED9F-9255-4CEC-AE44-7F2EAA392C18}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
build.bat = build.bat
|
||||
readme.md = readme.md
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x64 = Debug|x64
|
||||
|
||||
@@ -13,9 +13,8 @@ if "%~1"=="" (
|
||||
)
|
||||
|
||||
echo.
|
||||
echo Building Velopack Rust
|
||||
cd %~dp0..\..\..\for-rust
|
||||
cargo build --features cli -r
|
||||
echo Building Velopack C Lib with Cargo
|
||||
cargo build -p velopack_libc
|
||||
|
||||
cd %~dp0
|
||||
|
||||
@@ -43,8 +42,6 @@ cd %~dp0
|
||||
|
||||
echo #define UPDATE_URL "REPLACE_ME" > constants.h
|
||||
|
||||
copy %~dp0..\..\..\for-rust\target\release\vfusion.exe x64\Debug
|
||||
|
||||
echo.
|
||||
echo Building Velopack Release v%~1
|
||||
vpk pack -u VeloCppWinSample -o releases -p x64\Debug -v %*
|
||||
vpk pack -u VelopackCppWin32Sample -o releases -p x64\Debug -v %* -e VeloCppWinSample.exe
|
||||
@@ -1,5 +1,5 @@
|
||||
# VeloCppWinSample
|
||||
_Prerequisites: Rust/Cargo, Dotnet, Msbuild_
|
||||
# VelopackCppWin32Sample
|
||||
_Prerequisites: Rust/Cargo, Msbuild_
|
||||
|
||||
This app is purely a proof of concept at this time, `velopack.hpp` currently only works on windows and needs testing / fixes for other operating systems, and probably also needs fixing for unicode/strings. This sample is made up of a simple Win32 desktop app, generated via a Visual Studio template, and it includes `velopack.hpp` and [`subprocess.h`](https://github.com/sheredom/subprocess.h).
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef void* vpkc_update_manager_t;
|
||||
typedef void vpkc_update_manager_t;
|
||||
typedef void (*vpkc_progress_callback_t)(size_t progress);
|
||||
typedef void (*vpkc_log_callback_t)(const char* pszLevel, const char* pszMessage);
|
||||
typedef void (*vpkc_hook_callback_t)(const char* pszAppVersion);
|
||||
@@ -93,7 +93,7 @@ typedef struct {
|
||||
// !! AUTO-GENERATED-END C_TYPES
|
||||
|
||||
// Update Manager
|
||||
VPKC_EXPORT bool VPKC_CALL vpkc_new_update_manager(const char* pszUrlOrString, vpkc_update_options_t* pOptions, vpkc_locator_config_t* pLocator, vpkc_update_manager_t* pManager);
|
||||
VPKC_EXPORT bool VPKC_CALL vpkc_new_update_manager(const char* pszUrlOrString, vpkc_update_options_t* pOptions, vpkc_locator_config_t* pLocator, vpkc_update_manager_t** pManager);
|
||||
VPKC_EXPORT size_t VPKC_CALL vpkc_get_current_version(vpkc_update_manager_t* pManager, char* pszVersion, size_t cVersion);
|
||||
VPKC_EXPORT size_t VPKC_CALL vpkc_get_app_id(vpkc_update_manager_t* pManager, char* pszId, size_t cId);
|
||||
VPKC_EXPORT bool VPKC_CALL vpkc_is_portable(vpkc_update_manager_t* pManager);
|
||||
@@ -330,7 +330,7 @@ public:
|
||||
|
||||
class UpdateManager {
|
||||
private:
|
||||
vpkc_update_manager_t m_pManager;
|
||||
vpkc_update_manager_t* m_pManager = 0;
|
||||
public:
|
||||
UpdateManager(const std::string& urlOrPath, const UpdateOptions* options = nullptr, const VelopackLocatorConfig* locator = nullptr) {
|
||||
vpkc_update_options_t* pOptions = nullptr;
|
||||
@@ -345,31 +345,31 @@ public:
|
||||
pLocator = &vpkc_locator;
|
||||
}
|
||||
|
||||
if (0 != vpkc_new_update_manager(urlOrPath.c_str(), pOptions, pLocator, &m_pManager)) {
|
||||
if (!vpkc_new_update_manager(urlOrPath.c_str(), pOptions, pLocator, &m_pManager)) {
|
||||
throw_last_error();
|
||||
}
|
||||
};
|
||||
~UpdateManager() {
|
||||
vpkc_free_update_manager(&m_pManager);
|
||||
vpkc_free_update_manager(m_pManager);
|
||||
};
|
||||
bool IsPortable() noexcept {
|
||||
return vpkc_is_portable(&m_pManager);
|
||||
return vpkc_is_portable(m_pManager);
|
||||
};
|
||||
std::string GetCurrentVersion() noexcept {
|
||||
size_t neededSize = vpkc_get_current_version(&m_pManager, nullptr, 0);
|
||||
size_t neededSize = vpkc_get_current_version(m_pManager, nullptr, 0);
|
||||
std::string strVersion(neededSize, '\0');
|
||||
vpkc_get_current_version(&m_pManager, &strVersion[0], neededSize);
|
||||
vpkc_get_current_version(m_pManager, &strVersion[0], neededSize);
|
||||
return strVersion;
|
||||
};
|
||||
std::string GetAppId() noexcept {
|
||||
size_t neededSize = vpkc_get_app_id(&m_pManager, nullptr, 0);
|
||||
size_t neededSize = vpkc_get_app_id(m_pManager, nullptr, 0);
|
||||
std::string strId(neededSize, '\0');
|
||||
vpkc_get_app_id(&m_pManager, &strId[0], neededSize);
|
||||
vpkc_get_app_id(m_pManager, &strId[0], neededSize);
|
||||
return strId;
|
||||
};
|
||||
std::optional<VelopackAsset> UpdatePendingRestart() noexcept {
|
||||
vpkc_asset_t asset;
|
||||
if (vpkc_update_pending_restart(&m_pManager, &asset)) {
|
||||
if (vpkc_update_pending_restart(m_pManager, &asset)) {
|
||||
VelopackAsset cpp_asset = to_cpp(asset);
|
||||
vpkc_free_asset(&asset);
|
||||
return cpp_asset;
|
||||
@@ -378,7 +378,7 @@ public:
|
||||
};
|
||||
std::optional<UpdateInfo> CheckForUpdates() {
|
||||
vpkc_update_info_t update;
|
||||
vpkc_update_check_t result = vpkc_check_for_updates(&m_pManager, &update);
|
||||
vpkc_update_check_t result = vpkc_check_for_updates(m_pManager, &update);
|
||||
switch (result) {
|
||||
case vpkc_update_check_t::UPDATE_ERROR:
|
||||
throw_last_error();
|
||||
@@ -394,7 +394,7 @@ public:
|
||||
};
|
||||
void DownloadUpdates(const UpdateInfo& update, vpkc_progress_callback_t progress = nullptr) {
|
||||
vpkc_update_info_t vpkc_update = to_c(update);
|
||||
if (!vpkc_download_updates(&m_pManager, &vpkc_update, progress)) {
|
||||
if (!vpkc_download_updates(m_pManager, &vpkc_update, progress)) {
|
||||
throw_last_error();
|
||||
}
|
||||
};
|
||||
@@ -406,7 +406,7 @@ public:
|
||||
}
|
||||
|
||||
vpkc_asset_t vpkc_asset = to_c(asset);
|
||||
bool result = vpkc_wait_exit_then_apply_update(&m_pManager, &vpkc_asset, silent, restart, pRestartArgs, restartArgs.size());
|
||||
bool result = vpkc_wait_exit_then_apply_update(m_pManager, &vpkc_asset, silent, restart, pRestartArgs, restartArgs.size());
|
||||
|
||||
// Free all the memory
|
||||
for (size_t i = 0; i < restartArgs.size(); i++) {
|
||||
|
||||
@@ -235,15 +235,20 @@ static inline void clear_last_error() {
|
||||
}
|
||||
|
||||
// Update Manager
|
||||
VPKC_EXPORT bool VPKC_CALL vpkc_new_update_manager(const char* pszUrlOrString, vpkc_update_options_t* pOptions, vpkc_locator_config_t* pLocator, vpkc_update_manager_t* pManager) {
|
||||
VPKC_EXPORT bool VPKC_CALL vpkc_new_update_manager(const char* pszUrlOrString, vpkc_update_options_t* pOptions, vpkc_locator_config_t* pLocator, vpkc_update_manager_t** pManager) {
|
||||
clear_last_error();
|
||||
try {
|
||||
if (pManager == nullptr) {
|
||||
set_last_error("pManager cannot be null");
|
||||
return false;
|
||||
}
|
||||
|
||||
VelopackLocatorConfigDtoOption locator = to_bridge_opt(pLocator);
|
||||
UpdateOptionsDtoOption options = to_bridge_opt(pOptions);
|
||||
|
||||
::rust::Box<::UpdateManagerOpaque> manager = bridge_new_update_manager(pszUrlOrString, options, locator);
|
||||
UpdateManagerOpaque* pOpaque = manager.into_raw();
|
||||
*pManager = pOpaque;
|
||||
*pManager = reinterpret_cast<vpkc_update_manager_t*>(pOpaque);
|
||||
return true;
|
||||
} catch (const std::exception& e) {
|
||||
set_last_error(e.what());
|
||||
@@ -251,22 +256,22 @@ VPKC_EXPORT bool VPKC_CALL vpkc_new_update_manager(const char* pszUrlOrString, v
|
||||
}
|
||||
}
|
||||
VPKC_EXPORT size_t VPKC_CALL vpkc_get_current_version(vpkc_update_manager_t* pManager, char* pszVersion, size_t cVersion) {
|
||||
UpdateManagerOpaque* pOpaque = reinterpret_cast<UpdateManagerOpaque*>(*pManager);
|
||||
UpdateManagerOpaque* pOpaque = reinterpret_cast<UpdateManagerOpaque*>(pManager);
|
||||
std::string version = (std::string)bridge_get_current_version(*pOpaque);
|
||||
return return_c_string(version, pszVersion, cVersion);
|
||||
}
|
||||
VPKC_EXPORT size_t VPKC_CALL vpkc_get_app_id(vpkc_update_manager_t* pManager, char* pszId, size_t cId) {
|
||||
UpdateManagerOpaque* pOpaque = reinterpret_cast<UpdateManagerOpaque*>(*pManager);
|
||||
UpdateManagerOpaque* pOpaque = reinterpret_cast<UpdateManagerOpaque*>(pManager);
|
||||
std::string id = (std::string)bridge_get_app_id(*pOpaque);
|
||||
return return_c_string(id, pszId, cId);
|
||||
|
||||
}
|
||||
VPKC_EXPORT bool VPKC_CALL vpkc_is_portable(vpkc_update_manager_t* pManager) {
|
||||
UpdateManagerOpaque* pOpaque = reinterpret_cast<UpdateManagerOpaque*>(*pManager);
|
||||
UpdateManagerOpaque* pOpaque = reinterpret_cast<UpdateManagerOpaque*>(pManager);
|
||||
return bridge_is_portable(*pOpaque);
|
||||
}
|
||||
VPKC_EXPORT bool VPKC_CALL vpkc_update_pending_restart(vpkc_update_manager_t* pManager, vpkc_asset_t* pAsset) {
|
||||
UpdateManagerOpaque* pOpaque = reinterpret_cast<UpdateManagerOpaque*>(*pManager);
|
||||
UpdateManagerOpaque* pOpaque = reinterpret_cast<UpdateManagerOpaque*>(pManager);
|
||||
VelopackAssetDtoOption asset = bridge_update_pending_restart(*pOpaque);
|
||||
if (asset.has_data) {
|
||||
allocate_velopackasset(asset.data, pAsset);
|
||||
@@ -277,7 +282,7 @@ VPKC_EXPORT bool VPKC_CALL vpkc_update_pending_restart(vpkc_update_manager_t* pM
|
||||
VPKC_EXPORT vpkc_update_check_t VPKC_CALL vpkc_check_for_updates(vpkc_update_manager_t* pManager, vpkc_update_info_t* pUpdate) {
|
||||
clear_last_error();
|
||||
try {
|
||||
UpdateManagerOpaque* pOpaque = reinterpret_cast<UpdateManagerOpaque*>(*pManager);
|
||||
UpdateManagerOpaque* pOpaque = reinterpret_cast<UpdateManagerOpaque*>(pManager);
|
||||
UpdateInfoDtoOption update = bridge_check_for_updates(*pOpaque);
|
||||
if (update.has_data) {
|
||||
allocate_updateinfo(update.data, pUpdate);
|
||||
@@ -298,7 +303,7 @@ VPKC_EXPORT bool VPKC_CALL vpkc_download_updates(vpkc_update_manager_t* pManager
|
||||
return false;
|
||||
}
|
||||
|
||||
UpdateManagerOpaque* pOpaque = reinterpret_cast<UpdateManagerOpaque*>(*pManager);
|
||||
UpdateManagerOpaque* pOpaque = reinterpret_cast<UpdateManagerOpaque*>(pManager);
|
||||
UpdateInfoDto update = to_bridge(pUpdate);
|
||||
|
||||
DownloadCallbackManager download{};
|
||||
@@ -319,7 +324,7 @@ VPKC_EXPORT bool VPKC_CALL vpkc_wait_exit_then_apply_update(vpkc_update_manager_
|
||||
return false;
|
||||
}
|
||||
|
||||
UpdateManagerOpaque* pOpaque = reinterpret_cast<UpdateManagerOpaque*>(*pManager);
|
||||
UpdateManagerOpaque* pOpaque = reinterpret_cast<UpdateManagerOpaque*>(pManager);
|
||||
VelopackAssetDto asset = to_bridge(pAsset);
|
||||
|
||||
::rust::Vec<::rust::String> restartArgs{};
|
||||
@@ -384,7 +389,7 @@ VPKC_EXPORT void VPKC_CALL vpkc_set_log(vpkc_log_callback_t cbLog) {
|
||||
bridge_set_logger_callback(&logMgr);
|
||||
}
|
||||
VPKC_EXPORT void VPKC_CALL vpkc_free_update_manager(vpkc_update_manager_t* pManager) {
|
||||
UpdateManagerOpaque* pOpaque = reinterpret_cast<UpdateManagerOpaque*>(*pManager);
|
||||
UpdateManagerOpaque* pOpaque = reinterpret_cast<UpdateManagerOpaque*>(pManager);
|
||||
auto box = ::rust::Box<::UpdateManagerOpaque>::from_raw(pOpaque);
|
||||
// this will free when the box goes out of scope
|
||||
}
|
||||
|
||||
@@ -144,6 +144,19 @@ struct UpdateManagerOpaque {
|
||||
obj: UpdateManager,
|
||||
}
|
||||
|
||||
impl UpdateManagerOpaque {
|
||||
fn new(obj: UpdateManager) -> Self {
|
||||
log::debug!("UpdateManagerOpaque allocated");
|
||||
UpdateManagerOpaque { obj }
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for UpdateManagerOpaque {
|
||||
fn drop(&mut self) {
|
||||
log::debug!("UpdateManagerOpaque dropped");
|
||||
}
|
||||
}
|
||||
|
||||
fn bridge_new_update_manager(
|
||||
url_or_path: &String,
|
||||
options: &ffi::UpdateOptionsDtoOption,
|
||||
@@ -153,7 +166,7 @@ fn bridge_new_update_manager(
|
||||
let options = updateoptions_to_core_option(options);
|
||||
let locator = velopacklocatorconfig_to_core_option(locator);
|
||||
let update_manager = UpdateManager::new(source, options, locator)?;
|
||||
Ok(Box::new(UpdateManagerOpaque { obj: update_manager }))
|
||||
Ok(Box::new(UpdateManagerOpaque::new(update_manager)))
|
||||
}
|
||||
|
||||
fn bridge_get_current_version(manager: &UpdateManagerOpaque) -> String {
|
||||
|
||||
Reference in New Issue
Block a user