mirror of
https://github.com/Open-Shell/Open-Shell-Menu.git
synced 2026-04-11 17:37:22 +10:00
Add support for silent OS upgrade task (#176)
`Open-Shell` needs to adjust itself after OS upgrade. It seems that `StartMenuHelper` registration is lost after such upgrade: http://www.classicshell.net/forum/viewtopic.php?f=7&t=8082#p34821 To fix this registration, administrator rights are required (means user interaction, UAC). While this is acceptable in consumer environment, it is typically not desired in business environment where users typically doesn't have administrator rights. This patch allows to run `Open-Shell` in silent upgrade mode that will: * check if OS version changed (otherwise end immediately) * perform OS upgrade tasks without any user interraction Such mode can be then used to create scheduled task that will run this silent upgrade check on every boot with system rights: `schtasks /Create /RU "NT AUTHORITY\SYSTEM" /SC ONSTART /TN "Open-Shell OS updgrade check" /TR "%ProgramFiles%\Open-Shell\StartMenu.exe -upgrade -silent"` #167
This commit is contained in:
@@ -274,6 +274,97 @@ public:
|
||||
//const wchar_t *g_AppId=L"Microsoft.BingWeather_8wekyb3d8bbwe!App";
|
||||
const wchar_t *g_AppId=L"microsoft.windowscommunicationsapps_8wekyb3d8bbwe!microsoft.windowslive.calendar";
|
||||
|
||||
static DWORD g_winVer = GetVersionEx(GetModuleHandle(L"user32.dll"));
|
||||
|
||||
bool WasOsUpgrade()
|
||||
{
|
||||
CRegKey regKey;
|
||||
if (regKey.Open(HKEY_LOCAL_MACHINE, L"Software\\OpenShell\\OpenShell", KEY_READ | KEY_WOW64_64KEY) == ERROR_SUCCESS)
|
||||
{
|
||||
DWORD ver;
|
||||
if (regKey.QueryDWORDValue(L"WinVersion", ver) == ERROR_SUCCESS)
|
||||
{
|
||||
if (ver < g_winVer)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// starts new instance of StartMenu.exe with "-upgrade" command line parameter
|
||||
// UAC dialog is shown to ensure it will run with administrator privileges
|
||||
void RunOsUpgradeTaskAsAdmin()
|
||||
{
|
||||
#ifdef _WIN64
|
||||
wchar_t path[_MAX_PATH] = L"%windir%\\System32\\StartMenuHelper64.dll";
|
||||
#else
|
||||
wchar_t path[_MAX_PATH] = L"%windir%\\System32\\StartMenuHelper32.dll";
|
||||
#endif
|
||||
DoEnvironmentSubst(path, _countof(path));
|
||||
if (GetFileAttributes(path) != INVALID_FILE_ATTRIBUTES)
|
||||
{
|
||||
GetModuleFileName(NULL, path, _countof(path));
|
||||
CoInitialize(NULL);
|
||||
ShellExecute(NULL, L"runas", path, L"-upgrade", NULL, SW_SHOWNORMAL);
|
||||
CoUninitialize();
|
||||
}
|
||||
}
|
||||
|
||||
DWORD PerformOsUpgradeTask(bool silent)
|
||||
{
|
||||
CRegKey regKey;
|
||||
DWORD error = regKey.Open(HKEY_LOCAL_MACHINE, L"Software\\OpenShell\\OpenShell", KEY_WRITE | KEY_WOW64_64KEY);
|
||||
const wchar_t *nl = error == ERROR_SUCCESS ? L"\r\n\r\n" : L"\r\n";
|
||||
if (error == ERROR_SUCCESS)
|
||||
{
|
||||
regKey.SetDWORDValue(L"WinVersion", g_winVer);
|
||||
|
||||
// run regsvr32 StartMenuHelper
|
||||
#ifdef _WIN64
|
||||
wchar_t cmdLine[_MAX_PATH] = L"regsvr32 /s \"%windir%\\System32\\StartMenuHelper64.dll\"";
|
||||
#else
|
||||
wchar_t cmdLine[_MAX_PATH] = L"regsvr32 /s \"%windir%\\System32\\StartMenuHelper32.dll\"";
|
||||
#endif
|
||||
DoEnvironmentSubst(cmdLine, _countof(cmdLine));
|
||||
|
||||
wchar_t exe[_MAX_PATH] = L"%windir%\\System32\\regsvr32.exe";
|
||||
DoEnvironmentSubst(exe, _countof(exe));
|
||||
|
||||
STARTUPINFO startupInfo = { sizeof(startupInfo) };
|
||||
PROCESS_INFORMATION processInfo;
|
||||
memset(&processInfo, 0, sizeof(processInfo));
|
||||
if (CreateProcess(exe, cmdLine, NULL, NULL, FALSE, 0, NULL, NULL, &startupInfo, &processInfo))
|
||||
{
|
||||
CloseHandle(processInfo.hThread);
|
||||
WaitForSingleObject(processInfo.hProcess, INFINITE);
|
||||
GetExitCodeProcess(processInfo.hProcess, &error);
|
||||
CloseHandle(processInfo.hProcess);
|
||||
}
|
||||
else
|
||||
{
|
||||
error = GetLastError();
|
||||
}
|
||||
}
|
||||
|
||||
if (!silent)
|
||||
{
|
||||
if (error)
|
||||
{
|
||||
wchar_t msg[1024];
|
||||
int len = Sprintf(msg, _countof(msg), L"%s%s", DllLoadStringEx(IDS_UPGRADE_ERROR), nl);
|
||||
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, error, 0, msg + len, _countof(msg) - len, NULL);
|
||||
MessageBox(NULL, msg, DllLoadStringEx(IDS_APP_TITLE), MB_OK | MB_ICONERROR);
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageBox(NULL, DllLoadStringEx(IDS_UPGRADE_SUCCESS), DllLoadStringEx(IDS_APP_TITLE), MB_OK | MB_ICONINFORMATION);
|
||||
}
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int WINAPI wWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpstrCmdLine, int nCmdShow )
|
||||
{
|
||||
/* CoInitialize(NULL);
|
||||
@@ -340,8 +431,8 @@ int WINAPI wWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpstrC
|
||||
ImportLegacyData();
|
||||
|
||||
DllLogToFile(STARTUP_LOG,L"StartMenu: start '%s'",lpstrCmdLine);
|
||||
DWORD winVer=GetVersionEx(GetModuleHandle(L"user32.dll"));
|
||||
if (wcsstr(lpstrCmdLine,L"-startup") || (wcsstr(lpstrCmdLine,L"-autorun") && HIWORD(winVer)<WIN_VER_WIN8))
|
||||
|
||||
if (wcsstr(lpstrCmdLine,L"-startup") || (wcsstr(lpstrCmdLine,L"-autorun") && HIWORD(g_winVer)<WIN_VER_WIN8))
|
||||
{
|
||||
WaitDllInitThread();
|
||||
if (!DllGetSettingBool(L"AutoStart"))
|
||||
@@ -360,31 +451,11 @@ int WINAPI wWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpstrC
|
||||
else if (wcsstr(lpstrCmdLine,L"-autorun")) // on Win8+
|
||||
{
|
||||
WaitDllInitThread();
|
||||
CRegKey regKey;
|
||||
if (regKey.Open(HKEY_LOCAL_MACHINE,L"Software\\OpenShell\\OpenShell",KEY_READ|KEY_WOW64_64KEY)==ERROR_SUCCESS)
|
||||
if (WasOsUpgrade())
|
||||
{
|
||||
DWORD ver1;
|
||||
if (regKey.QueryDWORDValue(L"WinVersion",ver1)==ERROR_SUCCESS)
|
||||
{
|
||||
if (ver1<winVer)
|
||||
{
|
||||
// this is an upgrade
|
||||
MessageBox(NULL,DllLoadStringEx(IDS_UPGRADE_WIN),DllLoadStringEx(IDS_APP_TITLE),MB_OK);
|
||||
#ifdef _WIN64
|
||||
wchar_t path[_MAX_PATH]=L"%windir%\\System32\\StartMenuHelper64.dll";
|
||||
#else
|
||||
wchar_t path[_MAX_PATH]=L"%windir%\\System32\\StartMenuHelper32.dll";
|
||||
#endif
|
||||
DoEnvironmentSubst(path,_countof(path));
|
||||
if (GetFileAttributes(path)!=INVALID_FILE_ATTRIBUTES)
|
||||
{
|
||||
GetModuleFileName(NULL,path,_countof(path));
|
||||
CoInitialize(NULL);
|
||||
ShellExecute(NULL,L"runas",path,L"-upgrade",NULL,SW_SHOWNORMAL);
|
||||
CoUninitialize();
|
||||
}
|
||||
}
|
||||
}
|
||||
// this is an upgrade
|
||||
MessageBox(NULL, DllLoadStringEx(IDS_UPGRADE_WIN), DllLoadStringEx(IDS_APP_TITLE), MB_OK);
|
||||
RunOsUpgradeTaskAsAdmin();
|
||||
}
|
||||
if (!DllGetSettingBool(L"AutoStart"))
|
||||
{
|
||||
@@ -399,49 +470,14 @@ int WINAPI wWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpstrC
|
||||
if (wcsstr(lpstrCmdLine,L"-upgrade"))
|
||||
{
|
||||
WaitDllInitThread();
|
||||
CRegKey regKey;
|
||||
DWORD error=regKey.Open(HKEY_LOCAL_MACHINE,L"Software\\OpenShell\\OpenShell",KEY_WRITE|KEY_WOW64_64KEY);
|
||||
const wchar_t *nl=error==ERROR_SUCCESS?L"\r\n\r\n":L"\r\n";
|
||||
if (error==ERROR_SUCCESS)
|
||||
{
|
||||
regKey.SetDWORDValue(L"WinVersion",winVer);
|
||||
|
||||
// run regsvr32 StartMenuHelper
|
||||
#ifdef _WIN64
|
||||
wchar_t cmdLine[_MAX_PATH]=L"regsvr32 /s \"%windir%\\System32\\StartMenuHelper64.dll\"";
|
||||
#else
|
||||
wchar_t cmdLine[_MAX_PATH]=L"regsvr32 /s \"%windir%\\System32\\StartMenuHelper32.dll\"";
|
||||
#endif
|
||||
DoEnvironmentSubst(cmdLine,_countof(cmdLine));
|
||||
|
||||
wchar_t exe[_MAX_PATH]=L"%windir%\\System32\\regsvr32.exe";
|
||||
DoEnvironmentSubst(exe,_countof(exe));
|
||||
|
||||
STARTUPINFO startupInfo={sizeof(startupInfo)};
|
||||
PROCESS_INFORMATION processInfo;
|
||||
memset(&processInfo,0,sizeof(processInfo));
|
||||
if (CreateProcess(exe,cmdLine,NULL,NULL,FALSE,0,NULL,NULL,&startupInfo,&processInfo))
|
||||
{
|
||||
CloseHandle(processInfo.hThread);
|
||||
WaitForSingleObject(processInfo.hProcess,INFINITE);
|
||||
GetExitCodeProcess(processInfo.hProcess,&error);
|
||||
CloseHandle(processInfo.hProcess);
|
||||
}
|
||||
else
|
||||
error=GetLastError();
|
||||
}
|
||||
if (error)
|
||||
if (WasOsUpgrade())
|
||||
{
|
||||
wchar_t msg[1024];
|
||||
int len=Sprintf(msg,_countof(msg),L"%s%s",DllLoadStringEx(IDS_UPGRADE_ERROR),nl);
|
||||
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,NULL,error,0,msg+len,_countof(msg)-len,NULL);
|
||||
MessageBox(NULL,msg,DllLoadStringEx(IDS_APP_TITLE),MB_OK|MB_ICONERROR);
|
||||
const bool silent = wcsstr(lpstrCmdLine, L"-silent") != nullptr;
|
||||
return PerformOsUpgradeTask(silent);
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageBox(NULL,DllLoadStringEx(IDS_UPGRADE_SUCCESS),DllLoadStringEx(IDS_APP_TITLE),MB_OK|MB_ICONINFORMATION);
|
||||
}
|
||||
return error;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const wchar_t *pCmd=wcsstr(lpstrCmdLine,L"-cmd ");
|
||||
|
||||
Reference in New Issue
Block a user