How to register a COM component with rollback?
I have the .exe that does the registering
thanks
Probably you can do the registration from one of the Custom Actions (e.g. project events). Though as far as I know WiX strongly encourages registering COM via registry manipulation.
I am using one custom action and it does not seem to work do I need higher privileges do I set them up to admin
C#
var project = new ManagedProject(productName,
new Dir($@"%ProgramFiles%\ACL\{solutionName}\{productName}",
new Files(filesPath), new File(msoPath), new File(rtdPath),
new File(new Id("registrator_exe"), regPath))
)
{
GUID = installerGuid,
ManagedUI = new ManagedUI(),
Actions = new Action[]
{
// execute installed application
new InstalledFileAction("registrator_exe", "/u", Return.check, When.Before, Step.InstallFinalize,
Condition.Installed),
new InstalledFileAction("registrator_exe", "", Return.check, When.After, Step.InstallFinalize,
Condition.NOT_Installed)
}
};
If you want to register the COM server this way you may need to start it with elevation. The easiest way to do that is form the elevated custom action (see the samples) or from normal action (e.g. ):
C#
static void run(string app, string args)
{
var startInfo = new ProcessStartInfo();
startInfo.UseShellExecute = true;
startInfo.WorkingDirectory = Environment.CurrentDirectory;
startInfo.FileName = "msiexec.exe";
startInfo.Arguments = "/i \"" + session.Property("OriginalDatabase") + "\"";
startInfo.Verb = "runas";
Process.Start(startInfo);
}
. . .
project.BeforeInstall += args =>
{
if (!args.IsUninstalling)
run(args.InstallDir.PathJoin("registrator_exe"), "/u");
else
run(args.InstallDir.PathJoin("registrator_exe"), "");
};
I know how to do it in Wix how to translate in wixSharp please
I am not sure we are on the same page. In my previous email I shared the sample how you register a com component from events (simplified custom actions). This is arguably the simplest way to do it. Did you try it?
If you want the exact equivalent of your WiX sample then your code probably very close to it. You'll just need to ensure your actions are deferred and you are using the exact file IDs. Have a look at "DeferredActions" sample.
new WixSharp.Action(Return.check, When.Before, Step.InstallFinalize, Condition.NOT_Installed)
{
Impersonate = true,
Execute=Execute.deferred,
AttributesDefinition = "BinaryKey=adxregistrator_exe;"+
"ExeCommand=/install="[INSTALLDIR]adxregistrator.exe""
}
Another hint - look at the generated WiX file. It will give you exact idea what you are missing.
1) I have tried the first suggestion and there are c# syntax errors:
a) startInfo.Arguments = "/i \"" + session.Property("OriginalDatabase") + "\""; session is not recognised
b) run(args.InstallDir.PathJoin("registrator_exe"), "/u"); again PathJoin I get c# syntax errors
c) run is not recognised but it probably is up to me to define it.
Thanks for the last suggestion I will have a go
C#
new WixSharp.Action(Return.check, When.Before, Step.InstallFinalize, Condition.NOT_Installed)
{
Impersonate = true,
Execute=Execute.deferred,
AttributesDefinition = "BinaryKey=adxregistrator_exe;"+
"ExeCommand=/install="[INSTALLDIR]adxregistrator.exe""
}
bear in mind WixSharp.Action is a protected class and cannot be instantiated directlly .
I am grateful for your time. I have used wixsharp for a while now and it has served me well. I feel there may be breaking changes in the last version.
regards Laz
BT, I have checked and found that WixSharp.Action is actually public and the constructors are simple made protected by mistake.
It is fixed now. The fix will be available in the very next release.
Maybe better to use BinaryFileAction?
Install:
```C#
new BinaryFileAction("adxregistrator_exe", "/install=\"[INSTALLDIR]adxregistrator.exe\"", "adxregistrator_exe", "/uninstall=\"[INSTALLDIR]adxregistrator.exe\"")
{
Impersonate = true,
Execute = Execute.deferred,
Return = Return.check,
Step = Step.InstallFinalize,
When = When.Before,
Condition = Condition.NOT_Installed,
});
Uninstall:
```C#
new BinaryFileAction("adxregistrator_exe", "/uninstall=\"[INSTALLDIR]adxregistrator.exe\"", "adxregistrator_exe", "/install=\"[INSTALLDIR]adxregistrator.exe\"")
{
Impersonate = true,
Execute = Execute.deferred,
Return = Return.check,
Step = Step.InstallFinalize,
When = When.Before,
Condition = Condition.Installed,
});
Hi Oleg
many thanks for your help. Excellent solution my favourite in fact. the installation partially works but registration is not happening I believe somehow I need elevated privileges, the impersonate may not be sufficient. Any idea?
Thanks Laz
There is no need for Impersonate.
Impersonate causes the installer to perform an action on behalf of System, but you need to perform an action from the user who launched the installer.
Use Impersonate = false
I believe somehow I need elevated privileges
Yes you do. And 29 days ago I have provided you the sample that does the elevation. Did you try it?
And of course you have @Xaddan solution as well.
``` C#
project.BeforeInstall += args => Run(args.InstallDir.PathJoin("registrator_exe"), !args.IsUninstalling ? "/u" : "");
**I got an error saying ambiguous invocation. and "registrator_exe" underlined**
```C#
private static void Run(string app, string args)
{
var startInfo = new ProcessStartInfo
{
UseShellExecute = true,
WorkingDirectory = Environment.CurrentDirectory,
FileName = "msiexec.exe",
Arguments = "/i \"" + session.Property("OriginalDatabase") + "\"",
Verb = "runas"
};
Process.Start(startInfo);
}
I got an error "The name session does not exist in this context"
Regards Thanks
The sample I gave you was a pseudo-code that needed adjustments to reflect your specific deployment scenario. The implementation of the Run was also taken from WixSharp codebase and contained invalid (for your scenario) bits.
Assuming:
-install -uninstall You will need to adjust your code like this.
```C#
static void run(string app, string args)
{
var startInfo = new ProcessStartInfo();
startInfo.UseShellExecute = true;
startInfo.WorkingDirectory = Environment.CurrentDirectory;
startInfo.FileName = app;
startInfo.Arguments = args;
startInfo.Verb = "runas";
Process.Start(startInfo);
}
. . .
project.BeforeInstall += args =>
{
if (!args.IsUninstalling)
run(args.InstallDir.PathJoin("myComServer.exe"), "-uninstall");
else
run(args.InstallDir.PathJoin("myComServer.exe"), "-install");
};
If your com server is a dll (myComServer.dll), then it is like below:
```C#
. . .
if (!args.IsUninstalling)
run("regsvr32.exe", "\"" + args.InstallDir.PathJoin("myComServer.dll") + "\" /u");
else
run("regsvr32.exe", "\"" + args.InstallDir.PathJoin("myComServer.dll") + "\" /i");
Hi
Grateful for the help. All your assumptions are correct.
1 - //project.BeforeInstall += args => Run(Path.Combine(args.InstallDir, "adxregistrator.exe"),
// !args.IsUninstalling ? "-uninstall" : "-install");
project.BeforeInstall += args => Run(args.InstallDir.PathJoin("adxregistrator.exe"),
!args.IsUninstalling ? "-uninstall" : "-install");
I still get the ambigious invocation using the PathJoin I replaced by Path.Combine
The installer runs fine no errors But no files have been installed in the target directory. When I right click on the msi and select uninstall I get the message indicating no product is installed.
you may want to run your msi with logging and have a look at the log file. if msi is indicating that "no product is installed" then probably it was an error.
Hi
Yes there an error
Info: Calling custom action WixSharp!WixSharp.ManagedProjectActions.WixSharp_BeforeInstall_Action
Info: WixSharp aborted the session because of the error:
System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.ComponentModel.Win32Exception: The system cannot find the file specified
at System.Diagnostics.Process.StartWithShellExecuteEx(ProcessStartInfo startInfo)
at System.Diagnostics.Process.Start()
at System.Diagnostics.Process.Start(ProcessStartInfo startInfo)
at Core.Installer.AclInstaller.Run(String app, String args)
at Core.Installer.AclInstaller.<>c.
--- End of inner exception stack trace ---
at System.RuntimeMethodHandle.InvokeMethod(Object target, Object arguments, Signature sig, Boolean constructor)
at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object parameters, Object arguments)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object parameters, CultureInfo culture)
at WixSharp.ManagedProject.InvokeClientHandler(String info, SetupEventArgs eventArgs)
at WixSharp.ManagedProject.InvokeClientHandlers(Session session, String eventName, IShellView UIShell)
Info: CustomAction WixSharp_BeforeInstall_Action returned actual error code 1603 (note this may not be 100% accurate if translation happened inside sandbox)
Info: Action ended 19:52:30: WixSharp_BeforeInstall_Action. Return value 3.
CommonData: Message type: 2, Argument: 0
CommonData: Message type: 2, Argument: 1
Info: Action ended 19:52:30: INSTALL. Return value 3.
InstallEnd: 1: ExcelLogix 2: {11C8C916-1DA7-4DCB-8956-5A5B41CC171B} 3: 3
CommonData: 1: 2 2: 0
CommonData: 1: 2 2: 1
private static void Run([NotNull] string app, [NotNull] string args)
{
var startInfo = new ProcessStartInfo
{
UseShellExecute = true,
WorkingDirectory = Environment.CurrentDirectory,
FileName = app,
Arguments = args,
Verb = "runas"
};
Process.Start(startInfo);
}
I will have to use my project logger to log more info and find out why
Thanks for your help
Of curse! Silly mistake.
Simply the app file is not installed at that time.
You will need to execute uninstall from Project.BeforeInstall and install from Project.AfterInstall.
Hi Oleg
I spotted that yesterday and was not sure. will do. Thanks very much
Laz
Hi Oleg
I attempted as suggested by using Project.AfterInstall, several issues arose,
1 - UseShellExecute = false, : To use the Environment.CurrentDirectory this property needed to be set to false.
2 - The installation ran through OK then I attempted to uninstall and I could not uninstall the App, is there a project.BeforeUninstall? I tried to uninstall to no avail what happens the un-installation runs then rolls back. I believe it is the same error where it cannot find the file...
Severity Code Description Project File Line Suppression State
4 - When I took a look at the Wix folder two files with the exact name have been generated and appeared to have the same content. I deleted the wix folder rebuilt but still the same error and two "Core.Installer.g.wxs" files are generated in the wix folder. (Core.Installer is my project name)
I am sorry if this has been dragging on a bit , I am a wixsharp fan.
regards Laz
Hi Oleg
I have now tried the binaryFileAction suggestion with impersonate set to false and it works very well and my com object registers and the entire installed app works as expected.
Thanks for your help and unless you would like me to pursue the event method I am happy to close the issue.
kind regards Laz
I am glad you found the solution.
Though just to address some confusion:
1 - UseShellExecute = false, : To use the Environment.CurrentDirectory this property needed to be set to false.
The point is that you don't want to use Environment.CurrentDirectory so you need to set UseShellExecute = true in order to for the elevation to happen.
...is there a project.BeforeUninstall?
Yes there is. This is what you want to do foe the event driven approach:
```C#
project.BeforeInstall += args =>
{
if (args.IsUninstalling)
run(args.InstallDir.PathJoin("myComServer.exe"), "-uninstall");
};
project.AfterInstall += args =>
{
if (!args.IsUninstalling)
run(args.InstallDir.PathJoin("myComServer.exe"), "-install");
};
```
3 - I now have an additional issue when I build the ...
This cannot be diagnosed without knowing what is installed and how.
...4 - When I took a look at the Wix folder two files with the exact name have been generated and appeared to have the same content.
If you can, please send me your project file as it might be some problem with it. Please remove from it all sensitive content before sending
Hi Oleg
Please get my project from聽https://1drv.ms/u/s!Ai1jsiYR5baCjOhahvepRIb0xWjxKQ.
聽I had some breaking changes in the dialogs after updating wixsharp again you helped with the solution.
I am also having issue with building the project in release mode I get :
Severity Code Description Project File Line Suppression StateError The command ""C:\Dev\src\Products\Core.Installer\bin\Release\Core.Installer.exe" "/MSBUILD:Core.Installer" "/WIXBIN:"" exited with code -532462766. Core.Installer C:\Dev\src\Products\packages\WixSharp.1.9.2\build\WixSharp.targets 6
no issue building in debug mode
regards Laz
Thank you Laz,
Unfortunately your project cannot be built. There missing dependencies and it also fails to restore the packages. Though it did dive me idea about the content of the Wix sub-folder. It does actually not contain two *.g.wxs files as I was afraid if. Simply the project file contains two entries with the same _effective_ name but pointing to the same *.g.wsx file.
<None Include="wix\Core.Installer.g.wxs" />
<None Include="wix\$(ProjectName).g.wxs" />
It is most likely a result of the updating WixShapr package to the latest version in that project.
It is a side effect of the latest change in the NuGet package structure and it has no effect on the outcome of building the msi.
As for the VS project, you can get read of that extra item by removing the <None Include="wix\Core.Installer.g.wxs" /> item from the project file manually. Or by deleting the item from the solution explorer.
Hi Oleg
Many thanks again for the assistance. In any case the project builds OK and the installer works well when in debug. Any idea as to why I can't build it in Release mode? The error seems to be in this xml file
Regards Laz
Laz, you should stop using email to respond. It publishes your surname and phone number. I keep editing your responses and removing all sensetive information but you should start using Github to send responses instead.
I cannot reproduce the problem as the project is not built. If you can simplify it so it can be build without any dependencies then I can have a look at it. Otherwise it's not much I can do.
Hi Oleg
Thanks very much for your help all is now solved the error when building in release mode was due to a syntax error somehow the debug did not mind it for some reason.
I am now finally closing the case thanks again for persisting with the help I was eager to continue using WixSharp as I have all my dialogs customised to my company pictures and logs.
regards Laz