Skip to content

Commit

Permalink
gh-742: Improve installer error reporting, don't show error code twice.
Browse files Browse the repository at this point in the history
  • Loading branch information
Maximus5 committed Jun 21, 2016
1 parent 40d4c61 commit ebd10ab
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 36 deletions.
17 changes: 12 additions & 5 deletions src/Setup/Executor/Executor.cpp
Expand Up @@ -79,24 +79,31 @@ int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCm
sei.nShow = SW_SHOWNORMAL;
if (!ShellExecuteEx(&sei))
{
iInstRc = ReportError(32, L"Installer failed\n%s", pszMsi);
//iInstRc = ReportError(32, L"Installer failed\n%s", pszMsi);
iInstRc = MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, GetLastError());
}
else
{
if (!sei.hProcess)
{
iInstRc = ReportError(33, L"Installer failed\n%s", pszMsi);
//iInstRc = ReportError(33, L"Installer failed\n%s", pszMsi);
iInstRc = MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WINDOWS, GetLastError());
}
else
{
WaitForSingleObject(sei.hProcess, INFINITE);
DWORD nCode = 0;
SetLastError(0);
//1602 - seems like "user cancelled"
if (!GetExitCodeProcess(sei.hProcess, &nCode) || (nCode != 0 && nCode != 1602))
if (!GetExitCodeProcess(sei.hProcess, &nCode) /*|| (nCode != 0 && nCode != 1602)*/)
{
wchar_t szFormat[128]; wsprintf(szFormat, L"Installer failed\n%%s\nExitCode=%u", nCode);
iInstRc = ReportError(nCode ? nCode : 34, szFormat, pszMsi);
//wchar_t szFormat[128]; wsprintf(szFormat, L"Installer failed\n%%s\nExitCode=%u", nCode);
//iInstRc = ReportError(nCode ? nCode : 34, szFormat, pszMsi);
iInstRc = MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, GetLastError());
}
else
{
iInstRc = nCode;
}
}
}
Expand Down
78 changes: 47 additions & 31 deletions src/Setup/Setupper/Setupper.cpp
Expand Up @@ -14,6 +14,9 @@
#include "VersionI.h"
#include "NextArg.h"

// String resources (messages)
#include "Setupper.h"


// Global Variables:
HINSTANCE hInst;
Expand All @@ -28,7 +31,6 @@ wchar_t gsTempFolder[MAX_PATH-24];
wchar_t gsMsiFile[MAX_PATH];
wchar_t gsCabFile[MAX_PATH];
wchar_t gsExeFile[MAX_PATH];
const wchar_t gsWWW[] = L"Project page: <a href=\"https://conemu.github.io/\">https://conemu.github.io/</a>";
bool gbExtractOnly = false;
bool gbUseElevation = false;
bool gbAlreadyAdmin = false;
Expand Down Expand Up @@ -347,11 +349,11 @@ int ExportFile(int ResID, wchar_t* FilePath)
{
HRSRC hResInfo = FindResource(hInst, MAKEINTRESOURCE(ResID), L"DATA");
if (!hResInfo)
return ReportError(1, L"FindResource(%i) failed", (void*)ResID);
return ReportError(1, msgFindResourceFailed, (void*)ResID);

HGLOBAL hGbl = LoadResource(hInst, hResInfo);
if (!hGbl)
return ReportError(2, L"LoadResource(%i) failed", (void*)ResID);
return ReportError(2, msgLoadResourceFailed, (void*)ResID);

DWORD nResSize = hResInfo ? SizeofResource(hInst, hResInfo) : 0;
LPVOID pRes = hGbl ? LockResource(hGbl) : NULL;
Expand All @@ -360,21 +362,21 @@ int ExportFile(int ResID, wchar_t* FilePath)

if (!nResSize || !pRes)
{
iRc = ReportError(3, L"LoadResource(%i) failed", (void*)ResID);
iRc = ReportError(3, msgLoadResourceFailed, (void*)ResID);
}
else
{
HANDLE hFile = CreateFile(FilePath, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (!hFile || hFile == INVALID_HANDLE_VALUE)
{
iRc = ReportError(4, L"CreateFile(%s) failed", FilePath);
iRc = ReportError(4, msgCreateFileFailed, FilePath);
}
else
{
DWORD nWritten = 0;
if (!WriteFile(hFile, pRes, nResSize, &nWritten, NULL) || nWritten != nResSize)
{
iRc = ReportError(5, L"WriteFile(%s) failed", FilePath);
iRc = ReportError(5, msgWriteFileFailed, FilePath);
}

CloseHandle(hFile);
Expand All @@ -400,8 +402,8 @@ int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCm

int nInstallVer = 0;

wsprintf(gsTitle, L"ConEmu %s installer", CONEMUVERL);
lstrcpyn(gsRunAsAdm, L"Run installer as administrator", countof(gsRunAsAdm));
wsprintf(gsTitle, msgConEmuInstaller, CONEMUVERL);
lstrcpyn(gsRunAsAdm, msgRunSetupAsAdmin, countof(gsRunAsAdm));

wchar_t szArg[MAX_PATH+1];
LPCWSTR pszCmdToken = GetCommandLine();
Expand All @@ -414,13 +416,7 @@ int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCm
if (lstrcmp(szArg, L"/?") == 0 || lstrcmp(szArg, L"-?") == 0 || lstrcmp(szArg, L"-h") == 0
|| lstrcmp(szArg, L"-help") == 0 || lstrcmp(szArg, L"--help") == 0)
{
MessageBox(NULL,
L"Usage:\n"
L" ConEmuSetup [/p:x86[,adm] | /p:x64[,adm]] [<msi args>]\n"
L" ConEmuSetup [/e[:<extract path>]] [/p:x86 | /p:x64]\n"
L"Example (run x64 auto update as administrator):\n"
L" ConEmuSetup /p:x64,adm /qr",
gsTitle, MB_ICONINFORMATION);
MessageBox(NULL, msgUsageExample, gsTitle, MB_ICONINFORMATION);
return 1;
}

Expand Down Expand Up @@ -478,7 +474,7 @@ int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCm
bool bInstalled;
HKEY hk;

lstrcpyn(gsMessage, L"Choose version to install", countof(gsMessage));
lstrcpyn(gsMessage, msgChooseInstallVer, countof(gsMessage));

szInstallPath[0] = 0; bInstalled = false;
struct {HKEY hk; LPCWSTR path; LPCWSTR name; bool our;}
Expand Down Expand Up @@ -512,7 +508,7 @@ int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCm
int nLen = lstrlen(szInstallPath);
lstrcat(szInstallPath, (nLen > 0 && szInstallPath[nLen-1] != L'\\') ? L"\\ConEmu" : L"ConEmu");
}
wsprintf(gsVer86, L"%s x86\n%s installation folder is\n%s", CONEMUVERL, bInstalled ? L"Current" : L"Default", szInstallPath);
wsprintf(gsVer86, msgInstallFolderIs, CONEMUVERL, L"x86", bInstalled ? msgPathCurrent : msgPathDefault, szInstallPath);


if (isWin64)
Expand Down Expand Up @@ -549,9 +545,9 @@ int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCm
int nLen = lstrlen(szInstallPath);
lstrcat(szInstallPath, (nLen > 0 && szInstallPath[nLen-1] != L'\\') ? L"\\ConEmu" : L"ConEmu");
}
wsprintf(gsVer64, L"%s x64\n%s installation folder is\n%s", CONEMUVERL, bInstalled ? L"Current" : L"Default", szInstallPath);
wsprintf(gsVer64, msgInstallFolderIs, CONEMUVERL, L"x64", bInstalled ? msgPathCurrent : msgPathDefault, szInstallPath);

wsprintf(gsFull, L"%s\n\nPress `Yes` to install x64 version\nPress `No` to install x86 version", gsMessage);
wsprintf(gsFull, msgInstallConfirm, gsMessage);
}
else
{
Expand All @@ -574,10 +570,10 @@ int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCm
lstrcpy(pszSubDir, CONEMUVERL);
}

lstrcpyn(gsMessage, L"Choose version to extract", countof(gsMessage));
wsprintf(gsVer86, L"%s x86\nExtract installation files to\n%s", CONEMUVERL, szPath);
wsprintf(gsVer64, L"%s x64\nExtract installation files to\n%s", CONEMUVERL, szPath);
wsprintf(gsFull, L"%s\n\nPress `Yes` to extract x64 version\nPress `No` to extract x86 version\n\n%s", gsMessage, szPath);
lstrcpyn(gsMessage, msgChooseExtractVer, countof(gsMessage));
wsprintf(gsVer86, msgExtractX86X64, CONEMUVERL, L"x86", szPath);
wsprintf(gsVer64, msgExtractX86X64, CONEMUVERL, L"x64", szPath);
wsprintf(gsFull, msgExtractConfirm, gsMessage, szPath);
}

if (nInstallVer == 0)
Expand Down Expand Up @@ -614,7 +610,7 @@ int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCm
}
if (!lbCreated)
{
return ReportError(10, L"Can't create temp folder\n%s", gsTempFolder);
return ReportError(10, msgTempFolderFailed, gsTempFolder);
}
}
}
Expand Down Expand Up @@ -647,7 +643,7 @@ int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCm
if (gbExtractOnly)
{
wchar_t szMessage[MAX_PATH*2];
wsprintf(szMessage, L"Installation files was extracted successfully\n%s", gsTempFolder);
wsprintf(szMessage, msgExtractedSuccessfully, gsTempFolder);
MessageBox(NULL, szMessage, gsTitle, MB_ICONINFORMATION);
return 0;
}
Expand All @@ -664,6 +660,7 @@ int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCm
}
else
{
// Executor has `<requestedExecutionLevel level="requireAdministrator" ...>` in manifest
sei.lpFile = gsExeFile;
int nMaxLen = lstrlen(gsMsiFile) + (pszCmdToken ? lstrlen(pszCmdToken) : 0) + 64;
pszParms = (wchar_t*)malloc(nMaxLen*sizeof(wchar_t));
Expand Down Expand Up @@ -696,24 +693,43 @@ int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCm

if (!lbExecute)
{
iInstRc = ReportError(20, L"Installer failed\n%s", gsMsiFile);
iInstRc = ReportError(20, msgInstallerFailed, gsMsiFile);
}
else
{
if (!sei.hProcess)
{
iInstRc = ReportError(21, L"Installer failed\n%s", gsMsiFile);
iInstRc = ReportError(21, msgInstallerFailed, gsMsiFile);
}
else
{
WaitForSingleObject(sei.hProcess, INFINITE);
DWORD nCode = 0;
SetLastError(0);
//1602 - это похоже "Отмена" пользователем
if (!GetExitCodeProcess(sei.hProcess, &nCode) || (nCode != 0 && nCode != 1602))
wchar_t szFormat[256];
if (GetExitCodeProcess(sei.hProcess, &nCode))
{
switch (nCode)
{
case 0:
iInstRc = 0;
break;
case 1602: // cancelled by user
iInstRc = 0; // don't show any errors
break;
case 3010: // reboot is required
wsprintf(szFormat, msgRebootRequired, nCode);
iInstRc = ReportError(100+nCode, szFormat, gsMsiFile);
break;
default:
wsprintf(szFormat, msgInstallerFailedEx, nCode);
iInstRc = ReportError(100+nCode, szFormat, gsMsiFile);
}
}
else
{
wchar_t szFormat[128]; wsprintf(szFormat, L"Installer failed\n%%s\nExitCode=%u", nCode);
iInstRc = ReportError(100+nCode, szFormat, gsMsiFile);
lstrcpyn(szFormat, msgExitCodeFailed, countof(szFormat));
iInstRc = ReportError(30, szFormat, gsMsiFile);
}
}
}
Expand Down
36 changes: 36 additions & 0 deletions src/Setup/Setupper/Setupper.h
@@ -0,0 +1,36 @@
// NO BOM! Compiled with old gcc!

#pragma once

// String resources (messages)

const wchar_t gsWWW[] = L"Project page: <a href=\"https://conemu.github.io/\">https://conemu.github.io/</a>";

const wchar_t msgConEmuInstaller[] = L"ConEmu %s installer";
const wchar_t msgRunSetupAsAdmin[] = L"Run installer as administrator";

const wchar_t msgUsageExample[] =
L"Usage:\n"
L" ConEmuSetup [/p:x86[,adm] | /p:x64[,adm]] [<msi args>]\n"
L" ConEmuSetup [/e[:<extract path>]] [/p:x86 | /p:x64]\n"
L"Example (run x64 auto update as administrator):\n"
L" ConEmuSetup /p:x64,adm /qr";

const wchar_t msgRebootRequired[] = L"You have chosen not to reboot the machine.\nReboot is required to get ConEmu instance working properly!\n%%s\nExitCode=%u";
const wchar_t msgInstallerFailed[] = L"Installer failed\n%s";
const wchar_t msgInstallerFailedEx[] = L"Installer failed\n%%s\nExitCode=%u";
const wchar_t msgExitCodeFailed[] = L"Installer failed (GetExitCodeProcess)\n%%s";
const wchar_t msgFindResourceFailed[] = L"FindResource(%i) failed";
const wchar_t msgLoadResourceFailed[] = L"LoadResource(%i) failed";
const wchar_t msgCreateFileFailed[] = L"CreateFile(%s) failed";
const wchar_t msgWriteFileFailed[] = L"WriteFile(%s) failed";
const wchar_t msgTempFolderFailed[] = L"Can't create temp folder\n%s";
const wchar_t msgExtractedSuccessfully[] = L"Installation files were extracted successfully\n%s";
const wchar_t msgChooseExtractVer[] = L"Choose version to extract";
const wchar_t msgExtractX86X64[] = L"%s %s\nExtract installation files to\n%s";
const wchar_t msgExtractConfirm[] = L"%s\n\nPress `Yes` to extract x64 version\nPress `No` to extract x86 version\n\n%s";
const wchar_t msgChooseInstallVer[] = L"Choose version to install";
const wchar_t msgInstallFolderIs[] = L"%s %s\n%s installation folder is\n%s";
const wchar_t msgPathCurrent[] = L"Current";
const wchar_t msgPathDefault[] = L"Default";
const wchar_t msgInstallConfirm[] = L"%s\n\nPress `Yes` to install x64 version\nPress `No` to install x86 version";

0 comments on commit ebd10ab

Please sign in to comment.