mirror of
https://github.com/modernw/App-Installer-For-Windows-8.x-Reset.git
synced 2026-06-21 22:51:00 +10:00
Update Settings Shell.
This commit is contained in:
@@ -0,0 +1,239 @@
|
||||
#pragma once
|
||||
#include <Windows.h>
|
||||
#include <WinInet.h>
|
||||
#include <string>
|
||||
#include "strcode.h"
|
||||
#include "mpstr.h"
|
||||
#include <chrono>
|
||||
#include <rapidjson/writer.h>
|
||||
#include <rapidjson/stringbuffer.h>
|
||||
|
||||
// Generated by ChatGTP
|
||||
|
||||
using namespace System;
|
||||
using namespace System::Threading;
|
||||
using namespace System::Reflection;
|
||||
#include <Windows.h>
|
||||
#include <string>
|
||||
|
||||
std::wstring GetLastErrorString ()
|
||||
{
|
||||
DWORD errCode = GetLastError ();
|
||||
if (errCode == 0)
|
||||
return L"No error";
|
||||
|
||||
wchar_t* msgBuffer = nullptr;
|
||||
|
||||
// FORMAT_MESSAGE_ALLOCATE_BUFFER: 让系统分配缓冲区
|
||||
// FORMAT_MESSAGE_FROM_SYSTEM: 从系统获取错误信息
|
||||
// FORMAT_MESSAGE_IGNORE_INSERTS: 忽略 %1 %2
|
||||
DWORD size = FormatMessageW (
|
||||
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
nullptr,
|
||||
errCode,
|
||||
0, // 默认语言
|
||||
(LPWSTR)&msgBuffer,
|
||||
0,
|
||||
nullptr
|
||||
);
|
||||
|
||||
std::wstring msg;
|
||||
if (size && msgBuffer)
|
||||
{
|
||||
msg = msgBuffer;
|
||||
LocalFree (msgBuffer); // 释放缓冲区
|
||||
}
|
||||
else
|
||||
{
|
||||
msg = L"Unknown error code: " + std::to_wstring (errCode);
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
|
||||
public ref class DownloadHelper
|
||||
{
|
||||
public:
|
||||
static void DownloadFile (
|
||||
String^ httpUrl,
|
||||
String^ savePath,
|
||||
Object^ onProgress,
|
||||
Object^ onComplete,
|
||||
Object^ onError)
|
||||
{
|
||||
DownloadHelper^ obj = gcnew DownloadHelper ();
|
||||
obj->m_url = httpUrl;
|
||||
obj->m_savePath = savePath;
|
||||
obj->cbProgress = onProgress;
|
||||
obj->cbComplete = onComplete;
|
||||
obj->cbError = onError;
|
||||
|
||||
Thread^ th = gcnew Thread (gcnew ThreadStart (obj, &DownloadHelper::Worker));
|
||||
th->IsBackground = true;
|
||||
th->Start ();
|
||||
}
|
||||
|
||||
private:
|
||||
void Worker ()
|
||||
{
|
||||
std::wstring url = MPStringToStdW (m_url);
|
||||
std::wstring outPath = MPStringToStdW (m_savePath);
|
||||
|
||||
HINTERNET hInternet = InternetOpenW (L"MyDownloader",
|
||||
INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
|
||||
|
||||
if (!hInternet)
|
||||
{
|
||||
ReportError (outPath, L"InternetOpenW Failed: " + GetLastErrorString ());
|
||||
return;
|
||||
}
|
||||
|
||||
HINTERNET hFile = InternetOpenUrlW (
|
||||
hInternet,
|
||||
url.c_str (),
|
||||
NULL,
|
||||
0,
|
||||
INTERNET_FLAG_RELOAD | INTERNET_FLAG_NO_CACHE_WRITE,
|
||||
0
|
||||
);
|
||||
|
||||
if (!hFile)
|
||||
{
|
||||
InternetCloseHandle (hInternet);
|
||||
ReportError (outPath, L"InternetOpenUrlW Failed: " + GetLastErrorString ());
|
||||
return;
|
||||
}
|
||||
|
||||
DWORD fileSize = 0;
|
||||
DWORD len = sizeof (fileSize);
|
||||
HttpQueryInfoW (hFile, HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER,
|
||||
&fileSize, &len, NULL);
|
||||
|
||||
HANDLE hOut = CreateFileW (outPath.c_str (), GENERIC_WRITE, 0,
|
||||
NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
|
||||
if (hOut == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
InternetCloseHandle (hFile);
|
||||
InternetCloseHandle (hInternet);
|
||||
ReportError (outPath, L"Cannot create output file: " + GetLastErrorString ());
|
||||
return;
|
||||
}
|
||||
|
||||
BYTE buffer [8192];
|
||||
DWORD bytesRead = 0;
|
||||
DWORD bytesWritten = 0;
|
||||
long long received = 0;
|
||||
|
||||
auto t0 = std::chrono::high_resolution_clock::now ();
|
||||
|
||||
while (InternetReadFile (hFile, buffer, sizeof (buffer), &bytesRead) && bytesRead > 0)
|
||||
{
|
||||
WriteFile (hOut, buffer, bytesRead, &bytesWritten, NULL);
|
||||
received += bytesRead;
|
||||
|
||||
// 计算速度
|
||||
auto t1 = std::chrono::high_resolution_clock::now ();
|
||||
double sec = std::chrono::duration<double> (t1 - t0).count ();
|
||||
long long speed = (long long)(received / (sec > 0 ? sec : 1));
|
||||
|
||||
ReportProgress (received, fileSize, speed);
|
||||
}
|
||||
|
||||
CloseHandle (hOut);
|
||||
InternetCloseHandle (hFile);
|
||||
InternetCloseHandle (hInternet);
|
||||
|
||||
ReportComplete (outPath, received);
|
||||
}
|
||||
|
||||
// ---------------- 回调组装 JSON ----------------
|
||||
|
||||
void ReportProgress (long long received, long long total, long long speed)
|
||||
{
|
||||
if (!cbProgress) return;
|
||||
|
||||
rapidjson::StringBuffer buf;
|
||||
rapidjson::Writer<rapidjson::StringBuffer> w (buf);
|
||||
|
||||
w.StartObject ();
|
||||
w.Key ("received"); w.Uint64 (received);
|
||||
w.Key ("total"); w.Uint64 (total);
|
||||
w.Key ("speed"); w.Uint64 (speed);
|
||||
w.Key ("progress"); w.Double (received / (double)total * 100);
|
||||
w.EndObject ();
|
||||
|
||||
CallJS (cbProgress, CStringToMPString (StringToWString (buf.GetString (), CP_UTF8)));
|
||||
}
|
||||
|
||||
void ReportComplete (const std::wstring& file, long long size)
|
||||
{
|
||||
if (!cbComplete) return;
|
||||
|
||||
rapidjson::StringBuffer buf;
|
||||
rapidjson::Writer<rapidjson::StringBuffer> w (buf);
|
||||
|
||||
w.StartObject ();
|
||||
w.Key ("file"); w.String (WStringToString (file, CP_UTF8).c_str ());
|
||||
w.Key ("status"); w.String ("ok");
|
||||
w.Key ("size"); w.Uint64 (size);
|
||||
w.EndObject ();
|
||||
|
||||
CallJS (cbComplete, CStringToMPString (StringToWString (buf.GetString (), CP_UTF8)));
|
||||
}
|
||||
|
||||
void ReportError (const std::wstring& file, const std::wstring &reason)
|
||||
{
|
||||
if (!cbError) return;
|
||||
|
||||
rapidjson::StringBuffer buf;
|
||||
rapidjson::Writer<rapidjson::StringBuffer> w (buf);
|
||||
|
||||
w.StartObject ();
|
||||
w.Key ("file"); w.String (WStringToString (file, CP_UTF8).c_str ());
|
||||
w.Key ("status"); w.String ("failed");
|
||||
w.Key ("reason"); w.String (WStringToString (reason, CP_UTF8).c_str ());
|
||||
w.EndObject ();
|
||||
|
||||
CallJS (cbError, CStringToMPString (StringToWString (buf.GetString (), CP_UTF8)));
|
||||
}
|
||||
|
||||
// ---------------- 调用 JS 回调 ----------------
|
||||
void CallJS (Object^ jsFunc, String^ arg)
|
||||
{
|
||||
if (!jsFunc) return;
|
||||
try
|
||||
{
|
||||
jsFunc->GetType ()->InvokeMember (
|
||||
"call",
|
||||
BindingFlags::InvokeMethod,
|
||||
nullptr,
|
||||
jsFunc,
|
||||
gcnew array<Object^>{ 1, arg }
|
||||
);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
// 失败可忽略
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
String^ m_url;
|
||||
String^ m_savePath;
|
||||
|
||||
Object^ cbProgress;
|
||||
Object^ cbComplete;
|
||||
Object^ cbError;
|
||||
};
|
||||
|
||||
using namespace System::Runtime::InteropServices;
|
||||
[ComVisible (true)]
|
||||
public ref class _I_Download
|
||||
{
|
||||
public:
|
||||
void WorkAsync (String ^httpurl, String ^saveFilePath, Object ^onComplete, Object ^onError, Object ^onProgress)
|
||||
{
|
||||
auto download = gcnew DownloadHelper ();
|
||||
download->DownloadFile (httpurl, saveFilePath, onProgress, onComplete, onError);
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user