mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2026-08-06 03:42:56 +00:00
Stop Telegram before Windows uninstallation
This commit is contained in:
@@ -555,6 +555,7 @@ void Launcher::processArguments() {
|
||||
{ "-autostart" , KeyFormat::NoValues },
|
||||
{ "-fixprevious" , KeyFormat::NoValues },
|
||||
{ "-cleanup" , KeyFormat::NoValues },
|
||||
{ "-uninstall" , KeyFormat::NoValues },
|
||||
{ "-noupdate" , KeyFormat::NoValues },
|
||||
{ "-tosettings" , KeyFormat::NoValues },
|
||||
{ "-startintray" , KeyFormat::NoValues },
|
||||
@@ -603,6 +604,7 @@ void Launcher::processArguments() {
|
||||
gLaunchMode = parseResult.contains("-autostart") ? LaunchModeAutoStart
|
||||
: parseResult.contains("-fixprevious") ? LaunchModeFixPrevious
|
||||
: parseResult.contains("-cleanup") ? LaunchModeCleanup
|
||||
: parseResult.contains("-uninstall") ? LaunchModeUninstall
|
||||
: LaunchModeNormal;
|
||||
gNoStartUpdate = parseResult.contains("-noupdate");
|
||||
gStartToSettings = parseResult.contains("-tosettings");
|
||||
|
||||
@@ -49,6 +49,9 @@ base::options::toggle OptionDeadlockDetector({
|
||||
.description = "Check once every 30 seconds that main thread is still responsive.",
|
||||
});
|
||||
|
||||
constexpr auto kUninstallIpcTimeout = 10 * crl::time(1000);
|
||||
constexpr auto kUninstallQuitTimeout = 30 * crl::time(1000);
|
||||
|
||||
} // namespace
|
||||
|
||||
const char kOptionDeadlockDetector[] = "deadlock-detector";
|
||||
@@ -65,10 +68,6 @@ Sandbox::Sandbox(int &argc, char **argv)
|
||||
}
|
||||
|
||||
int Sandbox::start() {
|
||||
if (!Core::UpdaterDisabled()) {
|
||||
_updateChecker = std::make_unique<Core::UpdateChecker>();
|
||||
}
|
||||
|
||||
{
|
||||
const auto d = QFile::encodeName(QDir(cWorkingDir()).absolutePath());
|
||||
char h[33] = { 0 };
|
||||
@@ -76,6 +75,17 @@ int Sandbox::start() {
|
||||
_localServerName = Platform::SingleInstanceLocalServerName(h);
|
||||
}
|
||||
|
||||
if (cLaunchMode() == LaunchModeUninstall) {
|
||||
const auto result = stopRunningInstance();
|
||||
psCleanup();
|
||||
closeApplication();
|
||||
return result;
|
||||
}
|
||||
|
||||
if (!Core::UpdaterDisabled()) {
|
||||
_updateChecker = std::make_unique<Core::UpdateChecker>();
|
||||
}
|
||||
|
||||
{
|
||||
const auto d = QFile::encodeName(cExeDir() + cExeName());
|
||||
QByteArray h;
|
||||
@@ -171,6 +181,48 @@ int Sandbox::start() {
|
||||
return exec();
|
||||
}
|
||||
|
||||
int Sandbox::stopRunningInstance() {
|
||||
LOG(("Uninstall: connecting to %1...").arg(_localServerName));
|
||||
_localSocket.connectToServer(_localServerName);
|
||||
if (!_localSocket.waitForConnected(int(kUninstallIpcTimeout))) {
|
||||
if (_localSocket.error() == QLocalSocket::ServerNotFoundError) {
|
||||
LOG(("Uninstall: no running instance found."));
|
||||
return 0;
|
||||
}
|
||||
LOG(("Uninstall: connect error %1.").arg(_localSocket.error()));
|
||||
return 1;
|
||||
}
|
||||
_localSocket.write("CMD:quit;");
|
||||
if (!_localSocket.waitForBytesWritten(int(kUninstallIpcTimeout))) {
|
||||
LOG(("Uninstall: could not send the quit command."));
|
||||
return 1;
|
||||
}
|
||||
auto response = QByteArray();
|
||||
const auto deadline = crl::now() + kUninstallIpcTimeout;
|
||||
while (!response.contains(';')) {
|
||||
const auto timeout = deadline - crl::now();
|
||||
if (timeout <= 0 || !_localSocket.waitForReadyRead(int(timeout))) {
|
||||
LOG(("Uninstall: no response to the quit command."));
|
||||
return 1;
|
||||
}
|
||||
response.append(_localSocket.readAll());
|
||||
}
|
||||
const auto match = QRegularExpression(u"RES:(\\d+)_(\\d+);"_q).match(
|
||||
QString::fromLatin1(response));
|
||||
if (!match.hasMatch()) {
|
||||
LOG(("Uninstall: bad response to the quit command."));
|
||||
return 1;
|
||||
}
|
||||
const auto processId = match.capturedView(1).toULongLong();
|
||||
LOG(("Uninstall: waiting for process %1 to quit...").arg(processId));
|
||||
if (!Platform::WaitForProcessExit(processId, kUninstallQuitTimeout)) {
|
||||
LOG(("Uninstall: the process did not quit in time."));
|
||||
return 1;
|
||||
}
|
||||
LOG(("Uninstall: the running instance quit."));
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Sandbox::NotifySystemShuttingDown() {
|
||||
SystemShuttingDown = true;
|
||||
}
|
||||
|
||||
@@ -103,6 +103,7 @@ private:
|
||||
void socketWritten(qint64 bytes);
|
||||
void socketReading();
|
||||
void newInstanceConnected();
|
||||
int stopRunningInstance();
|
||||
|
||||
void readClients();
|
||||
void removeClients();
|
||||
|
||||
@@ -34,6 +34,10 @@ inline uint64 ActivationWindowId(not_null<QWidget*> window) {
|
||||
inline void ActivateOtherProcess(uint64 processId, uint64 windowId) {
|
||||
}
|
||||
|
||||
inline bool WaitForProcessExit(uint64 processId, crl::time timeout) {
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace Platform
|
||||
|
||||
inline void psCheckLocalSocket(const QString &serverName) {
|
||||
|
||||
@@ -36,6 +36,10 @@ inline uint64 ActivationWindowId(not_null<QWidget*> window) {
|
||||
inline void ActivateOtherProcess(uint64 processId, uint64 windowId) {
|
||||
}
|
||||
|
||||
inline bool WaitForProcessExit(uint64 processId, crl::time timeout) {
|
||||
return true;
|
||||
}
|
||||
|
||||
inline QString ApplicationIconName() {
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -540,6 +540,18 @@ void ActivateOtherProcess(uint64 processId, uint64 windowId) {
|
||||
}
|
||||
}
|
||||
|
||||
bool WaitForProcessExit(uint64 processId, crl::time timeout) {
|
||||
const auto process = ::OpenProcess(
|
||||
SYNCHRONIZE,
|
||||
FALSE,
|
||||
DWORD(processId));
|
||||
if (!process) {
|
||||
return (::GetLastError() == ERROR_INVALID_PARAMETER);
|
||||
}
|
||||
const auto guard = gsl::finally([&] { ::CloseHandle(process); });
|
||||
return (::WaitForSingleObject(process, DWORD(timeout)) == WAIT_OBJECT_0);
|
||||
}
|
||||
|
||||
} // namespace Platform
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -39,6 +39,8 @@ void SetWindowPriority(not_null<QWidget*> window, uint32 priority);
|
||||
// Activate window with windowId (if found) or the largest priority.
|
||||
void ActivateOtherProcess(uint64 processId, uint64 windowId);
|
||||
|
||||
[[nodiscard]] bool WaitForProcessExit(uint64 processId, crl::time timeout);
|
||||
|
||||
inline QString ApplicationIconName() {
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -44,6 +44,7 @@ enum LaunchMode {
|
||||
LaunchModeAutoStart,
|
||||
LaunchModeFixPrevious,
|
||||
LaunchModeCleanup,
|
||||
LaunchModeUninstall,
|
||||
};
|
||||
DeclareReadSetting(LaunchMode, LaunchMode);
|
||||
DeclareSetting(QString, WorkingDir);
|
||||
|
||||
@@ -113,7 +113,7 @@ var ResultCode: Integer;
|
||||
begin
|
||||
if CurUninstallStep = usUninstall then
|
||||
begin
|
||||
ShellExec('', ExpandConstant('{app}\{#MyAppExeName}'), '-cleanup', '', SW_SHOW, ewWaitUntilTerminated, ResultCode);
|
||||
Exec(ExpandConstant('{app}\{#MyAppExeName}'), '-uninstall', '', SW_HIDE, ewWaitUntilTerminated, ResultCode);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user