修正引号
智能大石头 authored at 2023-03-01 00:56:04
7.80 KiB
LuckyClover
#include "BaseInclude.h"
#include "CDownloadFile.h"
#include "CGetOSVersion.h"
#include "CRegistryVisit.h"

using namespace std;

bool CheckRuntime();
void InstallNet20();
void InstallNet40();
void InstallNet45();
void InstallNet48();

bool _silent = false;

int main(int argc, char* argv[])
{
    //检测OS版本状态
    CGetOSVersion cOSVer;
    int iOSMainVerNum = 0;
    int iOSSubVerNum = 0;
    bool bIsServer = false;

    cout << "幸运草 v1.0.2023.215 NewLife" << endl;
    cout << "检测并安装主流.NET运行时。" << endl;
    cout << "操作系统: " << cOSVer.GetOSVersionDesc(iOSMainVerNum, iOSSubVerNum, bIsServer) << "\n";
    cout << "用法:clover.exe [net2|net4|net45|net48] -silent" << endl;
    cout << "本地server.txt文件设置下载文件的服务器地址。" << endl;

    CheckRuntime();

    // 读取静默安装标记
    for (int i = 0; i < argc; ++i)
    {
        string strArg = argv[i];
        if (strArg == "-silent") _silent = true;
    }

    string ver = "";
    if (argc >= 2)
        ver.assign(argv[1]);
    else if (iOSMainVerNum <= 5)
        ver = "net2";
    else
        ver = "net4";

    if (ver == "net2" || ver == "net20") {
        InstallNet20();
    }
    else if (ver == "net4" || ver == "net40") {
        InstallNet40();
    }
    else if (ver == "net45") {
        InstallNet45();
    }
    else if (ver == "net48") {
        InstallNet48();
    }

    return 0;
}

bool CheckRuntime()
{
    //检测OS是否安装 .net Framework客户端版本
    CRegistryVisit cRegVisit;

    cout << endl;
    cout << "已安装版本:" << endl;
    bool bNet20 = cRegVisit.CheckIsInstallNet(_T("2.0"));
    if (bNet20) {
        cout << "v2.0" << endl;
    }

    bool bNet30 = cRegVisit.CheckIsInstallNet(_T("3.0"));
    if (bNet30) {
        cout << "v3.0" << endl;
    }

    bool bNet35 = cRegVisit.CheckIsInstallNet(_T("3.5"));
    if (bNet35) {
        cout << "v3.5" << endl;
    }

    bool bNet40 = cRegVisit.CheckIsInstallNet(_T("4.0"));
    if (bNet40) {
        cout << "v4.0" << endl;
    }

    bool bNet45 = cRegVisit.CheckIsInstallNet(_T("4.5"));
    if (bNet45) {
        cout << "v4.5" << endl;
    }

    bool bNet48 = cRegVisit.CheckIsInstallNet(_T("4.8"));
    if (bNet48) {
        cout << "v4.8" << endl;
    }

    //if (ver == "net2" || ver == "net20") return bNet20;
    //if (ver == "net3" || ver == "net30") return bNet30;
    //if (ver == "net35") return bNet35;
    //if (ver == "net4" || ver == "net40") return bNet40;
    //if (ver == "net45") return bNet45;
    //if (ver == "net48") return bNet48;

    return true;
}

const string GetFile(const string& ver)
{
    if (ver == "net2" || ver == "net20") return "NetFx20SP2_x86.exe";
    if (ver == "net3" || ver == "net30" || ver == "net35") return "NetFx20SP2_x86.exe";
    if (ver == "net4" || ver == "net40") return "dotNetFx40_Full_x86_x64.exe";
    if (ver == "net45") return "NDP452-KB2901907-x86-x64-AllOS-ENU.exe";
    if (ver == "net48") return "ndp48-x86-x64-allos-enu.exe";

    //构造本地文件目录绝对路径 -- 获取当前工作目录
    TCHAR szPath[MAX_PATH] = { 0 };
    CString strFilePath;
    if (GetModuleFileName(NULL, szPath, MAX_PATH))
    {
        CString strTemp(szPath);
        CString strPathTemp;
        strPathTemp = strTemp.Left(strTemp.ReverseFind('\\'));
        strFilePath = strPathTemp + _T("\\dotNetFx40_Full_x86_x64.exe");
    }

    return "";
}

bool Download(const string& localFile, const string& remoteFile)
{
    string server = "http://x.newlifex.com";

    // 从配置文件读取服务器地址
    char szPath[MAX_PATH] = { 0 };
    if (GetModuleFileName(NULL, szPath, MAX_PATH))
    {
        CString strTemp(szPath);
        CString strCurrentDir = strTemp.Left(strTemp.ReverseFind('\\'));
        CString strConfigFilePath = strCurrentDir + _T("\\server.txt");
        if (::PathFileExists(strConfigFilePath)) {
            ifstream infile;
            infile.open(strConfigFilePath);
            if (infile) {
                char line[64];
                if (infile.getline(line, sizeof(line))) {
                    string str(line);
                    if (!str.empty()) {
                        server = str;
                    }
                }
            }

            infile.close();
        }
    }

    CDownloadFile cDownFile;
    string remote = "/dotnet/" + remoteFile;

    cout << "下载:" << server << remote << endl;
    cout << "保存:" << localFile << endl;

    //执行下载操作
    int iTryCount = 0;
    while (++iTryCount < 15)
    {
        if (cDownFile.Download(localFile.c_str(), server.c_str(), 80, remote.c_str())) return true;

        //沉默1秒后重试
        Sleep(1 * 1000);
    }

    return false;
}

bool Install(const string& fileName, const string& baseUrl, const string& arg)
{
    cout << "安装:" << fileName << endl;

    //构造本地文件目录绝对路径 -- 获取当前工作目录
    TCHAR szPath[MAX_PATH] = { 0 };
    if (!GetModuleFileName(NULL, szPath, MAX_PATH)) return false;

    CString strTemp(szPath);
    CString strPathTemp = strTemp.Left(strTemp.ReverseFind('\\'));

    string file(strPathTemp);
    file += "\\" + fileName;
    string remoteFile = fileName;
    if (baseUrl.empty()) remoteFile = baseUrl + fileName;

    // 不存在则下载
    if (!::PathFileExists(file.c_str())) {
        if (!Download(file, remoteFile)) {
            cout << "下载失败!" << endl;
            return false;
        }
    }

    // 仍然不存在,则退出
    if (!::PathFileExists(file.c_str())) return false;

    cout << "开始安装 " << fileName << " ......" << endl;

    // 执行.net Framework安装文件(exe),带参数
    // system 执行命令并等待完成,ShellExecute 不等返回
    //ShellExecute(NULL, _T("open"), file.c_str(), _T("/passive /promptrestart"), NULL, SW_HIDE);
    if (!_silent)
        system(("\"" + file + "\"").c_str());
    else if (arg.empty())
        system(("\"" + file + "\" /passive /promptrestart").c_str());
    else
        system(("\"" + file + "\" " + arg).c_str());
}

bool Install(const string& fileName)
{
    return Install(fileName, "", "");
}

void InstallNet20()
{
    CRegistryVisit cRegVisit;

    bool bNet = cRegVisit.CheckIsInstallNet(_T("2.0"));
    if (bNet) {
        cout << "已安装.NET2.0" << endl;
        return;
    }

    Install("NetFx20SP2_x86.exe");
}

void InstallNet40()
{
    CRegistryVisit cRegVisit;

    bool bNet = cRegVisit.CheckIsInstallNet(_T("4.0"));
    if (bNet) {
        cout << "已安装.NET4.0" << endl;
        return;
    }

    Install("dotNetFx40_Full_x86_x64.exe");
}

void InstallNet45()
{
    CRegistryVisit cRegVisit;

    bool bNet = cRegVisit.CheckIsInstallNet(_T("4.5"));
    if (bNet) {
        cout << "已安装.NET4.5" << endl;
        return;
    }

    Install("NDP452-KB2901907-x86-x64-AllOS-ENU.exe");
    Install("NDP452-KB2901907-x86-x64-AllOS-CHS.exe");
}

void InstallNet48()
{
    CRegistryVisit cRegVisit;

    bool bNet = cRegVisit.CheckIsInstallNet(_T("4.8"));
    if (bNet) {
        cout << "已安装.NET4.8" << endl;
        return;
    }

    CGetOSVersion cOSVer;
    int iOSMainVerNum = 0;
    int iOSSubVerNum = 0;
    bool bIsServer = false;

    cOSVer.GetOSVersionDesc(iOSMainVerNum, iOSSubVerNum, bIsServer);

    bool isWin7 = iOSMainVerNum == 6 && iOSSubVerNum == 1;
    if (isWin7)
        Install("Windows6.1-KB3063858-x64.msu", "win7/", "/quiet /norestart");

    // win10/win11 中安装 .NET4.8.1
    if (iOSMainVerNum >= 10)
    {
        Install("ndp481-x86-x64-allos-enu.exe", "", "/passive /promptrestart /showfinalerror");
        Install("ndp481-x86-x64-allos-chs.exe", "", "/passive /promptrestart /showfinalerror");
    }
    else
    {
        Install("ndp48-x86-x64-allos-enu.exe", "", "/passive /promptrestart /showfinalerror");
        Install("ndp48-x86-x64-allos-chs.exe", "", "/passive /promptrestart /showfinalerror");
    }
}