我编写了一个简单的安装程序,当我使用以下命令时获取属性值:
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值。
答案 0 :(得分:1)
直接的方法是在项目设置中将C ++应用程序子系统类型更改为windows
:Linker->System->SubSystem
并将main
函数替换为WinMain - 它不会创建任何窗口本身,您可以忽略其参数,并执行您目前在main
中执行的操作。
答案 1 :(得分:0)
所有“RegisterMyProgramForStartup”正在写的是编写注册表值。这是RegistryValue元素公开的基本Windows Installer 101功能。所有这些自定义操作代码都是反模式。