Added /LOADTHEME switch to SkinInstaller.exe. Usage:

"SkinInstaller.exe" /LOADTHEME themeName
This commit is contained in:
Birunthan Mohanathas 2011-11-27 14:14:39 +00:00
parent caa1ef893f
commit abb1831092
5 changed files with 169 additions and 77 deletions

View File

@ -29,21 +29,13 @@ GLOBALDATA g_Data;
*/ */
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow) int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow)
{ {
if (wcscmp(lpCmdLine, L"/BACKUP") != 0) bool loadTheme = (wcsncmp(lpCmdLine, L"/LOADTHEME ", 11) == 0);
if (wcscmp(lpCmdLine, L"/BACKUP") != 0 && !loadTheme)
{ {
// Temporary solution until Rainstaller rewrite // Temporary solution until Rainstaller rewrite
return Rainstaller(hInstance, hPrevInstance, lpCmdLine, nCmdShow); return Rainstaller(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
} }
// Check whether Rainstaller.exe is already running and bring it to front if so
HANDLE hMutex;
if (IsRunning(L"RmSkinInstallerMutex", &hMutex))
{
HWND hwnd = FindWindow(L"#32770", L"Backup Rainmeter");
SetForegroundWindow(hwnd);
return 0;
}
// Avoid loading a dll from current directory // Avoid loading a dll from current directory
SetDllDirectory(L""); SetDllDirectory(L"");
@ -63,6 +55,7 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLi
// Find the settings file and read skins path off it // Find the settings file and read skins path off it
if (_waccess(buffer, 0) == 0) if (_waccess(buffer, 0) == 0)
{ {
g_Data.iniFile = buffer;
if (GetPrivateProfileString(L"Rainmeter", L"SkinPath", L"", buffer, MAX_LINE_LENGTH, buffer) > 0) if (GetPrivateProfileString(L"Rainmeter", L"SkinPath", L"", buffer, MAX_LINE_LENGTH, buffer) > 0)
{ {
g_Data.skinsPath = buffer; g_Data.skinsPath = buffer;
@ -79,6 +72,7 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLi
wcscat(buffer, L"\\Rainmeter\\"); wcscat(buffer, L"\\Rainmeter\\");
g_Data.settingsPath = buffer; g_Data.settingsPath = buffer;
wcscat(buffer, L"Rainmeter.ini"); wcscat(buffer, L"Rainmeter.ini");
g_Data.iniFile = buffer;
if (SUCCEEDED(hr) && _waccess(buffer, 0) == 0) if (SUCCEEDED(hr) && _waccess(buffer, 0) == 0)
{ {
if (GetPrivateProfileString(L"Rainmeter", L"SkinPath", L"", buffer, MAX_LINE_LENGTH, buffer) > 0) if (GetPrivateProfileString(L"Rainmeter", L"SkinPath", L"", buffer, MAX_LINE_LENGTH, buffer) > 0)
@ -100,16 +94,120 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLi
} }
} }
if (loadTheme)
{
// Skip "/LOADTHEME "
lpCmdLine += 11;
if (CloseRainmeterIfActive() && *lpCmdLine)
{
LoadTheme(lpCmdLine);
std::wstring file = g_Data.programPath + L"Rainmeter.exe";
SHELLEXECUTEINFO sei = {0};
sei.cbSize = sizeof(SHELLEXECUTEINFO);
sei.fMask = SEE_MASK_UNICODE;
sei.lpFile = file.c_str();
sei.nShow = SW_SHOWNORMAL;
ShellExecuteEx(&sei);
}
return 0;
}
// Check whether Rainstaller.exe is already running and bring it to front if so
HANDLE hMutex;
if (IsRunning(L"RmSkinInstallerMutex", &hMutex))
{
HWND hwnd = FindWindow(L"#32770", L"Backup Rainmeter");
SetForegroundWindow(hwnd);
return 0;
}
CDialogBackup::Create(hInstance, lpCmdLine); CDialogBackup::Create(hInstance, lpCmdLine);
ReleaseMutex(hMutex); ReleaseMutex(hMutex);
return 0; return 0;
} }
/* bool CloseRainmeterIfActive()
** Checks whether Rainstaller.exe is running (modified from Application.cpp) {
*/ // Close Rainmeter.exe
HWND hwnd = FindWindow(L"DummyRainWClass", L"Rainmeter control window");
if (hwnd)
{
DWORD pID, exitCode;
GetWindowThreadProcessId(hwnd, &pID);
HANDLE hProcess = OpenProcess(PROCESS_TERMINATE | SYNCHRONIZE, FALSE, pID);
PostMessage(hwnd, WM_DESTROY, 0, 0);
// Wait up to 5 seconds for Rainmeter to close
WaitForSingleObject(hProcess, 5000);
GetExitCodeProcess(hProcess, &exitCode);
CloseHandle(hProcess);
if (exitCode == STILL_ACTIVE)
{
return false;
}
}
return true;
}
void LoadTheme(const WCHAR* name)
{
std::wstring backup = g_Data.settingsPath + L"Themes\\Backup";
CreateDirectory(backup.c_str(), NULL);
backup += L"\\Rainmeter.thm";
// Make a copy of current Rainmeter.ini
CopyFiles(g_Data.iniFile, backup);
// Replace Rainmeter.ini with theme
std::wstring theme = g_Data.settingsPath + L"Themes\\";
theme += name;
std::wstring wallpaper = theme + L"\\RainThemes.bmp";
theme += L"\\Rainmeter.thm";
CopyFiles(theme, g_Data.iniFile);
PreserveSetting(backup, L"SkinPath");
PreserveSetting(backup, L"ConfigEditor");
PreserveSetting(backup, L"LogViewer");
PreserveSetting(backup, L"Logging");
PreserveSetting(backup, L"DisableVersionCheck");
PreserveSetting(backup, L"Language");
PreserveSetting(backup, L"NormalStayDesktop");
PreserveSetting(backup, L"TrayExecuteL", false);
PreserveSetting(backup, L"TrayExecuteM", false);
PreserveSetting(backup, L"TrayExecuteR", false);
PreserveSetting(backup, L"TrayExecuteDM", false);
PreserveSetting(backup, L"TrayExecuteDR", false);
// Set wallpaper if it exists
if (_waccess(wallpaper.c_str(), 0) != -1)
{
SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, (void*)wallpaper.c_str(), SPIF_UPDATEINIFILE);
}
}
void PreserveSetting(const std::wstring& from, LPCTSTR key, bool replace)
{
WCHAR* buffer = new WCHAR[MAX_LINE_LENGTH];
if ((replace || GetPrivateProfileString(L"Rainmeter", key, L"", buffer, 4, g_Data.iniFile.c_str()) == 0) &&
GetPrivateProfileString(L"Rainmeter", key, L"", buffer, MAX_LINE_LENGTH, from.c_str()) > 0)
{
WritePrivateProfileString(L"Rainmeter", key, buffer, g_Data.iniFile.c_str());
}
delete buffer;
}
// -----------------------------------------------------------------------------------------------
// Stolen functions from Rainmeter Litestep.cpp, System.cpp, and Application.cpp
// -----------------------------------------------------------------------------------------------
bool IsRunning(const WCHAR* name, HANDLE* hMutex) bool IsRunning(const WCHAR* name, HANDLE* hMutex)
{ {
// Create mutex // Create mutex
@ -126,6 +224,26 @@ bool IsRunning(const WCHAR* name, HANDLE* hMutex)
} }
} }
bool CopyFiles(const std::wstring& strFrom, const std::wstring& strTo, bool bMove)
{
std::wstring tmpFrom(strFrom), tmpTo(strTo);
// The strings must end with double nul
tmpFrom.append(1, L'\0');
tmpTo.append(1, L'\0');
SHFILEOPSTRUCT fo =
{
NULL,
bMove ? FO_MOVE : FO_COPY,
tmpFrom.c_str(),
tmpTo.c_str(),
FOF_NO_UI | FOF_NOCONFIRMATION | FOF_ALLOWUNDO
};
return SHFileOperation(&fo) != 0;
}
std::string ConvertToAscii(LPCTSTR str) std::string ConvertToAscii(LPCTSTR str)
{ {
std::string szAscii; std::string szAscii;

View File

@ -41,10 +41,15 @@ struct GLOBALDATA
std::wstring programPath; std::wstring programPath;
std::wstring settingsPath; std::wstring settingsPath;
std::wstring skinsPath; std::wstring skinsPath;
std::wstring iniFile;
}; };
bool IsRunning(const WCHAR* name, HANDLE* hMutex); bool CloseRainmeterIfActive();
void LoadTheme(const WCHAR* name);
void PreserveSetting(const std::wstring& from, LPCTSTR key, bool replace = true);
bool IsRunning(const WCHAR* name, HANDLE* hMutex);
bool CopyFiles(const std::wstring& strFrom, const std::wstring& strTo, bool bMove = false);
std::string ConvertToAscii(LPCTSTR str); std::string ConvertToAscii(LPCTSTR str);
std::wstring ConvertToWide(LPCSTR str); std::wstring ConvertToWide(LPCSTR str);

View File

@ -144,27 +144,34 @@ INT_PTR CDialogBackup::OnCommand(WPARAM wParam, LPARAM lParam)
void CDialogBackup::StartBackup() void CDialogBackup::StartBackup()
{ {
HWND item = GetDlgItem(m_Window, IDC_BACKUP_BACKUP_BUTTON); if (!CloseRainmeterIfActive())
EnableWindow(item, FALSE);
item = GetDlgItem(m_TabBackup.GetWindow(), IDC_BACKUP_FILE_TEXT);
ShowWindow(item, SW_HIDE);
item = GetDlgItem(m_TabBackup.GetWindow(), IDC_BACKUP_BROWSE_BUTTON);
ShowWindow(item, SW_HIDE);
item = GetDlgItem(m_TabBackup.GetWindow(), IDC_BACKUP_INPROGRESS_TEXT);
ShowWindow(item, SW_SHOWNORMAL);
item = GetDlgItem(m_TabBackup.GetWindow(), IDC_BACKUP_PROGRESS);
ShowWindow(item, SW_SHOWNORMAL);
SendMessage(item, PBM_SETMARQUEE, (WPARAM)TRUE, 0);
m_ThreadHandle = (HANDLE)_beginthreadex(NULL, 0, BackupThreadProc, this, 0, NULL);
if (!m_ThreadHandle)
{ {
MessageBox(m_Window, L"Unable to start backup.", L"Backup Rainmeter", MB_ERROR); MessageBox(m_Window, L"Unable to close Rainmeter.", L"Backup Rainmeter", MB_ERROR);
EndDialog(m_Window, 0); }
else
{
HWND item = GetDlgItem(m_Window, IDC_BACKUP_BACKUP_BUTTON);
EnableWindow(item, FALSE);
item = GetDlgItem(m_TabBackup.GetWindow(), IDC_BACKUP_FILE_TEXT);
ShowWindow(item, SW_HIDE);
item = GetDlgItem(m_TabBackup.GetWindow(), IDC_BACKUP_BROWSE_BUTTON);
ShowWindow(item, SW_HIDE);
item = GetDlgItem(m_TabBackup.GetWindow(), IDC_BACKUP_INPROGRESS_TEXT);
ShowWindow(item, SW_SHOWNORMAL);
item = GetDlgItem(m_TabBackup.GetWindow(), IDC_BACKUP_PROGRESS);
ShowWindow(item, SW_SHOWNORMAL);
SendMessage(item, PBM_SETMARQUEE, (WPARAM)TRUE, 0);
m_ThreadHandle = (HANDLE)_beginthreadex(NULL, 0, BackupThreadProc, this, 0, NULL);
if (!m_ThreadHandle)
{
MessageBox(m_Window, L"Unable to start backup.", L"Backup Rainmeter", MB_ERROR);
EndDialog(m_Window, 0);
}
} }
} }

View File

@ -1028,26 +1028,11 @@ bool IsDefaultAddon(LPCTSTR addon)
*/ */
bool InstallComponents(RMSKIN_DATA* data) bool InstallComponents(RMSKIN_DATA* data)
{ {
// Close Rainmeter.exe if (!CloseRainmeterIfActive())
HWND hwnd = FindWindow(L"DummyRainWClass", L"Rainmeter control window");
if (hwnd)
{ {
DWORD pID, exitCode; std::wstring error = L"Failed to close Rainmeter.";
GetWindowThreadProcessId(hwnd, &pID); MessageBox(NULL, error.c_str(), APP_NAME, MB_ERROR);
HANDLE hProcess = OpenProcess(PROCESS_TERMINATE | SYNCHRONIZE, FALSE, pID); return false;
PostMessage(hwnd, WM_DESTROY, 0, 0);
// Wait up to 5 seconds for Rainmeter to close
WaitForSingleObject(hProcess, 5000);
GetExitCodeProcess(hProcess, &exitCode);
CloseHandle(hProcess);
if (exitCode == STILL_ACTIVE)
{
std::wstring error = L"Failed to close Rainmeter.";
MessageBox(NULL, error.c_str(), APP_NAME, MB_ERROR);
return false;
}
} }
int result; int result;
@ -1522,28 +1507,6 @@ unsigned __stdcall CreateInstallThread(void* pParam)
return InstallComponents((RMSKIN_DATA*)pParam) ? 0 : 1; return InstallComponents((RMSKIN_DATA*)pParam) ? 0 : 1;
} }
/*
** Copies files and folders from one location to another (from Rainmeter.cpp)
*/
bool CopyFiles(const std::wstring& strFrom, const std::wstring& strTo, bool bMove)
{
std::wstring tmpFrom(strFrom), tmpTo(strTo);
// The strings must end with double null
tmpFrom.append(L"0");
tmpFrom[tmpFrom.size() - 1] = L'\0';
tmpTo.append(L"0");
tmpTo[tmpTo.size() - 1] = L'\0';
SHFILEOPSTRUCT fo = {0};
fo.wFunc = bMove ? FO_MOVE : FO_COPY;
fo.pFrom = tmpFrom.c_str();
fo.pTo = tmpTo.c_str();
fo.fFlags = FOF_NO_UI | FOF_SILENT | FOF_NOCONFIRMATION;
return (SHFileOperation(&fo) != 0) ? false : true;
}
/* /*
** Splits the string from the delimiters and trims whitespace ** Splits the string from the delimiters and trims whitespace
*/ */

View File

@ -93,7 +93,6 @@ void KeepVariables(const std::wstring& backupFolder, const std::wstring& skinsPa
void LaunchRainmeter(); void LaunchRainmeter();
int CompareVersions(const std::wstring& strA, const std::wstring& strB); int CompareVersions(const std::wstring& strA, const std::wstring& strB);
bool CopyFiles(const std::wstring& strFrom, const std::wstring& strTo, bool bMove);
std::vector<std::wstring> Tokenize(const std::wstring& str, const std::wstring& delimiters); std::vector<std::wstring> Tokenize(const std::wstring& str, const std::wstring& delimiters);
std::wstring GetDotNETVersion(); std::wstring GetDotNETVersion();
std::wstring GetFileVersion(const std::wstring& file); std::wstring GetFileVersion(const std::wstring& file);