Uninstall Command Fails Only in Release Mode - c#

I'm able to successfully uninstall a third-party application via the command line and via a custom Inno Setup installer.
Command line Execution:
MSIEXEC.exe /x {14D74337-01C2-4F8F-B44B-67FC613E5B1F} /qn
Inno Setup Command:
[Run]
Filename: msiexec.exe; Flags: runhidden waituntilterminated;
Parameters: "/x {{14D74337-01C2-4F8F-B44B-67FC613E5B1F} /qn";
StatusMsg: "Uninstalling Service...";
I am also able to uninstall the application programmatically when executing the following C# code in debug mode.
C# Code:
string fileName = "MSIEXEC.exe";
string arguments = "/x {14D74337-01C2-4F8F-B44B-67FC613E5B1F} /qn";
ProcessStartInfo psi = new ProcessStartInfo(fileName, arguments)
{
CreateNoWindow = true,
UseShellExecute = false,
RedirectStandardOutput = true
};
Process process = Process.Start(psi);
string errorMsg = process.StandardOutput.ReadToEnd();
process.WaitForExit();
The same C# code, however, produces the following failure output when run as a compiled, deployed Windows Service:
"This action is only valid for products that are currently installed."
Additional Comments:
The Windows Service which is issuing
the uninstall command is running on
the same machine as the code being
tested in Debug Mode. The Windows
Service is running/logged on as the
Local system account.
I have consulted my application logs
and I have validated that the
executed command arguments are thhe
same in both debug and release mode.
I have consulted the Event Viewer
but it doesn't offer any clues.
Thoughts? Any help would be greatly appreciated. Thanks.

Step 1: Check the MSI error log files
I'm suspicious that your problem is due to running as LocalSystem.
The Local System account is not the same as a normal user account which happens to have admin rights. It has no access to the network, and its interaction with the registry and file system is quite different.
From memory any requests to read/write to your 'home directory' or HKCU under the registry actually go into either the default user profile, or in the case of temp dirs, c:\windows\temp

I've come across similar problems in the past with installation, a customer was using the SYSTEM account to install and this was causing all sorts of permission problems for non-administrative users.
MSI log files aren't really going to help if the application doesn't appear "installed", I'd suggest starting with capturing the output of MSIINV.EXE under the system account, that will get you an "Inventory" of the currently installed programs (or what that user sees installed) http://blogs.msdn.com/brada/archive/2005/06/24/432209.aspx
I think you probably need to go back to the drawing board and see if you really need the windows service to do the uninstall. You'll probably come across all sorts of Vista UAC issues if you haven't already...

Thanks to those offering help. This appears to be a permissions issue. I have updated my service to run under an Administrator account and it was able to successfully uninstall the third-party application. To Orion's point, though the Local System account is a powerful account that has full access to the system -- http://technet.microsoft.com/en-us/library/cc782435.aspx -- it doesn't seem to have the necessary rights to perform the uninstall.
[See additional comments for full story regarding the LocalSystem being able to uninstall application for which it installed.]

This is bizarre. LocalSystem definitely has the privileges to install applications (that's how Windows Update and software deployment in Active Directory work), so it should be able to uninstall as well.
Perhaps the application is initially installed per-user instead of per-machine?

#Paul Lalonde
The app's installer is wrapped within a custom InnoSetup Installer. The InnoSetup installer, in turn, is manually executed by the logged in user. That said, the uninstall is trigged by a service running under the Local System account.
Apparently, you were on to something. I put together a quick test which had the service running under the LocalSystem account install as well as uninstall the application and everything worked flawlessly. You were correct. The LocalSystem account has required uninstall permissions for applications in which it installs. You saved the day. Thanks for the feedback!

Related

Setting Registry from windows service does not work

I am setting or reading reg key from a windows services which runs as local system.
But when I read or set the values in the Registry Editor they are not the same as when i read and set them from the windows services.
If I execute the following command in powershell from the windows services or when i am logged in as a user the results differ as well. Why? Is there a different LocalMachine for a LocalSystem account?
$DefaultUserName = (Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" -Name "DefaultUserName").DefaultUserName
Write-Host $DefaultUserName
I am using the following c# lines to execute the powershell script from the windows service:
var process = new Process();
process.StartInfo.UseShellExecute = false;
process.StartInfo.FileName = #"C:\Windows\SysWOW64\WindowsPowerShell\v1.0\powershell.exe";
process.StartInfo.Arguments = "\"&'" + cacheFile + "'\"";
process.StartInfo.Verb = "runas";
process.Start();
You need to be careful of bitness. On 64-bit Windows, 32-bit applications run using the 'Windows on Windows' subsystem, which by default uses different filesystem paths and registry paths. You are executing powershell from the SysWOW64 folder, which means you are executing the 32-bit version, which will use the 32-bit registry hive.
If you open up regedit, the 32-bit hive for your registry key is: Computer\HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows NT\CurrentVersion\Winlogon. I suspect you are getting/setting this value.
Please refer to How to access a 64Bit Registry key using 32Bit Powershell without Redirection to WOW6432Node for strategies you can take, including using the Sysnative rather than SysWOW64 version of powershell.
If you need to support 32-bit and 64-bit operating systems, you will need to make sure you are using the appropriate technique.
This answer has beautiful explanation of Windows built in accounts :
The difference between the 'Local System' account and the 'Network Service' account?
A limited service account that is very similar to Network Service and meant to run standard least-privileged services. However, unlike Network Service it accesses the network as an Anonymous user
Completely trusted account, more so than the administrator account. There is nothing on a single box that this account cannot do, and it has the right to access the network as the machine (this requires Active Directory and granting the machine account permissions to something)
Also can you try running the service as SYSTEM?

Run C# Application on Windows Start up

I'm trying to start a few applications for the current user only when Windows starts up.
I can accomplish this with the following:
RegistryKey oKey = Registry.CurrentUser.OpenSubKey("Software", true);
oKey = oKey.OpenSubKey("Microsoft", true);
oKey = oKey.OpenSubKey("Windows", true);
oKey = oKey.OpenSubKey("CurrentVersion", true);
oKey = oKey.OpenSubKey("Run", true);
oKey.SetValue("Application 1", "C:\\path\\to\\ap1.exe");
oKey.SetValue("Application 2", "C:\\path\\to\\ap2.exe");
But I'm trying to run this as part of a Visual Studio Installer Project. I've added my custom action, the program starts like it should, and the installer works great in XP.
In Windows 7, the installer gets elevated privileges, and does everything but insert the entries into the registry for the current user. How ever, it does insert the registry entries when ran as a standalone application (outside of the installer project) and it does not get elevated privileges.
The only thing I can figure is that with the elevated privileges, it's trying to insert the entries into the Administrators account instead of the current user? or is there something else I'm missing? and is there another way I can achieve my goal here?
Is there a reason to not use the startup folder for the user?
More than likely the problem is the user the installer is executing under. If the user isn't the admin the elevated installer will run under the context of the user who elevated the process.
It would be a safer choice to add your application to the startup folder or to add the registry key on first launch.
If the installer is getting elevated permissions, why write the setting to HKCU? Write it to HKLM instead. It will then take effect for all users.

Loss of admin privileges when Java program calls C# program to write to %ProgramData%

The scenario:
I have a Java based installer.
The Java based installer calls a C# program, whose job is to create a shortcut.
The shortcut location depends on if the installer is running as administrator or as a regular user. When running as admin, I'm trying to create a shortcut to "%ALLUSERSPROFILE%\Desktop", else I write to "%USERPROFILE%\Desktop".
My impression is that the issue seems to be a loss of administrative privilege when my Java program calls my C# shortcut maker program.
Notes:
I run my Java based installer as administrator (right click, run as administrator).
I'm able to verify the installer is running with administrator privileged because I can read registry keys that require administrative privilege.
I'm calling my C# program via 'Process process = Runtime.getRuntime().exec(command);'
When running the command manually through an administrative command prompt, the command works fine. (When outputting to "%ALLUSERSPROFILE%\Desktop")
When running the the same command manually, from a normal command prompt, I get System.UnauthorizedAccessException. (Which is to be expected). The program crashes in a similar was that it does when run from the installer.
The Exception:
Unhandled Exception: System.UnauthorizedAccessException: Access is
denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED)) at
IWshRuntimeLibrary.IWshShortcut.Save()
Any thoughts on what I'm missing? The installer needs to be flexible to run as both a normal user and as an administrator. How can I ensure this behavior?
Update 1
I attached a debugger to the C# program at runtime. It is throwing a:
DirectoryNoFoundException was unhandled
The system cannot find the path specified. (Exception from HRESULT: 0x80070003)
I added "mkdir" commands before my shortcutmaker commands. The mkdir commands, just ensure that the directories exist before trying to write to them.
Rebuilt the installer, ran it and when trying to mkdir "%ALLUSERSPROFILE%\Desktop", java throws an exception of
java.io.IOException: Cannot run program "mkdir": CreateProcess error=2, The system cannot find the file specified
java.io.IOException: Cannot run program "mkdir": CreateProcess error=2, The system cannot find the file specified
at java.lang.ProcessBuilder.start(Unknown Source)
at java.lang.Runtime.exec(Unknown Source)
at java.lang.Runtime.exec(Unknown Source)
at java.lang.Runtime.exec(Unknown Source)
At this point, it looks like my process isn't getting admin access
Process process = Runtime.getRuntime().exec(command);
I'm going to see if I can find anything else.
Update 2
The following gave me some info that I tried: Enterprise Logging not translating environment variables in XML Trace Listener fileName specification
It suggested that %ALLUSERSPROFILE% was not getting translated.
Instead of %ALLUSERSPROFILE%, I got the environment variable values via:
String allUsersProfile = System.getenv("ALLUSERSPROFILE");
String userProfile = System.getenv("USERPROFILE");
I was then able to supply the actual values to the C# program. But I'm still having issues.
From a admin console I can navigate to "c:\ProgramData\Start Menu", but if I run "explorer" with administrative priviledges, I can navigate to "c:\ProgramData" but not see anything past that... Through some looking, I found out that "c:\ProgramData\Start Menu" is a protected operating system file. So I turned on the setting to see it. So now I can see it, but not go into it.
Using system internals, I elevated an explorer.exe to "system" access and still can't go into the folder (System internal elevation reference: http://verbalprocessor.com/2007/12/05/running-a-cmd-prompt-as-local-system/)
I right clicked on the folder and checked out the security tab. It looks like even my "System" user has limited access. I find this a bit baffling, that I can run the command from an admin command prompt that will write the shortcut to the desktop, but going through this other process I cannot... I also find the access to be a bit inconsistent.

Installing C# Windows Service on Windows 7

I have a batch file that I have been using to install my C# Windows Services for awhile now, never had a problem until Windows 7. I have attempted to run the batch file with Administrator privileges. I have attempted to run the command prompt with admin privs, navigate to the windows service EXE and run InstallUtil there. Still doesn't work.
After reading some other suggestions I tried moving my files out of the /bin folder and running them from another location but that also didn't work.
The batch file looks like this
#ECHO OFF
REM The following directory is for .NET 2.0
set DOTNETFX2=%SystemRoot%\Microsoft.NET\Framework\v2.0.50727
set PATH=%PATH%;%DOTNETFX2%
echo Installing IEPPAMS Win Service...
echo ---------------------------------------------------
InstallUtil /i IEPPAMS_WinService1.exe
echo ---------------------------------------------------
echo Done.
and I have a install log file that I dump info to. If I just double click the .bat file I get
Running a transacted installation.
Beginning the Install phase of the
installation. See the contents of the
log file for the
C:\Users\Justin\Desktop\service
test\IEPPAMS_WinService1.exe
assembly's progress. The file is
located at
C:\Users\Justin\Desktop\service
test\IEPPAMS_WinService1.InstallLog.
An exception occurred during the
Install phase.
System.InvalidOperationException:
Cannot open Service Control Manager on
computer '.'. This operation might
require other privileges. The inner
exception
System.ComponentModel.Win32Exception
was thrown with the following error
message: Access is denied.
The Rollback phase of the installation
is beginning. See the contents of the
log file for the
C:\Users\Justin\Desktop\service
test\IEPPAMS_WinService1.exe
assembly's progress. The file is
located at
C:\Users\Justin\Desktop\service
test\IEPPAMS_WinService1.InstallLog.
The Rollback phase completed
successfully.
The transacted install has completed.
When I run the .bat file with admin privileges nothing is written to the log file, and the service is still not installed.
Any thoughts? Is there a new way to install services in Windows 7?
Right click on the batch file and run it as Administrator.
You are most likely running into battle with the new security model (User Account Control) from Windows Vista and Windows 7. Even if you are running as an account that has Admin rights you will still need to elevate to do some (most) administrative activities. (Yes it is possible to disable this feature, but don't)
UAC (MSDN)
UAC (Wikipedia)
InstallUtil (MSDN)
Edit... The correct commandline is InstallUtil YourApp.exe. The /i does not look to be a vaild switch for InstallUtil.
So I was able to fix the problem by typing in the command line the entire path to InstallUtil and it worked. So after navigating to the folder that had my EXE I typed the following:
C:\Windows\Microsoft.NET\Framework\v4.0.21006\installutil.exe
IEPPAMS_WinService1.exe
Not sure why I have to do that in Windows 7 now when I never had to in XP, but oh well. Thanks for all the suggestions!
When I run the .bat file with admin privileges nothing is written to the log file, and the service is still not installed.
First off, you HAVE to run as admin permissions.
Second, when you "Run as Administrator", it actually changes the directory to c:\windows\system32 as the initial directory ( no idea why ), which would probably explain why running as admin causes no log file. Manually change to the path IEPPAMS_WinService1.exe resides in that the start of your script.

Mark MSI so it has to be run as elevated Administrator account

I have a CustomAction as part of an MSI.
It MUST run as a domain account that is also a member of the local Administrators account.
It can't use the NoImpersonate flag to run the custom action as NT Authority\System as it will not then get access to network resources.
On Vista/2008 with UAC enabled if NoImpersonate is off then it will run as the executing user but with the unprivileged token and not get access to local resources such as .installState. See UAC Architecture
Anyone know of a way to either
Force the MSI to run with the elevated token in the same way that running from an elevated command prompt does?
Force the CustomAction to run elevated (requireAdministrator in manifest doesn't appear to work)?
Work out if UAC is enabled and if it hasn't been ran elevated and if so warn or cancel the installation?
Answering my own question for any other poor s0d looking at this.
You can't add a manifest to an MSI. You could add a SETUP.EXE or bootstrapper to shell the MSI and manifest that with requireAdministrator but that defeats some of the point of using an MSI.
Adding a manifest to a CustomAction does not work as it is ran from msiexec.exe
The way I have tackled this is to set the MSIUSEREALADMINDETECTION property to 1 so the Privileged condition actually works and add a Launch Condition for Privileged that gives an error message about running via an elevated command prompt and then quits the installation.
This has the happy side effect - when an msi is ran from an elevated command prompt deferred CustomActions are ran as the current user with a full Administrator token (rather than standard user token) regardless of the NoImpersonate setting.
More details - http://www.microsoft.com/downloads/details.aspx?FamilyID=2cd92e43-6cda-478a-9e3b-4f831e899433
[Edit] - I've put script here that lets you add the MSIUSEREALADMINDETECTION property as VS doesn't have ability to do it and Orca's a pain.
requireAdministrator in the manifest should work.
You can also use a bootloader .exe file which can use ShellExecute with "RUNAS" as the verb (you can use 7-zip to create the bootloader, or there are many other ways).
You can creating a simple sfx archive file for msi file with Winrar and these options:
Setup tab > Run after execution input: your msi file name
Advanced tab > Mark Request Administrative access option checkbox

Categories

Resources