mirror of
https://github.com/koho/frpmgr.git
synced 2025-10-20 16:03:47 +08:00
Support reinstallation of the same version
This commit is contained in:
@ -243,9 +243,10 @@ __declspec(dllexport) UINT __stdcall EvaluateFrpServices(MSIHANDLE installer)
|
|||||||
record = MsiCreateRecord(5);
|
record = MsiCreateRecord(5);
|
||||||
if (!record)
|
if (!record)
|
||||||
continue;
|
continue;
|
||||||
|
BOOL start = services[i].ServiceStatusProcess.dwWin32ExitCode == ERROR_FAIL_NOACTION_REBOOT;
|
||||||
MsiRecordSetStringW(record, 1, identifier);
|
MsiRecordSetStringW(record, 1, identifier);
|
||||||
MsiRecordSetStringW(record, 2, services[i].lpServiceName);
|
MsiRecordSetStringW(record, 2, services[i].lpServiceName);
|
||||||
MsiRecordSetInteger(record, 3, msidbServiceControlEventStop | msidbServiceControlEventUninstallStop | (legacy == 0 ? msidbServiceControlEventDelete : 0) | msidbServiceControlEventUninstallDelete);
|
MsiRecordSetInteger(record, 3, (start ? msidbServiceControlEventStart : msidbServiceControlEventStop) | msidbServiceControlEventUninstallStop | (legacy == 0 ? msidbServiceControlEventDelete : 0) | msidbServiceControlEventUninstallDelete);
|
||||||
MsiRecordSetStringW(record, 4, L"frpmgr.exe");
|
MsiRecordSetStringW(record, 4, L"frpmgr.exe");
|
||||||
MsiRecordSetInteger(record, 5, 1);
|
MsiRecordSetInteger(record, 5, 1);
|
||||||
ret = MsiViewExecute(view, record);
|
ret = MsiViewExecute(view, record);
|
||||||
|
@ -43,8 +43,8 @@ if not defined TARGET_%ARCH% (
|
|||||||
|
|
||||||
:build_actions
|
:build_actions
|
||||||
%WINDRES% -DVERSION_ARRAY=%VERSION:.=,% -DVERSION_STR=%VERSION% -o %PLAT_DIR%\actions.res.obj -i actions\version.rc -O coff -c 65001 || exit /b 1
|
%WINDRES% -DVERSION_ARRAY=%VERSION:.=,% -DVERSION_STR=%VERSION% -o %PLAT_DIR%\actions.res.obj -i actions\version.rc -O coff -c 65001 || exit /b 1
|
||||||
set CFLAGS=-O3 -Wall -std=gnu11 -DWINVER=0x0601 -D_WIN32_WINNT=0x0601 -municode -DUNICODE -D_UNICODE -DNDEBUG
|
set CFLAGS=-O3 -Wall -std=gnu11 -DWINVER=0x0602 -D_WIN32_WINNT=0x0602 -municode -DUNICODE -D_UNICODE -DNDEBUG
|
||||||
set LDFLAGS=-shared -s -Wl,--kill-at -Wl,--major-os-version=6 -Wl,--minor-os-version=1 -Wl,--major-subsystem-version=6 -Wl,--minor-subsystem-version=1 -Wl,--tsaware -Wl,--dynamicbase -Wl,--nxcompat -Wl,--export-all-symbols
|
set LDFLAGS=-shared -s -Wl,--kill-at -Wl,--major-os-version=6 -Wl,--minor-os-version=2 -Wl,--major-subsystem-version=6 -Wl,--minor-subsystem-version=2 -Wl,--tsaware -Wl,--dynamicbase -Wl,--nxcompat -Wl,--export-all-symbols
|
||||||
set LDLIBS=-lmsi -lole32 -lshlwapi -lshell32 -ladvapi32
|
set LDLIBS=-lmsi -lole32 -lshlwapi -lshell32 -ladvapi32
|
||||||
%CC% %CFLAGS% %LDFLAGS% -o %PLAT_DIR%\actions.dll actions\actions.c %PLAT_DIR%\actions.res.obj %LDLIBS% || exit /b 1
|
%CC% %CFLAGS% %LDFLAGS% -o %PLAT_DIR%\actions.dll actions\actions.c %PLAT_DIR%\actions.res.obj %LDLIBS% || exit /b 1
|
||||||
goto :eof
|
goto :eof
|
||||||
@ -83,9 +83,9 @@ if not defined TARGET_%ARCH% (
|
|||||||
echo ERROR: UpgradeCode was not found.
|
echo ERROR: UpgradeCode was not found.
|
||||||
exit /b 1
|
exit /b 1
|
||||||
)
|
)
|
||||||
set CFLAGS=-O3 -Wall -std=gnu11 -DWINVER=0x0601 -D_WIN32_WINNT=0x0601 -municode -DUNICODE -D_UNICODE -DNDEBUG -DUPGRADE_CODE=L\"{%UPGRADE_CODE%}\" -DVERSION=L\"%VERSION%\"
|
set CFLAGS=-O3 -Wall -std=gnu11 -DWINVER=0x0602 -D_WIN32_WINNT=0x0602 -municode -DUNICODE -D_UNICODE -DNDEBUG -DUPGRADE_CODE=L\"{%UPGRADE_CODE%}\" -DVERSION=L\"%VERSION%\"
|
||||||
set LDFLAGS=-s -Wl,--major-os-version=6 -Wl,--minor-os-version=1 -Wl,--major-subsystem-version=6 -Wl,--minor-subsystem-version=1 -Wl,--tsaware -Wl,--dynamicbase -Wl,--nxcompat -mwindows
|
set LDFLAGS=-s -Wl,--major-os-version=6 -Wl,--minor-os-version=2 -Wl,--major-subsystem-version=6 -Wl,--minor-subsystem-version=2 -Wl,--tsaware -Wl,--dynamicbase -Wl,--nxcompat -mwindows
|
||||||
set LDLIBS=-lmsi -lole32 -lshlwapi -ladvapi32 -luser32
|
set LDLIBS=-lmsi -lole32 -lshlwapi -ladvapi32 -luser32 -lcomctl32
|
||||||
%CC% %CFLAGS% %LDFLAGS% -o %PLAT_DIR%\setup.exe setup\setup.c %PLAT_DIR%\setup.res.obj %LDLIBS% || exit /b 1
|
%CC% %CFLAGS% %LDFLAGS% -o %PLAT_DIR%\setup.exe setup\setup.c %PLAT_DIR%\setup.res.obj %LDLIBS% || exit /b 1
|
||||||
goto :eof
|
goto :eof
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@
|
|||||||
Detect previous install folder if it's a upgrade
|
Detect previous install folder if it's a upgrade
|
||||||
-->
|
-->
|
||||||
<SetProperty Id="INSTALLFOLDER" Value="[PREVINSTALLFOLDER]" After="AppSearch" Sequence="first">
|
<SetProperty Id="INSTALLFOLDER" Value="[PREVINSTALLFOLDER]" After="AppSearch" Sequence="first">
|
||||||
WIX_UPGRADE_DETECTED
|
PREVINSTALLFOLDER
|
||||||
</SetProperty>
|
</SetProperty>
|
||||||
|
|
||||||
<Property Id="WIXUI_INSTALLDIR" Value="INSTALLFOLDER" />
|
<Property Id="WIXUI_INSTALLDIR" Value="INSTALLFOLDER" />
|
||||||
@ -125,7 +125,7 @@
|
|||||||
-->
|
-->
|
||||||
<CustomAction Id="EvaluateFrpServices" BinaryKey="actions.dll" DllEntry="EvaluateFrpServices" />
|
<CustomAction Id="EvaluateFrpServices" BinaryKey="actions.dll" DllEntry="EvaluateFrpServices" />
|
||||||
<InstallExecuteSequence>
|
<InstallExecuteSequence>
|
||||||
<Custom Action="EvaluateFrpServices" After="InstallInitialize">NOT (UPGRADINGPRODUCTCODE AND (REMOVE="ALL"))</Custom>
|
<Custom Action="EvaluateFrpServices" After="InstallInitialize">NOT ((UPGRADINGPRODUCTCODE OR SAVESTATE) AND (REMOVE="ALL"))</Custom>
|
||||||
</InstallExecuteSequence>
|
</InstallExecuteSequence>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
@ -143,7 +143,7 @@
|
|||||||
<CustomAction Id="RemoveFrpFiles" BinaryKey="actions.dll" DllEntry="RemoveFrpFiles" Impersonate="no" Execute="deferred" />
|
<CustomAction Id="RemoveFrpFiles" BinaryKey="actions.dll" DllEntry="RemoveFrpFiles" Impersonate="no" Execute="deferred" />
|
||||||
<InstallExecuteSequence>
|
<InstallExecuteSequence>
|
||||||
<Custom Action="RemoveFrpFiles.SetProperty" After="DeleteServices" />
|
<Custom Action="RemoveFrpFiles.SetProperty" After="DeleteServices" />
|
||||||
<Custom Action="RemoveFrpFiles" After="RemoveFrpFiles.SetProperty">(NOT UPGRADINGPRODUCTCODE) AND (REMOVE="ALL")</Custom>
|
<Custom Action="RemoveFrpFiles" After="RemoveFrpFiles.SetProperty">(NOT UPGRADINGPRODUCTCODE) AND (NOT SAVESTATE) AND (REMOVE="ALL")</Custom>
|
||||||
</InstallExecuteSequence>
|
</InstallExecuteSequence>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
|
@ -7,4 +7,10 @@
|
|||||||
#define IDC_LANG_COMBO 1000
|
#define IDC_LANG_COMBO 1000
|
||||||
#define IDC_STATIC -1
|
#define IDC_STATIC -1
|
||||||
|
|
||||||
|
#define IDS_TITLE 200
|
||||||
|
#define IDS_MANAGEMENT 201
|
||||||
|
#define IDS_OPERATION 202
|
||||||
|
#define IDS_REINSTALL 203
|
||||||
|
#define IDS_UNINSTALL 204
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -133,3 +133,63 @@ LANGUAGE LANG_SPANISH, SUBLANG_SPANISH_MODERN
|
|||||||
LANG_DIALOG_TEMPLATE(
|
LANG_DIALOG_TEMPLATE(
|
||||||
TITLE_ES_ES, "Seleccione el idioma para la instalación entre las opciones siguientes.", "Aceptar", "Cancelar"
|
TITLE_ES_ES, "Seleccione el idioma para la instalación entre las opciones siguientes.", "Aceptar", "Cancelar"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT
|
||||||
|
STRINGTABLE
|
||||||
|
BEGIN
|
||||||
|
IDS_TITLE TITLE_EN_US
|
||||||
|
IDS_MANAGEMENT "Manage Current Product"
|
||||||
|
IDS_OPERATION "Select the action you want to perform."
|
||||||
|
IDS_REINSTALL "Reinstall with ""%1""%rThis operation requires suspending the running services.\0 "
|
||||||
|
IDS_UNINSTALL "Uninstall"
|
||||||
|
END
|
||||||
|
|
||||||
|
LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED
|
||||||
|
STRINGTABLE
|
||||||
|
BEGIN
|
||||||
|
IDS_TITLE TITLE_ZH_CN
|
||||||
|
IDS_MANAGEMENT "管理当前产品"
|
||||||
|
IDS_OPERATION "选择希望执行的操作。"
|
||||||
|
IDS_REINSTALL "以 “%1” 重新安装%r此操作需要暂停正在运行的服务。\0 "
|
||||||
|
IDS_UNINSTALL "卸载"
|
||||||
|
END
|
||||||
|
|
||||||
|
LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL
|
||||||
|
STRINGTABLE
|
||||||
|
BEGIN
|
||||||
|
IDS_TITLE TITLE_ZH_TW
|
||||||
|
IDS_MANAGEMENT "管理現行產品"
|
||||||
|
IDS_OPERATION "選取您要執行的作業。"
|
||||||
|
IDS_REINSTALL "以「%1」重新安裝%r此操作需要暫停正在運作的服務。\0 "
|
||||||
|
IDS_UNINSTALL "移除"
|
||||||
|
END
|
||||||
|
|
||||||
|
LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT
|
||||||
|
STRINGTABLE
|
||||||
|
BEGIN
|
||||||
|
IDS_TITLE TITLE_JA_JP
|
||||||
|
IDS_MANAGEMENT "現在のインストールの管理"
|
||||||
|
IDS_OPERATION "実行するアクションを選択します。"
|
||||||
|
IDS_REINSTALL "「%1」で再インストールします%rこの操作では実行中のサービスを一時停止する必要があります。\0 "
|
||||||
|
IDS_UNINSTALL "アンインストール"
|
||||||
|
END
|
||||||
|
|
||||||
|
LANGUAGE LANG_KOREAN, SUBLANG_DEFAULT
|
||||||
|
STRINGTABLE
|
||||||
|
BEGIN
|
||||||
|
IDS_TITLE TITLE_KO_KR
|
||||||
|
IDS_MANAGEMENT "현재 제품 관리"
|
||||||
|
IDS_OPERATION "수행하고자 하는 작업을 선택하세요."
|
||||||
|
IDS_REINSTALL """%1""로 다시 설치%r이 작업을 수행하려면 실행 중인 서비스를 중단해야 합니다.\0 "
|
||||||
|
IDS_UNINSTALL "제거하다"
|
||||||
|
END
|
||||||
|
|
||||||
|
LANGUAGE LANG_SPANISH, SUBLANG_SPANISH_MODERN
|
||||||
|
STRINGTABLE
|
||||||
|
BEGIN
|
||||||
|
IDS_TITLE TITLE_ES_ES
|
||||||
|
IDS_MANAGEMENT "Administrar el producto actual"
|
||||||
|
IDS_OPERATION "Seleccione la acción que desea realizar."
|
||||||
|
IDS_REINSTALL "Reinstalar con ""%1""%rEsta operación requiere suspender los servicios en ejecución.\0 "
|
||||||
|
IDS_UNINSTALL "Desinstalar"
|
||||||
|
END
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#include <msi.h>
|
#include <msi.h>
|
||||||
#include <shlwapi.h>
|
#include <shlwapi.h>
|
||||||
#include <sddl.h>
|
#include <sddl.h>
|
||||||
|
#include <commctrl.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include "resource.h"
|
#include "resource.h"
|
||||||
|
|
||||||
@ -42,6 +43,42 @@ static INT MatchLanguageCode(LPWSTR langCode)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static LPWSTR FormatString(HINSTANCE hInstance, UINT uID, ...)
|
||||||
|
{
|
||||||
|
LPWSTR pBuffer = NULL, pFormat;
|
||||||
|
int n = LoadStringW(hInstance, uID, (LPWSTR)&pFormat, 0);
|
||||||
|
if (n < 2 || pFormat[n - 2] != L'\0')
|
||||||
|
return NULL;
|
||||||
|
va_list args = NULL;
|
||||||
|
va_start(args, uID);
|
||||||
|
FormatMessageW(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER, pFormat,
|
||||||
|
0, 0, (LPWSTR)&pBuffer, 0, &args);
|
||||||
|
va_end(args);
|
||||||
|
return pBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HANDLE CreateReinstallEvent(LPWSTR path, DWORD pathLen)
|
||||||
|
{
|
||||||
|
if (!PathAppendW(path, L"frpmgr.exe"))
|
||||||
|
return NULL;
|
||||||
|
HANDLE hFile = CreateFileW(path, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||||
|
path[pathLen] = L'\0';
|
||||||
|
if (hFile == INVALID_HANDLE_VALUE)
|
||||||
|
return NULL;
|
||||||
|
FILE_ID_INFO fileId;
|
||||||
|
BOOL ret = GetFileInformationByHandleEx(hFile, FileIdInfo, &fileId, sizeof(fileId));
|
||||||
|
CloseHandle(hFile);
|
||||||
|
if (!ret)
|
||||||
|
return NULL;
|
||||||
|
CHAR name[_countof("Global\\") + sizeof(fileId) * 2];
|
||||||
|
int n = sprintf_s(name, _countof(name), "Global\\%llx", fileId.VolumeSerialNumber);
|
||||||
|
if (n < 0)
|
||||||
|
return NULL;
|
||||||
|
for (size_t i = 0; i < sizeof(fileId.FileId); i++)
|
||||||
|
n += sprintf_s(&name[n], _countof(name) - n, "%02x", fileId.FileId.Identifier[i]);
|
||||||
|
return CreateEventA(NULL, TRUE, FALSE, name);
|
||||||
|
}
|
||||||
|
|
||||||
static INT GetApplicationLanguage(LPWSTR path, DWORD pathLen)
|
static INT GetApplicationLanguage(LPWSTR path, DWORD pathLen)
|
||||||
{
|
{
|
||||||
if (!PathAppendW(path, L"lang.config"))
|
if (!PathAppendW(path, L"lang.config"))
|
||||||
@ -144,7 +181,7 @@ INT_PTR CALLBACK LanguageDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM l
|
|||||||
return (INT_PTR)FALSE;
|
return (INT_PTR)FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cleanup(void)
|
static int Cleanup(void)
|
||||||
{
|
{
|
||||||
if (msiFile != INVALID_HANDLE_VALUE)
|
if (msiFile != INVALID_HANDLE_VALUE)
|
||||||
{
|
{
|
||||||
@ -159,13 +196,10 @@ static int cleanup(void)
|
|||||||
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nShowCmd)
|
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nShowCmd)
|
||||||
{
|
{
|
||||||
INT langIndex = -1;
|
INT langIndex = -1;
|
||||||
BOOL installed = FALSE, showDlg = TRUE;
|
BOOL installed = FALSE, reinstall = FALSE, showDlg = TRUE;
|
||||||
Product product = {
|
Product product = {
|
||||||
.path = { 0 },
|
|
||||||
.pathLen = _countof(product.path),
|
.pathLen = _countof(product.path),
|
||||||
.lang = { 0 },
|
|
||||||
.langLen = _countof(product.lang),
|
.langLen = _countof(product.lang),
|
||||||
.version = { 0 },
|
|
||||||
.versionLen = _countof(product.version)
|
.versionLen = _countof(product.version)
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -224,6 +258,40 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLi
|
|||||||
if (lang == NULL)
|
if (lang == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
if (installed)
|
||||||
|
{
|
||||||
|
LPWSTR pszButtonText = FormatString(hInstance, IDS_REINSTALL, lang->name);
|
||||||
|
const TASKDIALOG_BUTTON buttons[] = {
|
||||||
|
{ IDYES, pszButtonText },
|
||||||
|
{ IDNO, MAKEINTRESOURCE(IDS_UNINSTALL) }
|
||||||
|
};
|
||||||
|
TASKDIALOGCONFIG config = {
|
||||||
|
.cbSize = sizeof(config),
|
||||||
|
.hInstance = hInstance,
|
||||||
|
.dwFlags = TDF_USE_COMMAND_LINKS,
|
||||||
|
.dwCommonButtons = TDCBF_CLOSE_BUTTON,
|
||||||
|
.pszWindowTitle = MAKEINTRESOURCE(IDS_TITLE),
|
||||||
|
.pszMainIcon = MAKEINTRESOURCE(IDI_ICON),
|
||||||
|
.pszMainInstruction = MAKEINTRESOURCE(IDS_MANAGEMENT),
|
||||||
|
.pszContent = MAKEINTRESOURCE(IDS_OPERATION),
|
||||||
|
.cButtons = ARRAYSIZE(buttons),
|
||||||
|
.pButtons = buttons,
|
||||||
|
.nDefaultButton = IDYES
|
||||||
|
};
|
||||||
|
LPWSTR newLine;
|
||||||
|
if (pszButtonText && (newLine = wcschr(pszButtonText, L'\r')))
|
||||||
|
*newLine = L'\n';
|
||||||
|
int nButtonPressed = 0;
|
||||||
|
HRESULT ret = TaskDialogIndirect(&config, &nButtonPressed, NULL, NULL);
|
||||||
|
if (pszButtonText)
|
||||||
|
LocalFree((HLOCAL)pszButtonText);
|
||||||
|
if (ret != S_OK)
|
||||||
|
return 1;
|
||||||
|
if (nButtonPressed == IDCLOSE)
|
||||||
|
return 0;
|
||||||
|
reinstall = nButtonPressed == IDYES;
|
||||||
|
}
|
||||||
|
|
||||||
if (!GetWindowsDirectoryW(msiPath, _countof(msiPath)) || !PathAppendW(msiPath, L"Temp"))
|
if (!GetWindowsDirectoryW(msiPath, _countof(msiPath)) || !PathAppendW(msiPath, L"Temp"))
|
||||||
return 1;
|
return 1;
|
||||||
GUID guid;
|
GUID guid;
|
||||||
@ -254,7 +322,7 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLi
|
|||||||
LocalFree(sa.lpSecurityDescriptor);
|
LocalFree(sa.lpSecurityDescriptor);
|
||||||
if (msiFile == INVALID_HANDLE_VALUE)
|
if (msiFile == INVALID_HANDLE_VALUE)
|
||||||
return 1;
|
return 1;
|
||||||
_onexit(cleanup);
|
_onexit(Cleanup);
|
||||||
DWORD bytesWritten;
|
DWORD bytesWritten;
|
||||||
BOOL ok = WriteFile(msiFile, pResData, resSize, &bytesWritten, NULL);
|
BOOL ok = WriteFile(msiFile, pResData, resSize, &bytesWritten, NULL);
|
||||||
CloseHandle(msiFile);
|
CloseHandle(msiFile);
|
||||||
@ -262,7 +330,21 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLi
|
|||||||
if (!ok || bytesWritten != resSize)
|
if (!ok || bytesWritten != resSize)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
|
if (installed)
|
||||||
|
{
|
||||||
|
if (!reinstall)
|
||||||
|
return MsiInstallProductW(msiPath, L"REMOVE=ALL");
|
||||||
|
HANDLE hEvent = CreateReinstallEvent(product.path, product.pathLen);
|
||||||
|
UINT ret = MsiInstallProductW(msiPath, L"REMOVE=ALL MSIDISABLERMRESTART=1 SAVESTATE=1");
|
||||||
|
if (hEvent)
|
||||||
|
CloseHandle(hEvent);
|
||||||
|
if (ret != ERROR_SUCCESS)
|
||||||
|
return 1;
|
||||||
|
MsiSetInternalUI(INSTALLUILEVEL_BASIC | INSTALLUILEVEL_ENDDIALOG, NULL);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
|
||||||
|
|
||||||
#define CMD_FORMAT L"ProductLanguage=%s PREVINSTALLFOLDER=\"%s\""
|
#define CMD_FORMAT L"ProductLanguage=%s PREVINSTALLFOLDER=\"%s\""
|
||||||
WCHAR cmd[_countof(CMD_FORMAT) + _countof(product.path)];
|
WCHAR cmd[_countof(CMD_FORMAT) + _countof(product.path)];
|
||||||
if (swprintf_s(cmd, _countof(cmd), CMD_FORMAT, lang->id, product.path) < 0)
|
if (swprintf_s(cmd, _countof(cmd), CMD_FORMAT, lang->id, product.path) < 0)
|
||||||
|
@ -5,9 +5,12 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/Microsoft/go-winio"
|
||||||
"github.com/fatedier/frp/pkg/util/log"
|
"github.com/fatedier/frp/pkg/util/log"
|
||||||
|
"golang.org/x/sys/windows"
|
||||||
"golang.org/x/sys/windows/svc"
|
"golang.org/x/sys/windows/svc"
|
||||||
|
|
||||||
"github.com/koho/frpmgr/pkg/config"
|
"github.com/koho/frpmgr/pkg/config"
|
||||||
@ -82,6 +85,9 @@ func (service *frpService) Execute(args []string, r <-chan svc.ChangeRequest, ch
|
|||||||
switch c.Cmd {
|
switch c.Cmd {
|
||||||
case svc.Stop, svc.Shutdown:
|
case svc.Stop, svc.Shutdown:
|
||||||
svr.Stop(false)
|
svr.Stop(false)
|
||||||
|
if code := shutdownReason(path); code > 0 {
|
||||||
|
return false, code
|
||||||
|
}
|
||||||
return
|
return
|
||||||
case svc.ParamChange:
|
case svc.ParamChange:
|
||||||
// Reload service
|
// Reload service
|
||||||
@ -125,3 +131,24 @@ func ReloadService(configPath string) error {
|
|||||||
_, err = service.Control(svc.ParamChange)
|
_, err = service.Control(svc.ParamChange)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func shutdownReason(path string) uint32 {
|
||||||
|
f, err := os.Open(path)
|
||||||
|
if err != nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
fileID, err := winio.GetFileID(f)
|
||||||
|
f.Close()
|
||||||
|
if err != nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
name, err := syscall.UTF16PtrFromString(fmt.Sprintf("Global\\%x%x", fileID.VolumeSerialNumber, fileID.FileID))
|
||||||
|
if err != nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
if h, err := windows.OpenEvent(windows.READ_CONTROL, false, name); err == nil {
|
||||||
|
windows.CloseHandle(h)
|
||||||
|
return uint32(windows.ERROR_FAIL_NOACTION_REBOOT)
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user