WiX Custom Action to check firewall status causes installer to fail - c#

I have implemented a WiX Custom Action in C# to check whether the Windows firewall is on or off.
I tested the code with a C# console application and it worked without problems.
However, when I use the code in a WiX Custom Action it causes the installer to fail at run-time, with the following error in the msiexec error log:
DEBUG: Error 2755: Server returned unexpected error 1622 attempting to
nstall package MyInstaller.msi.
The installer has encountered an unexpected error installing this package.
This may indicate a problem with this package. The error code is 2755.
The arguments are: 1622, MyInstaller.msi,
Action ended 11:26:30: ExecuteAction. Return value 3.
Action 11:26:30: FatalError.
Action start 11:26:30: FatalError.
Action 11:26:30: FatalError. Dialog created
Action ended 11:26:31: FatalError. Return value 2.
Action ended 11:26:31: INSTALL. Return value 3.
Type NetFwMgrType = Type.GetTypeFromProgID("HNetCfg.FwMgr", true);
INetFwMgr fwMgr = Activator.CreateInstance(NetFwMgrType) as INetFwMgr;
bool Firewallenabled = fwMgr.LocalPolicy.CurrentProfile.FirewallEnabled;
MessageBox.Show("Firewall enabled: " + Firewallenabled.ToString());
In my WiX XML file the CA is like this:
<CustomAction Id="CheckWindowsFirewallId"
BinaryKey="CustomActions.dll"
DllEntry="CheckWindowsFirewall" Execute="deferred" Impersonate="no" Return="check"/>
<InstallExecuteSequence>
<Custom Action="CheckWindowsFirewallId" After="InstallInitialize">NOT Installed</Custom>
I am using Visual Studio 2005, Windows XP, WiX version 3.6.1321.0
I am logged in as admininstrator.
I know exactly which line causes in the problem.
If I comment out the line with "Activator.CreateInstance(NetFwMgrType)" the error does not occur.
I have tried several different combinations of 'deferred' and 'impersonate' with no success.
If I can't get it to work I will try the WiX Firewall Extension instead, but it would be great if someone has an idea why it doesn't work.

There isn't enough information to know for sure. However, my magic eight ball guesses that the assembly your trying to activate a class out of isn't available. The best thing would be to get a debugger on the code and look at the exception. If you're having trouble doing that, catching the exception and writing it to the log file might be useful as well.
I also agree with Yan's comment above. I'd recommend using the built in support for Firewalls in WiX instead of writing your own code if possible.

Related

Windows Service - UnauthorizedAccessException Error when Installing Service (C#)

So I am trying to create a service using C# in Visual Studio 2017 and I keep getting an error when I try to install it.
Right now, I don't even have anything in my service, I just want to be able to install the service. I created a new Project in Visual Studio 2017 using the Windows Service (.NET Framework) template under Visual C# > Windows Desktop. I then added the installer via Right Click > Add Installer. For serviceProcessInstaller1, I set the account to LocalSystem. And...that's it!
Now, I try to install it. I open up command prompt (run as administrator) and I do
InstallUtil ServiceTest.exe
Things start off smoothly, but then I get a message:
"An exception occured during the Install phase.
System.UnauthorizedAccessException: Attempted to perform an
unauthorized operation."
What could be generating this message?
I've googled and tried the following things:
Ensure I run command prompt as administrator.
Assign Full Control to
the project folder to my admin account.
Configure permissions to Full
Control for admin account in the security log of regedit.
Log into my
computer as an administrator (rather than regular user) and run it
that way.
Despite these things, I keep getting the same error. What else could I be doing wrong? Would really appreciate some advice!
Note: I am trying to install this service locally on my computer.
Edit: Per request, here are the logs. I named my project "FailedService", by the way, since I can't get it to work!
InstallUtil.InstallLog
Running a transacted installation.
Beginning the Install phase of the installation.
See the contents of the log file for the C:\Users\first.m.last\source\repos\FailedService\FailedService\bin\Debug\FailedService.exe assembly's progress.
The file is located at C:\Users\first.m.last\source\repos\FailedService\FailedService\bin\Debug\FailedService.InstallLog.
An exception occurred during the Install phase.
System.UnauthorizedAccessException: Attempted to perform an unauthorized operation.
The Rollback phase of the installation is beginning.
See the contents of the log file for the C:\Users\first.m.last\source\repos\FailedService\FailedService\bin\Debug\FailedService.exe assembly's progress.
The file is located at C:\Users\first.m.last\source\repos\FailedService\FailedService\bin\Debug\FailedService.InstallLog.
The Rollback phase completed successfully.
The transacted install has completed.
FailedService.InstallLog
Installing assembly 'C:\Users\first.m.last\source\repos\FailedService\FailedService\bin\Debug\FailedService.exe'.
Affected parameters are:
logtoconsole =
logfile = C:\Users\first.m.last\source\repos\FailedService\FailedService\bin\Debug\FailedService.InstallLog
assemblypath = C:\Users\first.m.last\source\repos\FailedService\FailedService\bin\Debug\FailedService.exe
Installing service Service1...
Creating EventLog source Service1 in log Application...
Rolling back assembly 'C:\Users\first.m.last\source\repos\FailedService\FailedService\bin\Debug\FailedService.exe'.
Affected parameters are:
logtoconsole =
logfile = C:\Users\first.m.last\source\repos\FailedService\FailedService\bin\Debug\FailedService.InstallLog
assemblypath = C:\Users\first.m.last\source\repos\FailedService\FailedService\bin\Debug\FailedService.exe
Restoring event log to previous state for source Service1.
I was FINALLY able to resolve this issue. I was able to get to the bottom of it by using SysInternal's Process Monitor. I opened up the program and had it take logs for InstallUtil.exe. From there, I began to search for any logs that said "Access Denied". As I sorted through them, I noticed something interesting: it was trying to create a registry key, but it kept failing!
So I went into the registry and created a key named "ServiceTest". After that, I ran the InstallUtil command again, and it worked!
If anyone else is having trouble, the solution is to create a key named after your process name in the following location:
HKLM\System\CurrentControlSet\Services\EventLog\Application\
Enter the full path to installUtil & your service binary in an elevated prompt, that could do.

Uninstall leads to 1603 error on windows 10 1703

We have a Windows 10 1607 image with our app installed via Advanced Installer.
We then updated the app to a new version and the update worked as excepted.
However if we do the same procedure but with a Windows 10 1703 image, the upgrade of our app fails with the following error:
MSI (s) (58:B8) [16:12:02:846]: Note: 1: 2769 2: ShopInstallClass_x64 3: 1
Error 1001. Error 1001. The specified service has been marked for deletion
Info 2769. Custom Action ShopInstallClass_x64 did not close 1 MSIHANDLEs.
CustomAction ShopInstallClass_x64 returned actual error code 1603 (note this
may not be 100% accurate if translation happened inside sandbox)
MSI (s) (58:EC) [16:12:02:858]: Note: 1: 2265 2: 3: -2147287035
MSI (s) (58:EC) [16:12:02:860]: User policy value 'DisableRollback' is 0
MSI (s) (58:EC) [16:12:02:860]: Machine policy value 'DisableRollback' is 0
Action ended 16:12:02: InstallExecute. Return value 3
The custom action above refers to a windows service which is being uninstalled and then reinstalled with the new update. I tried putting a stop service and even a stop process to see if that would work (possibly handles left open) and the installer still did not work.
Any ideas why this is happening?
The code in the custom action has crashed, I assume you know that. Without showing more of the log it's also not clear where in the upgrade it's happening, if in fact you're referring to a major upgrade when you say "update". In a major upgrade there's an install of the new product and an uninstall of the older one - where is this crash happening in that sequence? It's also possible that your ShopInstall class is an installer class to install a service, which isn't necessary because Windows Installer has ServiceInstall actions for that.
Having said that, the message "The specified service has been marked for deletion" implies that the code is trying to do something to a disabled service. So it looks like a previous uninstall of the service has been attempted, and the service did not shut down or stop correctly. In that situation Windows will mark the service disabled and then a reboot will finally delete it. In the meantime if something tries to do something with that service it will fail with the "pending deletion" error. So you'd have to go back to whatever uninstall was attempted and why it failed to first stop, and then uninstall the service.

"The handle is invalid" exception in Visual Studio 2015 test runner

I found that one of my tests that passes in VS2013 is failing in VS2015, the test calls a service that includes among other things a call to Console.Clear();
to find out whats going on I made a simple unit test
[TestMethod]
public void ExampleTest()
{
Console.Clear();
}
This test passes in visual studio 2013 but in 2015 I get the following error:
Test Name: ExampleTest
Test FullName: solution.Common.Test.CacheManagerTest.ExampleTest
Test Source: C:\solution.Common.Test\CacheManagerTest.cs : line 34
Test Outcome: Failed
Test Duration: 0:00:00.3015003
Result StackTrace: at System.IO.__Error.WinIOError(Int32 errorCode,
String maybeFullPath) at System.Console.GetBufferInfo(Boolean
throwOnNoConsole, Boolean& succeeded) at System.Console.Clear()
at sol.Common.Test.CacheManagerTest.ExampleTest() in
C:\solution.Common.Test\CacheManagerTest.cs:line 35 Result Message:
Test method Alexandria.Common.Test.CacheManagerTest.ExampleTest threw
exception: System.IO.IOException: The handle is invalid.
I do understand that it is bad design for my service to fail if it is not called by a console. The reason I am asking this question is to understand why this is failing in the new version of Visual Studio. Is this the intended behavior? What changed?
I did not see anything obvious in the change log that would seem related to this.
Edit: I am calling the Console.clear from the following dll
Microsoft\Framework.NETFramework\v4.5.1\mscorlib.dll
Edit 2:
picture of testproject properties in both visual studios
The changes in VS2015 are pretty visible, use the Test > Debug > All Tests to get insight. You can see that it now has a new test host process, its name is TE.ProcessHost.Managed.exe, stored in the C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\CommonExtensions\Microsoft\TestWindow directory.
Previous versions of VS used a different host, vstest.executionengine.exe. One notable change in the new test host is that it is no longer a console mode program. Something you can see by running Dumpbin.exe /headers on the exe.
Another way to see the underlying problem is with Task Manager. Note how running a test in an older VS version causes a conhost.exe process to get added. This is the process that owns the console window for a console mode app. A problem I've seen before is that this process tends to leak, not terminating when the test completes. Adding ever more conhost.exe instances, at one point researching this problem I had 12 of them running. Presumably the changes in VS2015 were meant to address that problem.
Technically you can configure the unit test with a .runsettings file and use the <ForcedLegacyMode> element to force the old test host process to be used. This however has no effect on the outcome of this test, looks like they addressed this in multiple ways.
That's a fair amount of guessing, I recommend you use connect.microsoft.com to file a feedback report. You can quote this Q+A for reference.
Meanwhile, you can consider a workaround. Do note that Console.Clear() is in general a trouble-maker, it will also fail in normal usage when the output of a console mode app is redirected. Very easy to do from a command line prompt with the > operator. Which is the ultimate reason it fails in a unit test. You'll want to make the code resilient so it can work properly both in production and in a unit test. Like this:
if (!Console.IsOutputRedirected) Console.Clear();
Which requires targeting .NET 4.5 or higher. You can use the code in this SO post if you need to target earlier versions.

WiX Custom Action Ends Prematurely

There are multiple questions on that topic, I tried all the solutions but nothing worked for me.
The problem is that it 'does' work on machines with visual studio installed, but does not work on other pc's.. making it very hard to debug.
The custom action code is:
[CustomAction]
public static ActionResult EnumerateSqlServers(Session session)
{
MessageBox.Show("start EnumerateSQLServers"); // the message is not showing.
ActionResult result;
DataTable dt = SmoApplication.EnumAvailableSqlServers(false);
DataRow[] rows = dt.Select(string.Empty);//, "IsLocal desc, Name asc");
result = EnumSqlServersIntoComboBox(session, rows);
return result;
}
The log file shows:
MSI (c) (2C:1C) [11:16:42:338]: Doing action: EnumerateSqlServersAction
Action 11:16:42: EnumerateSqlServersAction.
Action start 11:16:42: EnumerateSqlServersAction.
MSI (c) (2C:34) [11:16:42:385]: Invoking remote custom action. DLL: C:\Users\Test\AppData\Local\Temp\MSI9328.tmp, Entrypoint: EnumerateSqlServers
MSI (c) (2C:E8) [11:16:42:385]: Cloaking enabled.
MSI (c) (2C:E8) [11:16:42:385]: Attempting to enable all disabled privileges before calling Install on Server
MSI (c) (2C:E8) [11:16:42:385]: Connected to service for CA interface.
Action ended 11:16:42: EnumerateSqlServersAction. Return value 3.
DEBUG: Error 2896: Executing action EnumerateSqlServersAction failed.
The installer has encountered an unexpected error installing this package. This may indicate a problem with this package. The error code is 2896. The arguments are: EnumerateSqlServersAction, ,
Action ended 11:16:42: WelcomeDlg. Return value 3.
MSI (c) (2C:44) [11:16:42:635]: Doing action: FatalError
Action 11:16:42: FatalError.
Action start 11:16:42: FatalError.
Action 11:16:42: FatalError. Dialog created
Action ended 11:16:43: FatalError. Return value 2.
Action ended 11:16:43: INSTALL. Return value 3.
MSI (c) (2C:44) [11:16:43:370]: Destroying RemoteAPI object.
MSI (c) (2C:E8) [11:16:43:385]: Custom Action Manager thread ending.
I did try a empty action like this:
[CustomAction]
public static ActionResult CustomAction1(Session session)
{
MessageBox.Show("");
return ActionResult.Success;
}
that action works! it shows an empty message box.
EDIT: After a lot of testing, I found that the problem is with enumSQLServer when I comment this line it works.
SmoApplication.EnumAvailableSqlServers(false);
Log the installer using verbose (/l*v) settings. I expect to see a lot more including a .NET error stack trace. You are likely missing a dependency that's on the visual studio machine but not your clean test machine.
The most likely missing dependency is Microsoft.SqlServer.Smo.dll. In your custom action project check to see if this reference is set to CopyLocal = true and set it if it is not.
Did you already try to run your setup with elevated rights (right click on the setup and select "Run as administrator")?
SmoApplication.EnumAvailableSqlServers(false) needs elevated rights as far as I know.
Also check your definition of your custom action in your Product node within your .wxs file.
Following definition should work:
<CustomAction
Id="EnumerateSqlServers"
BinaryKey="YOUR BINARY KEY"
DllEntry="EnumerateSqlServers"
Execute="immediate"
Return="check"/>
Also try the following for testing purposes:
<InstallUISequence>
<Custom Action="EnumerateSqlServers"
Before="ExecuteAction"
Overridable="yes">NOT Installed</Custom>
</InstallUISequence>
In my case, this was happening on the install AND uninstall.
What we're doing is encrypting the connection string that was being passed in as a parameter.
Install
This fails because I don't have access to the installed config file which we're still working out. I wish WiX was a little easier to use or had better documentation.
Uninstall
Because we didn't have any conditions for the Custom Action, it was also running during uninstall and failing when attempting to load the config file that doesn't exist anymore.
Solution: Use NOT Installed AND NOT REMOVE. How to execute custom action only in install (not uninstall)

cannot uninstall a windows service: "...cannot be deleted, because it's equal to the log name."

I need to uninstall a Windows Service I have created, but I get this error using the "Uninstall or change program" program in windows:
Error. An exception occurred while
uninstalling. This exception will be
ignored and the uninstall will
continue. However, the application
might not be fully uninstalled after
the uninstall is complete. -> The
event log source '111 My Service'
cannot be deleted, because it's equal
to the log name.
Then I click "OK" and the program remains listed in the list of installed programs. What is worse, I cannot install a new version of it. The windows installer says that another version of this product is already installed and I should uninstall it first. How do I get rid of this program?
Update Here is what is happening when I run InstallUtil.exe /u command on it.
The uninstall is beginning. See the
contents of the log file for the
C:\MyService.MyService. assembly's progress. The file
is located at
C:\MyService.MyService.InstallLog.
Uninstalling assembly
'C:\MyService.MyService.exe'. Affected
parameters are: logtoconsole =
assemblypath = C:\MyService.exe
logfile =
C:\MyService.MyService.InstallLog
Removing EventLog source 111 My
Service. An exception occurred during
the uninstallation of the
System.Diagnostics.EventLogInstaller
installer.
System.InvalidOperationException: The
event log source '111 My Service'
cannot be deleted, because it's equal
to the log name. An exception occurred
while uninstalling. This exception
will be ignored and the uninstall will
continue. However, the application
might not be fully uninstalle l is
complete.
The uninstall has completed. An
exception occurred while uninstalling.
This exception will be ignored and the
uninstall will continue. However, the
application might not be fully
uninstalle l is complete.
Try to execute next command in cmd:
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\InstallUtil.exe /u "c:\myservice.exe"
The second option is:
sc delete <service name>
After running the line above you can try to remove the service branch as well in HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services.
The accepted answer didn't work for me.
What worked is open regedit in administrator mode and find the service and delete it.
I had the exact same problem (and nothing in the selected answer worked).
Surprisingly, what fixed the problem was (using the standard "Uninstall or change program" or "Programs and Features" windows dialog) right-clicking on the program and choosing repair (this was apparently successful), and then uninstalling.
This just happened to me and the solution above didn't work where you run the InstallUtil.exe or delete the service. I had initially set up my service with the "LocalSystem" security context, and it was installed with that. I later changed the security context to "User" and recompiled the service executable and tried to uninstall the old service. The error messages were coming up that are described here, and once I went and changed the security context back to "LocalSystem" I could fully uninstall.
In other words, you might want to uninstall your old service with the executable it was created with rather than a newer one with possible modifications.

Categories

Resources