I have a strange problem,
I have a WPF application. I have created a windows installer for this and installation will create application shortcut in user's start menu. I'm installing this MSI through windows service. Installation works fine through windows service but it doesnt create shortcut in start menu also i dont see this application under Programs and Features. But if i manually install this everything works fine. Any clue why this is happening ?
Code to execute MSI
Process installProcess = new Process();
//Assign required properties
installProcess.StartInfo.FileName = MSIEXEC;
installProcess.StartInfo.RedirectStandardError = true;
installProcess.StartInfo.UseShellExecute = false;
LogManager.Write("Process object is created");
//Create new StringBuilder instance
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.Append(SYMBOL_SLASH);
stringBuilder.Append(SYMBOL_INSTALL);
stringBuilder.Append(installerPath);
stringBuilder.Append(SYMBOL_QN);
LogManager.Write("StringBuilder is created: " + stringBuilder.ToString());
installProcess.StartInfo.Arguments = stringBuilder.ToString();
installProcess.Start();
InstallAllUsers property in for MSI was set to false. My windows service was running under Local System account and my machine was logged in with windows authentication under administrator account. So when the installation happened it was assumed that MSI is installed by the user other than who has logged into the machine with windows authentication so it didnt not show up in the start menu and under Programs and Features.
It was not necessary for me to keep the InstallAllUsers to false so simply i made it true which solved my problem.
Related
I have a project in visual studio written in C# that uses ABCpdf to create a PDF page count. I set the install to be instanced as the project is deployed on a server and the project is run without admin rights as our IT department does not want to have a GMSA with admin privs to run it (it runs as a nightly windows task schedule). My issue is the application fails when it tries to generate the PDF due to access denied when installing the license. If I run the application as administrator on the server it runs fine, so it's definitely something to do with no admin rights when installing the license (or other aspects perhaps to run).
My code for installing looks like this:
try { string sResult;
if (WebSupergoo.ABCpdf11.XSettings.InstallRedistributionLicense("<license string>"))
{
sResult = "License Installed Successfully: " + WebSupergoo.ABCpdf11.XSettings.LicenseDescription;
}
else
{
sResult = "License Installation Failed";
}
<does other formatting things for the pdf creation after this in the try catch>
Does anyone know how to get this working without admin rights, or do you know the specific task or registry item it modifies so I can give the GMSA access just to that without full privs? Any help would be awesome. Thanks in advance!
I have a app which gets installed in C:\Program Files{AppName} and a service associated with that app (NT Service{ServiceName}). This app asks for uac prompt during the installation and the service shows Elevated = "Yes" in task manager. Now, I need to update this app silently without getting uac prompt. I tried the below code which didnt work (Update didn't go through and no log file got created).
Process.Start(
new ProcessStartInfo("msiexec")
{
ArgumentList =
{
"/i",
"new_version_file_path",
"/qn",
"/L*V",
"Log_file_path",
},
UseShellExecute = true,
});
I thought that since the service is showing to be running in elevated mode update should go through. If I add my service to the local Administrators group then the installation runs fine and the app gets successfully updated. Why do I need to add it in local administrators group ? Is there another way I could update the app using c# without using any 3rd party application?
I want to restore previous version of C# application published using ClickOnce, if database migration fails because database wont be latest and it will not support latest version of application.
Details
I am developing an app which will be used locally in remote areas where internet is not available. A person will update his/her app every once in a while by getting internet somehow and then will deploy the app on local network. From there every one will be able to get the updated version of app. What I want now is to use database migration using this app and if the app fails It should restore to previous version. I have already used FluentMigrator for database migration and have used ClickOnce to deploy the app. I have also gone through almost every link over here to see how can I do it. I now know that its not possible using ClickOnce. Can anybody tell me some other way or may be some kind of hack?. I am using ClickOnce because of its auto update feature so don't really want to lose that functionality now. Any help will be appreciated.
FluentMigrator keeps track of current version in the database. It also keeps track of latest version in the current app version. Run Migrator function and check if the latest version of Migration files in the current version is equal to the latest version stored in a database. If both are equal then Migration was successful. If they are not equal then you can run the cmd command to directly open (remove or backup) window of the control panel and go to the previous version. This is the best you can do to revert to the previous version using ClickOnce.
try {
new MigrationsWrapper(AppManager.ConnectionString).MigrateToLatestVersion();
}
catch (Exception ex)
{
}
LatestVersionNumber = new MigrationsWrapper(AppManager.ConnectionStringADO).LatestVersionNumber;
CurrentVersionNumber = new MigrationsWrapper(AppManager.ConnectionStringADO).CurrentVersionNumber;
if (LatestVersionNumber > CurrentVersionNumber) {
string applicationName = ConfigurationManager.AppSettings["ApplicationName"].ToString();
string uninstallString = GetUninstallRegistryKeyByProductName(applicationName);
if (uninstallString != string.Empty) {
System.Diagnostics.Process process = new System.Diagnostics.Process();
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
startInfo.FileName = "cmd.exe";
startInfo.Arguments = "/c " + uninstallString;
process.StartInfo = startInfo;
process.Start();
}
} else {
// Successfull
}
So, you want to run previous version of the app if some problem happen during execution.
I don`t know solution for ClickOnce, but there is analogue for it - Squirrel.
Bad news that Squirrel has no straight solution too, but it phisically stores previous version of app and you can run it and it works (I just checked it on my app).
So, there is a strategy:
Migrate to the squirrel (they have a tool for it)
in case of emergency - calc path to the stored previous version and run it. Relative path should be like "../app-1.1.1/myApp.exe"
But there is one thing to keep in mind. Squirrel stores previous version only if it upgraded app from it. There is no prev version after first install.
Good luck.
From the description the different versions of the application are sharing a single database. As a new version of the application goes live on the machine it needs to patch/migrate a shared database. If that fails the application doesn't install. Let's hope it fails without corrupting the database also.
There are clickonce events that can be hoocked into. Create a Custom Installer maybe.
https://msdn.microsoft.com/en-us/library/system.deployment.application.applicationdeployment_events.aspx
https://msdn.microsoft.com/en-us/library/system.deployment.application.applicationdeployment.aspx
Publishing ClickOnce Applications
https://msdn.microsoft.com/en-us/library/748fh114.aspx
Walkthrough: Creating a Custom Installer for a ClickOnce Application
https://msdn.microsoft.com/en-us/library/dd997001.aspx
Hope that's helpful.
I have a visual studio installer project which installs a C# app, I have a custom action and code to run the process after install is complete.
Let's say the logged in user on windows machine is "john". Now when john runs the msi installer, I check the process in the taskmanager and it shows that msiexec.exe is the process name for installer and it is running as user "john"
The installer completes and runs the install app's process myapp.exe now when I check this process in taskmanager of windows it shows that myapp.exe is running as SYSTEM (which I do know what account is that and why its not running as john)
Problem
When myapp.exe runs as SYSTEM user it can not create com component instance of a component (iTunes in my case) which was already running as user john. If the component was not running then creating isntance of the iTunes is sucessful, otherwise it fails.
Question
So is it possible to make sure when installer runs as john, when it finishes it starts process myapp.exe as john and not as SYSTEM user ? Note that I do not asks user for password during installer.
Code that I run when installer completes
// Event handler for 'Committed' event.
private void MyInstaller_Committed(object sender, InstallEventArgs e)
{
try
{
Directory.SetCurrentDirectory(Path.GetDirectoryName
(Assembly.GetExecutingAssembly().Location));
Process.Start(Path.GetDirectoryName(
Assembly.GetExecutingAssembly().Location) + "\\MyApp.exe");
}
catch
{
// Do nothing...
}
}
This most likely happens because you are running your custom action as deferred. i.e. it is running by default under the SYSTEM user account.
A solution is to make sure you launch it immediate, for example you can launch it using a published event on the "Finish" button from the last dialog of the installation. I don't know exactly how to add a published event in VS setup projects, or if it is possible, but you can easily add one in packages built with specialized setup authoring tools.
In the Form_Load event write like this:
string lUserName=Environment.GetEnvironmentVariable("USERNAME");
Then instead of getting system user account you will get windows login user name at the time of installing MSI.
Personally I did manage to resolve this by running explorer.exe parameterized with the path to my app's executable:
Process.Start(
new ProcessStartInfo
{
FileName = "explorer.exe",
Arguments = Context.Parameters["target"],
UseShellExecute = true
});
I created a window service and to install it I created its deployment project and installed that. After installing I stared it. It successfully started.
Next day I made some modification, and rebuild and reinstalled but now its not installing.
Then I thought its issue with installer, lets create a custom installer for service so that anytime I can update my code.
I created it like this incase if anyone need this for future.
public class MyInstaller : Installer
{
ServiceProcessInstaller spi;
ServiceInstaller si;
public MyInstaller()
{
spi = new ServiceProcessInstaller();
spi.Account = ServiceAccount.LocalSystem;
si = new ServiceInstaller();
si.StartType = ServiceStartMode.Manual;
si.ServiceName = "MyService";
si.DisplayName = "My Service";
si.Description = "service installed from command line";
this.Installers.Add(spi);
this.Installers.Add(si);
}
}
I called it from main method by check the parameter args.
case "-i":
case "-install":
ti = new TransactedInstaller();
mi = new MyInstaller();
ti.Installers.Add(mi);
string logPath = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) + "\\install.log";
ctx = new InstallContext(logPath, cmdline);
ti.Context = ctx; //.Context ( ctx );
ti.Install(new Hashtable());
break;
Now when I am trying to install. I recevied error System.Security.SecurityException: The source was not found, but some or all event logs could not be searched. Inaccessible logs: Security.
I google it, and come to know service will try to access application log while installing and write log there.
I am not writing any event log. I have my log4net for logging. But still its default behaviour.
How to overcome this issue now? Its not getting installed even I have all permissions.
Thanks
I have found that at times you may need to "Run as Administrator". If you are installing from a command prompt you may need to start that up with "Run as Administrator".
I might have had a separate root cause for the message, but I fixed it by changing my service to run as LocalSystem (which is what I want anyway) instead of LocalService.
I can confirm that under "windows 7 64 bit" AND "Windows 10" you must:
1) run Visual studio command prompt AS ADMINISTRATOR (right click.. Other.. tun as admin)
2) go to "obj" folder where You have the exe.
(cd [all path to \obj] )
3) launch installutil [myservice.exe]
if not run as "admin", it fails even on old win7. :(
note: MSDN does explain it:
(at: https://learn.microsoft.com/en-us/dotnet/framework/windows-services/walkthrough-creating-a-windows-service-application-in-the-component-designer)
"To install a Windows service, you must have administrative credentials on the computer on which you're installing it."
:)