How to build a software update service which could update itself too? - delphi

I know that many software are updated by a windows service installed together. I made the service to serve as an update helper and a data server for my client application. But I am stuck on how do I control my client application from this service.
First my service will check for updates on the remote server and then download files.
It will broadcast the news to clients which will ask users if they want to update now or the next execution.
On the time to update, the client application can not delete it's own executable file, so, it would make sense if it asks the server to do it while it's not executing, and then when finished deleting and renaming the files, it would re-execute the client.
If the service is in session 0, it could not be able to re-execute the client to the same user session.
The other possible problem is when the very service would need an update. It could be solved by been updated by the client instead of itself.
So, in the case of updating client and server, should I need to create a third application to do the job. if this 3rd application is a console app, it would be no problem to execute it from the service, right?
If there is a solution that doesn't include this 3rd app, it would be the best.
Note:
The service is not just an update service, but a server to inform user access and rights. The main client application will not access the user information database directly.

If the service is in session 0, it could not be able to re-execute the client to the same user session.
Yes, it would, if you use CreateProcessAsUser() to specify the user account and the desktop to run the app on. The client could convey that info to the service before terminating itself.
But in any case, updating an exe requires it to stop running first. So when updating the service, especially since the service does more than just handle client updates, it would be safer to use an installer to stop the service, replace the exe, and restart the service. In which case, why not do the client update using an installer as well? The downloaded update could be a self-contained installer that stops both client and service as needed, replaces the files, and then either has the client or service delete the installer after it exits, or the installer can ask Windows to delete the installer upon the next OS reboot.

Related

How can background tasks be executed from a library in an ASP.NET MVC 5 app

In my job we are building Web Apps that rely on a common Enterprise class. This class has a method that sends a request to our server every time the app_start or app_end event triggers so we can monitor the status remotely. But we are now requiring that at least once a day the web app reports its status, a bit like telemetry. I don't know how to accomplish this, so far I have found some options, but some have limitations:
Use hangfire. I don't like this since it requires to setup a Database or add more tables and install a new Nuget package on each project, but could be my last option.
Use a Windows Service that reads databases. This could be less work but it can't access the Web App web.config code
Use a Javascript tasks that sends an AJAX request. This requires to have an open web browser and is a big risk.
I'm looking for a server side approach that could allow to set to trigger an event or function at 1am.
I would got with Hangifire.
It is dead easy to setup and very reliable.
You don't need to setup the database, you might want to check memory storage:
https://github.com/perrich/Hangfire.MemoryStorage
Also check:
What is the equivalent to CRON jobs in ASP.NET? - C#
You can use FluentScheduler instead of Hangfire (it is more lightweight).
Instead of a Javascript task that sends an AJAX request you can use a WebJob or an Azure Function.

How to shutdown one instance of an app service in azure

I have deployd an Asp.Net MVC application to an app service in azure and scaled it out to 2 instances.
Sometimes I need to restart an instance, but I only find a way to restart the whole web app. Is there a way to restart one instance only? Even removing the instance and then creating a new one would work for me.
There is no super clean way to do this, but it is still possible to achieve with the following steps:
Go to the Web App in the portal
Choose Process Explorer from Tools menu
You'll see processes for all instances. You can right click on specific w3wp's and kill them, which effectively restarts the site. You don't have to kill the Kudu process (the one with the K icon) if you only want to restart the site. For WebJobs, kill Kudu as well.
You can now restart an instance of an App Service Plan from the App Service Plans - Reboot Worker page in the Azure docs. You can restart the instance directly from that page using the 'Try it' feature.
Visit the Reboot Worker page
Login using an account from the Azure tenant containing the App Service Plan
Click 'Try it'
In the right hand pane enter the Name of the App Service plan and the resource group which contains the plan
Select the Azure subscription which contains the App Service plan
Enter the name of the work machine (instance) you wish to restart. This value typically starts with RD and may be found using the metric and diagnostic tools for the Web App in the Azure Portal.
Click the green Run button at the below the request preview.
If you are using App Services then, unfortunately, this is not possible. You can only update the no. of instances.
But as an alternative, you can decrease the number of instances and then increase back again. Or if you want more granular control, for any reason, then you can deploy the web app in IaaS Virtual Machine workloads and setup instances manually.
At the time of this posting, there is a Health Check (Preview) feature mentioned in the Azure Portal under the "Diagnose and solve problems -> Best Practices" blade for an App Service.
Health Check feature automatically removes a faulty instance from rotation, thus improving availability.
This feature will ping the specified health check path on all instances of your webapp every 2 minutes. If an instance does not respond within 10 minutes (5 pings), the instance is determined to be unhealthy and our service will stop routing requests to it.
It is highly recommended for production apps to utilize this feature and minimize any potential downtime caused due to a faulty instance.
Note : Health Check feature only works for applications that are hosted on more than one instance. For more information check the documentation below.
You can restart individual instances using "Advanced Application Restart", which you can find under diagnostic tools for your App Service in the Azure Portal.

Connect to already open Quickbooks instance via QBXML

I'm trying to help a client who has a web application (ASP/C#) that integrates with Quickbooks via the QBXML SDK.
I want to open up a connection to an already active QuickBooks instance in a user session.
The relevant code in question:
if (rp == null)
rp = new RequestProcessor2();
if (!connected)
{
rp.OpenConnection2("IMS", "Internal Management System", QBXMLRPConnectionType.localQBD);
connected = true;
}
if (xticket == null)
xticket = rp.BeginSession(cfg.qbfile, QBFileMode.qbFileOpenMultiUser);
As is, this will attempt to launch a new instance of Quickbooks via DCOM, which is not a viable option. Following the QBSDK documention, I attempted to pass null to BeginSession's first argument, which should use the open qbw file.
However, instead of the expected action of connecting to the running instance of Quickbooks, it launches a new instance, eventually yielding the error:
"If the QuickBooks company data file is not open, a call to the "BeginSession" method must include the name of the data file."
The IIS AppPool running the web app uses the same user as the Quickbooks instance I'm trying to connect to.
This was all set up by a third party who is no longer available, and, of course, they left no documentation whatsoever on how this system was supposed to work. Any assistance would be welcome.
I'm trying to help a client who has a web application (ASP/C#) that integrates with Quickbooks via the QBXML SDK.
Unfortunately, this approach will not work.
It's a well-known limitation of QuickBooks that:
QuickBooks has to be running in the user session you're trying to connect from
QuickBooks has to have access to a GUI (it uses a GUI message pump to function)
Because your web app is running in from within IIS, neither of those two criteria are met, and connections to QuickBooks will fail. You should be using the QuickBooks Web Connector instead.
I want to open up a connection to an already active QuickBooks instance in a user session.
Unfortunately, QuickBooks won't allow this.
I managed to create an acceptable workaround to my problem, for anyone trying something similar. (Which, honestly, I don't recommend. I'm working with legacy code here.)
First, a brief overview of my research:
The QBXml interface with QuickBooks uses COM requests in order to communicate. Now, for whatever reason, whether design, bug, or limitation in COM, Quickbooks cannot communicate across LSA Logon Sessions. In practice, this means that the same console session that Quickbooks is running under must also run the QBXml code. Additionally, both Quickbooks and your application must have the same UAC elevation status.
I found no way to get IIS to reliably launch Quickbooks. The individual who setup this system before me managed to do so through some very... unorthodox methods. It was incredibly flaky, and the cause of multiple issues.
Regardless, I did manage an acceptable workaround, in the form of IIS Express. IIS Express can run under a standard user session. As such, running both Quickbooks and the web app (through IIS Express) under the same Logon Session allowed them to communicate successfully.
It is not a permanent solution, as there are drawbacks to running a service such as this in a standard user paradigm, but it is an acceptable workaround, and will allow my client to run their business while we refactor. I plan to first decouple the portions of the app that communicate with Quickbooks, moving them into their own codebase. This will allow the web facing portions of the app to operate in a more standard manner, and communicate with the QB integration code through a more reliable means than COM calls.
Thanks to Keith Palmer for helping point me in the right direction.

Windows Service + Run application in System Tray

I have a Delphi application running in a server. This application do some critical work with my DB which is used in other applications and executes when a user logs in to Windows. It all is working fine, but, turns out the server's administrator sometimes reboot the server and does not log in to Windows. The server stays in Windows Login and my application doesn't start.
After a small research I decided to create a Windows Service to start my application even before a user logs in Windows. But, I have two forms. One form shows the Current Process that my application is executing and the other one edite a .ini file that its used to configure the first form.
What I need to be done is to create a service that starts my application before a user logs in Windows and after logging in, show my forms or open it but minimize it to System Tray.
Is it possible to use Windows Service with this behavior and minimize my forms to the System Tray?
A service cannot display a UI at all (including a System Tray icon) in Vista onwards, and it is discouraged in earlier versions. In all versions of Windows, you should be separating the UI out into its own non-service application that can be run by a logged-in user, manages the system tray icon for that user's tray, and communicates with the backend service as needed using any number of available IPC mechanisms (pipes, sockets, COM, RPC, WCF, etc).
Well, you can have a form in a service, but is has to run as Administrator and must be set up as an interactive service.
I've used SVCOM to create nice services with tray icons and a form that can minimize to system tray.
Have a look here: http://www.aldyn.ru/products/index.html
Hope this helps

Can a User DSN be accessed by a Windows Service

I've build a Windows service that allows a user to choose a DSN and the service will access it and peform tasks on it. The code works without error when running under a test command line application, and fails when running as the actual Windows Service.
My question is, are Windows Services not allowed to access User DSN? Is there any way to still allow users the ability to create and configure DSNs for the service to use?
check What are the access restrictions on accessing a DSN

Resources