Can we make dynamic URL in manifest file in officejs? - environment-variables

I am new to office addins. I want to add the environment variable. As in the below manifest code, we can see that the URL http://localhost:3000/ is repeated again and again. I want to store this URL in any specific place or in any file and after that, I want to use it in the manifest file. So, whenever I change the URL it will reflect all the places. We don't require to change at all. I am not getting any idea about it.
so can anyone guide me on "How to use a single URL in the manifest with an environment variable?"
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<OfficeApp xmlns="http://schemas.microsoft.com/office/appforoffice/1.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:bt="http://schemas.microsoft.com/office/officeappbasictypes/1.0" xmlns:ov="http://schemas.microsoft.com/office/taskpaneappversionoverrides" xsi:type="TaskPaneApp">
<Id>083aced0-1978-4026-bfb3-86e91ecdf2ec</Id>
<Version>1.0.0.0</Version>
<ProviderName>Test Excel Add-in</ProviderName>
<DefaultLocale>en-US</DefaultLocale>
<DisplayName DefaultValue="Test Excel Addin" />
<Description DefaultValue="A template to get started." />
<IconUrl DefaultValue="https://localhost:3000/assets/Favicon-36px.jpg" />
<HighResolutionIconUrl DefaultValue="https://localhost:3000/assets/Favicon-36px.jpg" />
<SupportUrl DefaultValue="https://test.zendesk.com/hc/en-us" />
<AppDomains>
<AppDomain>https://demo.test.test</AppDomain>
<AppDomain>https://test.test-const.net</AppDomain>
</AppDomains>
<Hosts>
<Host Name="Workbook" />
</Hosts>
<DefaultSettings>
<SourceLocation DefaultValue="https://localhost:3000/taskpane.html" />
</DefaultSettings>
<Permissions>ReadWriteDocument</Permissions>
<VersionOverrides xmlns="http://schemas.microsoft.com/office/taskpaneappversionoverrides" xsi:type="VersionOverridesV1_0">
<Hosts>
<Host xsi:type="Workbook">
<DesktopFormFactor>
<GetStarted>
<Title resid="GetStarted.Title" />
<Description resid="GetStarted.Description" />
<LearnMoreUrl resid="GetStarted.LearnMoreUrl" />
</GetStarted>
<FunctionFile resid="Commands.Url" />
<ExtensionPoint xsi:type="PrimaryCommandSurface">
<OfficeTab id="TabHome">
<Group id="CommandsGroup">
<Label resid="CommandsGroup.Label" />
<Icon>
<bt:Image size="16" resid="Icon.16x16" />
<bt:Image size="32" resid="Icon.32x32" />
<bt:Image size="80" resid="Icon.80x80" />
</Icon>
<Control xsi:type="Button" id="TaskpaneButton">
<Label resid="TaskpaneButton.Label" />
<Supertip>
<Title resid="TaskpaneButton.Label" />
<Description resid="TaskpaneButton.Tooltip" />
</Supertip>
<Icon>
<bt:Image size="16" resid="Icon.16x16" />
<bt:Image size="32" resid="Icon.32x32" />
<bt:Image size="80" resid="Icon.80x80" />
</Icon>
<Action xsi:type="ShowTaskpane">
<TaskpaneId>ButtonId1</TaskpaneId>
<SourceLocation resid="Taskpane.Url" />
</Action>
</Control>
</Group>
</OfficeTab>
</ExtensionPoint>
</DesktopFormFactor>
</Host>
</Hosts>
<Resources>
<bt:Images>
<bt:Image id="Icon.16x16" DefaultValue="https://localhost:3000/assets/Favicon-36px.jpg" />
<bt:Image id="Icon.32x32" DefaultValue="https://localhost:3000/assets/Favicon-36px.jpg" />
<bt:Image id="Icon.80x80" DefaultValue="https://localhost:3000/assets/Favicon-36px.jpg" />
</bt:Images>
<bt:Urls>
<bt:Url id="GetStarted.LearnMoreUrl" DefaultValue="https://go.microsoft.com/fwlink/?LinkId=276812" />
<bt:Url id="Commands.Url" DefaultValue="https://localhost:3000/commands.html" />
<bt:Url id="Taskpane.Url" DefaultValue="https://localhost:3000/taskpane.html" />
</bt:Urls>
<bt:ShortStrings>
<bt:String id="GetStarted.Title" DefaultValue="Get started with test Add-in" />
<bt:String id="CommandsGroup.Label" DefaultValue="Commands Group" />
<bt:String id="TaskpaneButton.Label" DefaultValue="test" />
</bt:ShortStrings>
<bt:LongStrings>
<bt:String id="GetStarted.Description" DefaultValue="test Add-in Loaded Successfully" />
<bt:String id="TaskpaneButton.Tooltip" DefaultValue="test Add-in Taskpane" />
</bt:LongStrings>
</Resources>
</VersionOverrides>
</OfficeApp>

The URLs in the manifest.xml file cannot change after the manifest has been uploaded to Microsoft AppSource (aka "the Store") or uploaded using Centralized Deployment in the Microsoft 365 Admin portal. It is not possible to store the URLs outside of the manifest.xml file once the manifest has been published or deployed.
You can change how the manifest.xml file is generated by modifying the webpack.config.js file in your add-in project by changing the following code:
plugins: [
...
new CopyWebpackPlugin({
patterns: [
...
{
from: "manifest*.xml",
to: "[name]" + "[ext]",
transform(content) {
if (dev) {
return content;
} else {
return content.toString().replace(new RegExp(urlDev + "(?:public/)?", "g"), urlProd);
}
},
},
],
}),

Typically in Node based applications you could store environment variable in ENV files in the following way:
# .env file
USER_ID="239482"
USER_KEY="foobar"
NODE_ENV="development"
And read them in your application when required:
require('dotenv').config();
process.env.USER_ID; // "239482"
process.env.USER_KEY; // "foobar"
process.env.NODE_ENV; // "development"
And you can do so in Office web add-ins.
But add-in manifest files are processed by the webpack and the final URL depends on the configuration of webpack where you can specify the release and debug URLs and depending the build conditions the required manifest file will produced with the right URL. If you use VSCode and Yeoman generator was used to scaffold the project, in the webpack.config.js file you may find the following declarations:
const urlDev = "https://localhost:3000/";
const urlProd = "https://www.contoso.com/"; // CHANGE THIS TO YOUR PRODUCTION DEPLOYMENT LOCATION
In the file you may find the code which replaces the localhost entries in your manifest file with the production URL specified in the code (see urlProd).
new CopyWebpackPlugin({
patterns: [
...
{
from: "manifest*.xml",
to: "[name]" + "[ext]",
transform(content) {
if (dev) {
return content;
} else {
return content.toString().replace(new RegExp(urlDev, "g"), urlProd);
}
},
},
],
}),
That is done by the webpack. You don't need to replace URLs manually in the manifest file.

Related

Serilog not logging anymore after upgrading to 2.*

We have a large application (about 40 projects) that uses .NET Framework 4.8 and C# in VS 2019. It includes a couple of WCF services and a bunch of Web Apps using different "old" technologies (WebForms, ASP.NET MVC).
We are trying to upgrade Serilog from 1.5.14 to 2.11.0.
The upgrade went fine following the upgrade guide (see Upgrade Guide here), and the project compiles and runs fine.
The problem is that it doesn't log anything anymore: each separate service and web app has its own Serilog configuration (using XML AppSettings), but no log file is created and of course no logging is done, and the configuration hasn't been changed. No exception or anything like that is thrown either.
The problem might be that the configuration is not read for some reason, or there is something to add missing from the upgrade guide. The original code that initializes the logger looks like this:
Log.Logger = new LoggerConfiguration()
.Enrich.WithExceptionDetails()
.ReadFrom.AppSettings()
.CreateLogger();
Log.Information("Service Starting");
If I change the code to be like this:
var l = new LoggerConfiguration().ReadFrom.AppSettings().Enrich.WithExceptionDetails().WriteTo.File("c:\\logs\\log.txt");
Log.Logger = l.CreateLogger();
Log.Information("Service Starting");
Then magically the "log.txt" file is created and everything is logged into it, but using "Debug" settings, so again it looks like the config is not read.
This is my typical Serilog configuration:
<appSettings>
<!--Serilog-->
<add key="serilog:minimum-level" value="Debug" />
<!--trace logging-->
<add key="serilog:write-to:Trace" value="Serilog.Trace" />
<add key="serilog:write-to:Trace.restrictedToMinimumLevel" value="Debug" />
<!--rolling file logging-->
<add key="serilog:write-to:RollingFile" value="Serilog.RollingFileSink" />
<add key="serilog:write-to:RollingFile.restrictedToMinimumLevel" value="Information" />
<add key="serilog:write-to:RollingFile.pathFormat" value="C:\Logs\Service-{Date}.log" />
<add key="serilog:write-to:RollingFile.retainedFileCountLimit" value="10" />
</appSettings>
And below is the list of packages installed on the project configured as above:
<package id="Serilog" version="2.11.0" targetFramework="net48" />
<package id="Serilog.Enrichers.Environment" version="2.2.0" targetFramework="net48" />
<package id="Serilog.Enrichers.Process" version="2.0.2" targetFramework="net48" />
<package id="Serilog.Enrichers.Thread" version="3.1.0" targetFramework="net48" />
<package id="Serilog.Exceptions" version="8.4.0" targetFramework="net48" />
<package id="Serilog.Formatting.Compact" version="1.1.0" targetFramework="net48" />
<package id="Serilog.Settings.AppSettings" version="2.2.2" targetFramework="net48" />
<package id="Serilog.Sinks.Console" version="4.0.1" targetFramework="net48" />
<package id="Serilog.Sinks.EventLog" version="3.1.0" targetFramework="net48" />
<package id="Serilog.Sinks.File" version="5.0.0" targetFramework="net48" />
<package id="Serilog.Sinks.Observable" version="2.0.2" targetFramework="net48" />
<package id="Serilog.Sinks.PeriodicBatching" version="2.3.1" targetFramework="net48" />
<package id="Serilog.Sinks.Seq" version="5.1.1" targetFramework="net48" />
<package id="Serilog.Sinks.TextWriter" version="2.1.0" targetFramework="net48" />
<package id="Serilog.Sinks.Trace" version="3.0.0" targetFramework="net48" />
<package id="SerilogMetrics" version="2.1.0" targetFramework="net48" />
Anybody who can help please?
Thanks
In the end after looking at some different pieces of docs I've found what the missing bits were.
The updated configuration above needs to look like this:
<add key="serilog:using:File" value="Serilog.Sinks.File" />
<add key="serilog:write-to:File" value="Serilog.FileSink" />
<add key="serilog:write-to:File.restrictedToMinimumLevel" value="Information" />
<add key="serilog:write-to:File.path" value="C:\Logs\Service-.log" />
<add key="serilog:write-to:File.rollingInterval" value="Day" />
<add key="serilog:write-to:File.retainedFileCountLimit" value="10" />
The config above works the same as the previous configuration and without the need to use the deprecated RollingFile sink.
The key thing here is the "using" line: without that nothing gets logged and no exception is thrown.
The second thing is the additional "rollingInterval" line that appends the date to the provided file name (note the "pathFormat" changed into just "path" there).
Hope it can be useful for somebody else.

Log4Net not logging in .NET WebApi project using UnityContainer

I have a very basic C# .NET WebApi project using Unity.AspNet.WebApi and Unity.Mvc for dependency injection and Unity.log4net for logging.
The injection into my controllers seems to be working correctly. The problem is that the logger never logs anything. The expected .log file is never created. When I inspect the logger object while debugging it has all the levels disabled (IsDebugEnable = false, IsErrorEnabled = false, etc.)
It is running as if has ignored my log4net.config file. In the root of my project I have a log4net.config file that defines a console and a file appender.
<log4net>
<root>
<level value="ALL" />
<appender-ref ref="console" />
<appender-ref ref="file" />
</root>
<appender name="console" type="log4net.Appender.ConsoleAppender">
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date %level %logger - %message%newline" />
</layout>
</appender>
<appender name="file" type="log4net.Appender.RollingFileAppender">
<file value="DemoWebApiUnityLog4Net.log" />
<appendToFile value="true" />
<rollingStyle value="Size" />
<maxSizeRollBackups value="5" />
<maximumFileSize value="10MB" />
<staticLogFileName value="true" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %level %logger - %message%newline" />
</layout>
</appender>
</log4net>
I have added this line to AssemblyInfo.cs
[assembly: log4net.Config.XmlConfigurator(ConfigFile = #"log4net.config", Watch = true)]
The log4net was registered in to the Unity container in UnityConfig.cs with this line:
container.AddNewExtension<Log4NetExtension>();
The full demo project can be found here: https://github.com/CarmonColvin/DemoWebApiUnityLog4Net
Nothing I have tried has resulted in a successful log. Any help is appreciated.
According to the log4net FAQ:
If you are configuring log4net by specifying assembly level attributes on your assembly then the configuration will be loaded once the first call to the LogManager.GetLogger is made. It is necessary that the first call to LogManager.GetLogger made during the process (or AppDomain) is made from the assembly that has the configuration attributes. Log4net will look only once and only on the first calling assembly for the configuration attributes.
So it sounds to me like you should be calling LogManager.GetLogger() in Global.asax when the application starts in order to load your configuration. Something like:
using log4net;
protected void Application_Start(object sender, EventArgs e)
{
var logger = LogManager.GetLogger(typeof(Global));
logger.Info("Application started.");
}

Asp.net MVC log4net with lockingModel makes session lost

I get a MVC website and with the log4net to record the log.
In the web application, I store the user information in session, add log some information after executing one operation. Then the session lost when I returned to the home page(just type the url of the home page).
I am sure that the session lost which has no relation to the "Response.Redirect()" or something else, because I test the application and found it will recover after I comment the lockingModel property which value is "log4net.Appender.FileAppender+MinimalLock" in log4net config file.
Below is the configuration:
<?xml version="1.0"?>
<log4net debug="true">
<appender name="AllInfoRollingAppender" type="log4net.Appender.RollingFileAppender">
<file value="bin\\Log\\AllInfo-UniqueBlog-" />
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
<appendToFile value="true" />
<staticLogFileName value="false" />
<rollingStyle value="Composite" />
<datePattern value="yyyy-MM-dd.LOG" />
<maximumFileSize value="1M" />
<maxSizeRollBackups value="4" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger: %message%newline%exception" />
</layout>
</appender>
<root>
<level value="ALL" />
<appender-ref ref="AllInfoRollingAppender" />
</root>
</log4net>
So I think the "lockingModel" property in log4net config cause this error, but i don't know the reason, and it will not throw any error there, does anyone encounter this? I found it is inconceivable because this shouldn't cause this issue.
Your question is totally not readable. However I have to things you can check. If your session is lost, do you log before or after the Session.Redirec(). If you log after the session redirect, your code is never hit. The redirect ends your current thread. Next thing you can enable log4net debugging:
<configuration>
<appSettings>
<add key="log4net.Internal.Debug" value="true"/>
</appSettings>
...
<system.diagnostics>
<trace autoflush="true">
<listeners>
<add
name="textWriterTraceListener"
type="System.Diagnostics.TextWriterTraceListener"
initializeData="C:\tmp\log4net.txt" />
</listeners>
</trace>
</system.diagnostics>
...
</configuration>
If something bad happens in log4net, you will see it in the logs.

Where is the log file in log4net?

I've got the following entries in my Web.config file in an asp.net mvc application:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net" />
...
</configSections>
<log4net>
<appender name="PublicAccessAppender" type="log4net.Appender.RollingFileAppender">
<datePattern value="'C:\Users\my_user_name\Documents\Temp\logs\public-access.'yyyy-MM-dd'.log'" />
<staticLogFileName value="false" />
<appendToFile value="true" />
<rollingStyle value="Date" />
<maxSizeRollBackups value="5" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger - %message%newline" />
</layout>
</appender>
<root>
<level value="DEBUG" />
<appender-ref ref="PublicAccessAppender" />
</root>
</log4net>
...
</configuration>
I hope it's pretty self-explanatory what I'm trying to achieve, but when I run the application (hosted in IIS), I get no log file. FWIW, the directory hierarchy exists up to Temp folder, and I'd like log4net to generate the rest of the directories/files in the path.
I've added the log4net nuget package to my application, and I'm logging with the INFO level.
What am I missing here?
I think you can't put full path into datePattern, there must be just YYYYmmdd and things like that. Put the file path into file element:
<file value="C:\Users\my_user_name\Documents\Temp\logs\public-access.log" />
<datePattern value="yyyyMMdd" />
<preserveLogFileNameExtension value="true" />
The last element forces to put datePattern before the .log extension which was probably your original goal..
Here's the working appender configuration:
<appender name="PublicAccessAppender" type="log4net.Appender.RollingFileAppender">
<file value="C:\temp\my_user_name\Documents\Temp\logs\app.log" />
<datePattern value=".yyyy-MM-dd" /><!-- can be omitted as it's the default datePattern value -->
<rollingStyle value="Date" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger - %message%newline" />
</layout>
</appender>
Note to readers struggling with log4net configuration: asp.net hosted in IIS pretty much has 0 write permssions, so the issue you're most likely struggling with is that your web app simply doesn't have permission to write to the log file.
That's what was happening for me, and I noticed it by inspecting the contents of log4net.LogManager.GetRepository().ConfigurationMessages in the debugger after calling .Configure().
I followed this post to give my web app the necessary persmissions to write to the log file (namely Read/Write/Modify).

Stopping and uninstalling a different service when user uninstalls

Is there anyway to check to see if a service is installed, and if so, stop it and uninstall it when my application is being uninstalled using WiX 3.7? I don't want WiX to install the service though - just uninstall it.
I have WiX setup to install several application components, but the application itself CAN spawn a Windows Service (depending on features selected during install). I'm not really sure what the best way to clean that up is - I guess just to have my setup check if that service exists and remove it upon uninstall.
I'm not sure if I would need a CustomAction for that. I'm fairly familiar with installing services with WiX, but not JUST removing them (if it exists).
Here is my setup project. Just to give a little additional background on this, this is an auto-updater/launcher application. It takes a series of XML files to tell it how to update/prepare an application. If you choose the "MyApp Printer" feature, for example, it would install an extra XML file that tells my application how to hash check the local files against a web service and then install and start the "MyApp Printer" Windows Service for that component. The Windows Service that is located inside my actual WiX Setup Project is something completely different, and that works fine when uninstalling so please disregard that one.
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="*" Name="MyApp ID" Language="1033" Version="1.0.0.0" Manufacturer="MyApp ID" UpgradeCode="932dbe1f-e112-4bd0-8f60-b81850fb465b">
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<MediaTemplate EmbedCab="yes" />
<WixVariable Id="WixUILicenseRtf" Value="EULA.rtf" />
<Feature Id="ProductFeature" Title="MyApp ID Setup Core" Level="1" Absent="disallow" Display="expand">
<ComponentGroupRef Id="ProductComponents" />
<ComponentRef Id="MyAppStartMenuFolderRemove" />
<Feature Id="MyAppClientFeature" Title="MyApp ID Windows Client" Level="1" Absent="allow">
<ComponentGroupRef Id="MyAppClientComponents" />
<ComponentRef Id="MyAppStartMenuIcon" />
</Feature>
<Feature Id="MyAppPrinterFeature" Title="MyApp ID Printer App" Level="2" Absent="allow">
<ComponentGroupRef Id="MyAppPrinterComponents" />
<ComponentRef Id="PrinterStartMenuIcon" />
</Feature>
</Feature>
<UIRef Id="WixUI_FeatureTree" />
<UIRef Id="WixUI_ErrorProgressText" />
</Product>
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="MyAppBaseFolder" Name="MyAppID">
<Directory Id="INSTALLFOLDER" Name="MyAppLauncher">
<Directory Id="UPDATESCRIPTSFOLDER" Name="Scripts" />
</Directory>
</Directory>
</Directory>
<Directory Id="ProgramMenuFolder">
<Directory Id="ApplicationProgramsFolder" Name="MyApp ID"/>
</Directory>
</Directory>
</Fragment>
<Fragment>
<DirectoryRef Id="ApplicationProgramsFolder">
<Component Id="PrinterStartMenuIcon">
<Shortcut Id="PrinterStartMenuShortcut"
Name="MyApp ID Printer UI"
Description="Manage the MyApp ID Printer Service"
Icon="MyAppPrinterIcon"
Target="[INSTALLFOLDER]AutoUpdater.exe"
Arguments="MyAppPrinter"
WorkingDirectory="INSTALLFOLDER">
<Icon Id="MyAppPrinterIcon" SourceFile="$(var.AutoUpdater.Launcher.TargetDir)\Resources\MyApp_printer_white.ico" />
</Shortcut>
<RegistryValue Root="HKCU" Key="Software\Microsoft\MyApp.CardPrinter.Service" Name="installed" Type="integer" Value="1" KeyPath="yes"/>
</Component>
<Component Id="MyAppStartMenuIcon">
<Shortcut Id="MyAppStartMenuShortcut"
Name="MyApp ID"
Description="Run the MyApp ID Windows Client software"
Target="[INSTALLFOLDER]AutoUpdater.exe"
Arguments="MyAppClient"
WorkingDirectory="INSTALLFOLDER"/>
<RegistryValue Root="HKCU" Key="Software\Microsoft\MyApp.WindowsClient" Name="installed" Type="integer" Value="1" KeyPath="yes"/>
</Component>
<Component Id="MyAppStartMenuFolderRemove">
<RemoveFolder Id="ApplicationProgramsFolder" On="uninstall"/>
<RegistryValue Root="HKCU" Key="Software\Microsoft\MyApp.WindowsClient" Name="installedFolder" Type="integer" Value="1" KeyPath="yes"/>
</Component>
</DirectoryRef>
</Fragment>
<Fragment>
<ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
<Component Id="LibrariesComponent" Guid="7ED3B3B3-A984-44ED-9BA3-841F53CEA114">
<File Source="$(var.AutoUpdater.Foundation.TargetPath)" Vital="yes" KeyPath="yes" />
<File Source="$(var.AutoUpdater.Module.TargetPath)" Vital="yes" />
<File Source="$(var.AutoUpdater.Module.WebService.TargetPath)" Vital="yes" />
</Component>
<Component Id="ServiceComponent" Guid="CAB8D997-5798-4B9D-8CA0-78AACE58932E">
<File Source="$(var.AutoUpdater.Service.TargetPath)" Vital="yes" KeyPath="yes" />
<File Source="$(var.AutoUpdater.Service.TargetDir)\AutoUpdater.Service.exe.config" Name="AutoUpdater.Service.exe.config" Vital="yes" />
<ServiceInstall Name="ServiceComponentInstall" Id="ServiceComponentInstall" DisplayName="MyApp ID Launcher" Account="LocalSystem" ErrorControl="normal" Type="ownProcess" Start="auto" Vital="yes" />
<ServiceControl Name="ServiceComponentInstall" Id="ServiceComponentControl" Start="install" Stop="both" Remove="uninstall" Wait="yes" />
</Component>
<Component Id="LauncherComponent">
<File Source="$(var.AutoUpdater.Launcher.TargetPath)" Vital="yes" />
<File Source="$(var.AutoUpdater.Launcher.TargetDir)\Resources\MyApp_printer_white.ico" Name="MyApp_printer_white.ico" />
</Component>
</ComponentGroup>
</Fragment>
<Fragment>
<ComponentGroup Id="MyAppClientComponents" Directory="UPDATESCRIPTSFOLDER">
<Component Id="MyAppClientXml">
<File Source="$(var.AutoUpdater.Service.TargetDir)\Scripts\MyAppClient.xml" Name="MyAppClient.xml" />
</Component>
</ComponentGroup>
</Fragment>
<Fragment>
<ComponentGroup Id="MyAppPrinterComponents" Directory="UPDATESCRIPTSFOLDER">
<Component Id="MyAppPrinterXml">
<File Source="$(var.AutoUpdater.Service.TargetDir)\Scripts\MyAppPrinter.xml" Name="MyAppPrinter.xml" />
</Component>
</ComponentGroup>
</Fragment>
</Wix>
I hope that wasn't too confusing :). Thanks in advance!
EDIT:
Thank you Rob, the solution was to add the <ServiceControl> element to the last Fragment:
<Fragment>
<ComponentGroup Id="MyAppPrinterComponents" Directory="UPDATESCRIPTSFOLDER">
<Component Id="MyAppPrinterXml">
<File Source="$(var.AutoUpdater.Service.TargetDir)\Scripts\MyAppPrinter.xml" Name="MyAppPrinter.xml" />
<ServiceControl Id="NukeMyAppPrinterService" Name="MyApp ID Printer Service" Remove="uninstall" Stop="uninstall" />
</Component>
</ComponentGroup>
</Fragment>
It will work whether or not that "MyApp ID Printer Service" is installed or not. I love the easy solutions!
Can't say I've done this myself (this is a pretty unique scenario) but the ServiceControl element should do the work just fine:
<ServiceControl Id='NukeService' Name='YourServiceName'
Remove='uninstall' Stop='uninstall' />

Resources