在后台Wix中运行该程序

时间:2014-12-08 15:18:10

标签: c# c++ visual-studio-2010 wix

我编写了一个简单的安装程序,当我使用以下命令时获取属性值:

msiexec /i file.msi /l*v output.txt IPADDRESS="192.168.2.1"

我在C#Custom操作中提取了IPADDRESS的值,并创建了两个文件夹输出 config 。在config中,我写了IPADDRESS的内容,输出用于记录。这是我的C#代码:

namespace SetupCA
{
    public class CustomActions
    {
        [CustomAction]
        public static ActionResult WriteFileToDisk(Session session)
        {
            session.Log("Begin WriteFileToDisk");
            string ipAddress = session["IPADDRESS"];
            string path = session["LocalAppDataFolder"]; //With trailing slash
            path = path.Replace(@"\", @"\\").ToString();
            string log_path = path + @"lpa\\output\\";
            string config_path = path + @"lpa\\config\\";
            session.Log("Local App Data Modified Path is: " + path.ToString());
            session.Log("Logging Folder Path is: " + log_path.ToString());
            string temp = @"
{{
 ""logpoint_ip"" : ""{0}"" 
}}";
            string config = string.Format(temp, ipAddress);
            session.Log("Config Generated from property is: " + config);
            System.IO.Directory.CreateDirectory(config_path);
            try
            {
                System.IO.File.Delete(path + "lpa.config");
            }
            catch (Exception e)
            {
                session.Log(e.ToString());
            }
            System.IO.File.WriteAllText(config_path + "lpa.config", config);
            session.Log("Confile file is written");
            System.IO.Directory.CreateDirectory(log_path);
            session.Log("Logging Folder is Created");
            return ActionResult.Success;
        }
    }
}

现在我已经创建了一个Visual C ++应用程序,用于检查程序是否已在启动期间注册。如果没有,它会在注册表中添加exe文件并进入无限循环。如果我运行已安装的exe,它将出现在命令窗口中。我想要的是在后台运行exe,用户可以在任务管理器中查看进程内的exe。我不想通过显示一个似乎什么都不做的空白终端窗口来打扰用户。这可以在Wix中完成,还是应该更改我的代码? 我附上了我的C ++代码和Wix文件。

CODE

#include <iostream>
#include <Windows.h>
#include <ShlObj.h>
#include <log4cplus/logger.h>
#include <log4cplus/fileappender.h>
#include <log4cplus/layout.h>
#include <log4cplus/ndc.h>
#include <log4cplus/helpers/loglog.h>
#include <log4cplus/loggingmacros.h>
#include <boost\lexical_cast.hpp>
#include <boost\algorithm\string\replace.hpp>
using namespace log4cplus;
Logger root;


std::string GetLocalAppDataPath();
void LoggingInit();

void LoggingInit()
{
        log4cplus::initialize ();
        helpers::LogLog::getLogLog()->setInternalDebugging(false);
        std::string local_path = GetLocalAppDataPath();
        local_path = local_path + "\\lpa\\output\\";
        SharedAppenderPtr append_1(new RollingFileAppender(LOG4CPLUS_TEXT( local_path + "outputgen.log"), 10*1024*1024, 5));
        append_1->setName(LOG4CPLUS_TEXT("LogpointAgentLog"));
        PatternLayout *p = new PatternLayout(LOG4CPLUS_TEXT("[%D] <%-5p> [%F : %L] %m%n"));
        append_1->setLayout(std::auto_ptr<Layout>(p));
        Logger::getRoot().addAppender(append_1);
        root = Logger::getRoot();
}

std::string GetLocalAppDataPath()
{
    HANDLE hfile;
    TCHAR szPath[MAX_PATH];
    if(SUCCEEDED(SHGetFolderPath(NULL,CSIDL_LOCAL_APPDATA,NULL,0, szPath))) 
    {
        std::string path = boost::lexical_cast<std::string>(szPath);
        boost::replace_all(path, "\\", "\\\\");
        return path;
    }
}


BOOL IsMyProgramRegisteredForStartup(PCWSTR pszAppName)
{
    HKEY hKey = NULL;
    LONG lResult = 0;
    BOOL fSuccess = TRUE;
    DWORD dwRegType = REG_SZ;
    wchar_t szPathToExe[MAX_PATH]  = {};
    DWORD dwSize = sizeof(szPathToExe);

    lResult = RegOpenKeyExW(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\Run", 0, KEY_READ, &hKey);

    fSuccess = (lResult == 0);

    if (fSuccess)
    {
        lResult = RegGetValueW(hKey, NULL, pszAppName, RRF_RT_REG_SZ, &dwRegType, szPathToExe, &dwSize);
        fSuccess = (lResult == 0);
    }

    if (fSuccess)
    {
        fSuccess = (wcslen(szPathToExe) > 0) ? TRUE : FALSE;
    }

    if (hKey != NULL)
    {
        RegCloseKey(hKey);
        hKey = NULL;
    }

    return fSuccess;
}

BOOL RegisterMyProgramForStartup(PCWSTR pszAppName, PCWSTR pathToExe)
{
    HKEY hKey = NULL;
    LONG lResult = 0;
    BOOL fSuccess = TRUE;
    DWORD dwSize;

    const size_t count = MAX_PATH*2;
    wchar_t szValue[count] = {};


    wcscpy_s(szValue, count, L"\"");
    wcscat_s(szValue, count, pathToExe);
    wcscat_s(szValue, count, L"\" ");

    lResult = RegCreateKeyExW(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\Run", 0, NULL, 0, (KEY_WRITE | KEY_READ), NULL, &hKey, NULL);

    fSuccess = (lResult == 0);

    if (fSuccess)
    {
        dwSize = (wcslen(szValue)+1)*2;
        lResult = RegSetValueExW(hKey, pszAppName, 0, REG_SZ, (BYTE*)szValue, dwSize);
        fSuccess = (lResult == 0);
    }

    if (hKey != NULL)
    {
        RegCloseKey(hKey);
        hKey = NULL;
    }

    return fSuccess;
}

int main()
{
    //std::string loc = GetLocalAppDataPath(); //Without trailing slashes
    LoggingInit();  
    if(IsMyProgramRegisteredForStartup(L"My_Program"))
    {
        //do nothing
    }
    else
    {
        LOG4CPLUS_INFO(root, "Starting Starup App");
        wchar_t szPathToExe[MAX_PATH];
        GetModuleFileNameW(NULL, szPathToExe, MAX_PATH);
        RegisterMyProgramForStartup(L"My_Program", szPathToExe);
        LOG4CPLUS_INFO(root, "Ending Starup App");
    }

    LOG4CPLUS_INFO(root, "BEFORE INFINITE LOOP #######################");
    while(1)
    {
        LOG4CPLUS_INFO(root, "INSIDE THE WHILE LOOOOOOPPPP");
        Sleep(5000);
    }

    return 0;

}

WIX FILE

<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
    <Product Id="*" Name="InstallerForStartupCPP" Language="1033" Version="1.0.0.0" Manufacturer="LPAA" UpgradeCode="70510e56-b6ab-4e6f-beb6-40bb2e30c568">
        <Package InstallerVersion="200" Compressed="no" InstallScope="perMachine" />

        <MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
        <MediaTemplate />

        <Feature Id="ProductFeature" Title="InstallerForStartupCPP" Level="1">
            <ComponentGroupRef Id="ProductComponents" />
        </Feature>
    </Product>

    <Fragment>
        <Directory Id="TARGETDIR" Name="SourceDir">
            <Directory Id="ProgramFilesFolder">
                <Directory Id="INSTALLFOLDER" Name="Startup CPP" />
            </Directory>
        </Directory>
    </Fragment>

    <Fragment>
        <ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
      <Component Id="ProductComponent">
        <File
          Id="STARTUPCPPINSTALLER"
          Name="StartupCPPInstaller.exe"
          DiskId="1"
          Source="$(var.StartupCPPInstaller.TargetPath)"
          Vital="yes"
          KeyPath="yes" />
      </Component>

      <Component Id="log4cplus">
        <File Source ="G:\SarVaGYa\myworkspace\LatestLpa\lpa\lpa_c\ext_library\log4cplus\bin\Release\log4cplus.dll" />
      </Component>
        </ComponentGroup>
    <Binary Id="SetupCA"  SourceFile="..\SetupCA\bin\Release\SetupCA.CA.dll"/>
    <CustomAction Id="WRITEFILETODISK" Execute="immediate" BinaryKey="SetupCA" DllEntry="WriteFileToDisk" />
    <InstallExecuteSequence>
      <Custom Action="WRITEFILETODISK" Sequence="2"></Custom>
    </InstallExecuteSequence>
    </Fragment>
</Wix>

我应该如何安装MSI文件并在后台运行该程序。请帮忙。 PS:我尝试过提供服务。如果我将程序作为服务运行,我不会得到 GetLocalAppDataPath true值。

2 个答案:

答案 0 :(得分:1)

直接的方法是在项目设置中将C ++应用程序子系统类型更改为windowsLinker->System->SubSystem并将main函数替换为WinMain - 它不会创建任何窗口本身,您可以忽略其参数,并执行您目前在main中执行的操作。

答案 1 :(得分:0)

所有“RegisterMyProgramForStartup”正在写的是编写注册表值。这是RegistryValue元素公开的基本Windows Installer 101功能。所有这些自定义操作代码都是反模式。