Finding which service has run an executable in C# - c#

I was wondering if it were possible to find out which windows service has run an executable?
I've got two different services running from the same exe, doing different things. The main method of the program detects a command line parameter and will either start the console app (if running in Environment.UserInteractive), or start one of the two possible services. I can't find a good way to discern which service is running so I can choose the correct service to start in the code. Passing in .exe parameters in the image path of the windows service doesn't seem to work. The services are running on a server and starting automatically, so doing it manually isn't really an option.
I'd really like to avoid having to have two different projects with different executables, so any way I can notify the program of which service to run would be great.

You can pass arguments in the ImagePath. I know I have done it at some point using a .net windows service, but as I recall, I had to install the service using something other than the standard .Net installer.
The .Net installer adds quotes around whatever you pass, which makes ImagePath go from C:\test\test.exe -arguments to "C:\test\test.exe -arguments" when it should be "C:\test\test.exe" -arguments.
Check out WiX, sc.exe or CreateService to get the correct registry value.
To test, install your service as usual and browse in regedit to HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\yourServiceName and edit ImagePath. For an example of how it should look, check out HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\seclogon.

You could create a Mutex in your service at the point it starts, using a name unique to the version it is running. If the mutex is obtained then you know it isn't running. If it can't be obtained then the service is already running.
You could then start your services through a new process that first tries to obtain the mutex for the first service and if it can't obtain it it starts the second.
So, you start ServiceRunner.exe -foo. A mutex called "foo" is obtained, so you release the Mutex and ServiceRunner.exe starts Service.exe -foo.
If the mutex is not obtained you then try to obtain a mutex called "bar" and follow the same process.
This is a nasty solution, and would require your to create a new exe that simply tries to start the services.

Have your service share its start state( temp file, registry key or other method, it could even write this as html to a web server... )
ServiceController yourService = new ServiceController( "YourServiceName" , "YourMachine" );
if( yourService.Status == ServiceControllerStatus.Stopped )
{
yourService.Start();
}

Related

Coded UI Application Under Test

Just started implementing a coded ui test automation solution but keep running into an issue when starting the application.
The application seems to start just fine but no matter what I always get an exception stating:
Microsoft.VisualStudio.TestTools.UITest.Extension.FailedToLaunchApplicationException: "The application cannot be started. This could be due to one of the following reasons:
1) Another instance of the application is already running and only one instance can be running at a time.
2) The application started another process and has now stopped. You may need to launch the process directly.
3) You do not have sufficient privileges for this application."
The application is a little strange as it currently is setup to run off of a setup.exe so the user always has the latest version.
Am I missing something in my code (sample below)? Or does the application need to be better set up before I start writing the automation tests. EXE is located in a network location.
ApplicationUnderTest aut = ApplicationUnderTest.Launch(#"\\test.com\\applicationdir\\testenv\\application\\setup.exe");
WpfEdit userName = new WpfEdit(aut);
userName.SearchProperties.Add(WpfEdit.PropertyNames.AutomationId, "PART_UserName");
userName.Text = "TEST";
Currently using a workaround where I start the app via Process and then pass it to the application under test FromProcess(). Seemed to fix the issue.
Probably not the best solution and have to use a Thread.Sleep() but it works for now.
Example:
var process = Process.Start(#"pathToApplication");
Thread.Sleep(2000);
process = Process.GetProcessesByName("process.Name")[0];
ApplicationUnderTest aut = ApplicationUnderTest.FromProcess(process);

How to update your exe from remote host - c# 4.0 - wpf application

I want to update my exe from remote server. So when the button clicked on my wpf application it will download the remote and also a remote txt file and replace the current ones in the same folder that exe running. So it will overwrite the current txt and and exe file while my exe is running. How can i achive this ?
Remote host is url like www.mydomain.com/MyAPP.exe
wpf application , c# 4.0
The way that we resolved this issue was to create a shell exe that as the one that was installed and deployed initially to the client machines.
The "real" executable program is stored in a subdirectory of this initial app. When the shell app is launched, after it has downloaded and installed any updates for the real app, it launches the real app's executable in a separate AppDomain.
Here is the core of the "real" app launching from within the shell app:
System.AppDomainSetup oSetup = new System.AppDomainSetup();
string sApplicationFile = null;
// Use this to ensure that if the application is running when the user performs the update, that we don't run into file locking issues.
oSetup.ShadowCopyFiles = "true";
oSetup.ApplicationName = sAppName;
// Generate the name of the DLL we are going to launch
sApplicationFile = System.IO.Path.Combine(sApplicationDirectory, sAppName + ".exe");
oSetup.ApplicationBase = sApplicationDirectory;
oSetup.ConfigurationFile = sApplicationFile + ".config";
oSetup.LoaderOptimization = LoaderOptimization.MultiDomain;
// Launch the application
System.AppDomain oAppDomain = AppDomain.CreateDomain(sAppName, AppDomain.CurrentDomain.Evidence, oSetup);
oAppDomain.SetData("App", sAppName);
oAppDomain.SetData("User", sUserName);
oAppDomain.SetData("Pwd", sUserPassword);
oAppDomain.ExecuteAssembly(sApplicationFile);
// When the launched application closes, close this application as well
Application.Exit();
Note that in our version, the shell app collects the user name and password from the user in order to access the update web site correctly. This data is then passed to the "real" app through the SetData method on the AppDomain.
The solution depends on your particular case. But there's no straight solution, because you can't update assemblies while they are loaded into memory and being used. I can propose 2 solutions: using shadow copying and using some sort of helper executable. I've used both of them.
Shadow copying.
The obvious way is to make your main executable to be shadow copied, replace it while your app is running and then restart the app. But you can't make your default app domain to be shadow copied, only secondary app domains can be. But you still can move all your code into another assembly (say, MainAppLib.dll) and rewrite your main app executable (MainApp.exe) so that it contains only "loader code". This loader code has to create another app domain, set it to be shadow copied and then run your program logic in the secondary app domain. Beware not to have any direct references from your main app domain into MainAppLib.dll because then this assembly will be loaded into your main app domain which is not shadow copied and the assembly file will get locked. In most cases you can go with AppDomain.ExecuteAssembly() methods.
Helper executable
The idea is to use some sort of update finisher. Your main app remains unchanged, you only add a little amount of code into it, so that your app will download update, put it into temporary folder, and then your main app starts update finisher (in separate process) and exits. Update finisher waits till your app closes and then copies new files from temporary folder into your app folder replacing all files. Update finisher can't replace it's own executable but it can be done by main application before it starts the update finisher. After copying files update finisher runs your application.
p.s. Personally I prefer the former solution because it involves some sort of voodoo magic using app domains, reflection, assemblies e.t.c. And it can be evolved into using plugins if you need (e.g. via MEF framework). But the latter is easier to understand especially if you have never worked with app domains and manual assemblies loading, it's quite straightforward.
You could probably use ClickOnce (based on your comment above that you would be prepared to have another assembly get the exe....as the other poster mentioned you can't replace a running assembly). You can configure it to check at various times (e.g. on startup) for new versions and it automatically downloads them. Its a very robust solution and you can do a lot with the deployment assemblies.

How do I get the command-line arguments of a Windows service?

I'm looking for a way to figure out the command-line arguments of any Windows service.
For a non-service process, the command-line arguments can be found in the Windows Task Manager, or programmatically by using WMI as shown in this post.
Unfortunately, these two solutions don't work for a Windows service that is started by the ServiceController.Start(String[] args) method. Both of them show only the executable file path on the command-line, even though some arguments were passed in.
What is the difference
between two scenarios (a service vs.
a non-service process)?
Is there a
way to figure out the arguments of the
Windows service?
I also tried creating a simple service that just logs any command-line arguments it has to the event log. I started it using "sc.exe start <my service> <arg1>" and verified that <arg1> was written to the event log.
However, none of the solutions has worked for me. I still only saw the path to the executable file. My OS version is Windows Server 2008 R2 SP1 x64 Enterprise.
There are two types of arguments for services:
Arguments that were passed on the process start command line. You can get to those easily using Process Explorer, etc.
Arguments that were passed to the ServiceMain function. This is the WIndows API that a service is supposed to implement. The .NET equivalent is ServiceBase.OnStart. This is what is used when you do an SC START \[arguments\]. This has nothing to do with "command line process arguments".
The second type of parameters is probably only known by the service itself, if the implementation makes any use of it which is not the case for many services. I don't think Windows keep track of this when we look at low level Windows structures like the PEB: Process and Thread Structures (MSDN), even the undocumented parts of it, Undocumented functions of NTDLL.
You can find the service EXE file details and edit or just see the commandline options in the registry entry for the service. You'll find that under
HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\services
Be sure to restart the Services window if you decide to change this as it won't reread it live.
Try the Process Explorer application from Sysinternals
It is like Task Manager, only it lists all the running processes. Select your service and see its properties.
A service process is not started as a usual EXE file. Even more, a service process could be just a .dll file. See: Windows service (Wikipedia).
Many appear in the processes list in the Windows Task Manager, most often with a username of SYSTEM, LOCAL SERVICE or NETWORK SERVICE, though not all processes with the SYSTEM username are services. The remaining services run through svchost.exe as DLLs loaded into memory.
Just override the ServiceBase.OnStart(string[] args) method. See more:
ServiceBase.OnStart(String[]) Method (MSDN)
Using Powershell you can call
(Get-CimInstance Win32_Service -Filter 'Name = "<my service>"').PathName
to get the full command line of the service (it returns file and arguments)
Just replace <my service> with the name of the desired service.
For example:
(Get-CimInstance Win32_Service -Filter 'Name = "Dnscache"').PathName
returns "C:\WINDOWS\system32\svchost.exe -k NetworkService -p"

Set service dependencies after install

I have an application that runs as a Windows service. It stores various things settings in a database that are looked up when the service starts. I built the service to support various types of databases (SQL Server, Oracle, MySQL, etc). Often times end users choose to configure the software to use SQL Server (they can simply modify a config file with the connection string and restart the service). The problem is that when their machine boots up, often times SQL Server is started after my service so my service errors out on start up because it can't connect to the database. I know that I can specify dependencies for my service to help guide the Windows service manager to start the appropriate services before mine. However, I don't know what services to depend upon at install time (when my service is registered) since the user can change databases later on.
So my question is: is there a way for the user to manually indicate the service dependencies based on the database that they are using? If not, what is the proper design approach that I should be taking? I've thought about trying to do something like wait 30 seconds after my service starts up before connecting to the database but this seems really flaky for various reasons. I've also considered trying to "lazily" connect to the database; the problem is that I need a connection immediately upon start up since the database contains various pieces of vital info that my service needs when it first starts. Any ideas?
Dennis
what your looking for is SC.exe. This is a command line tool that users can use to configure services.
sc [Servername] Command Servicename [Optionname= Optionvalue...]
more specificly you would want to use
sc [ServerName] config ServiceName depend=servicetoDependOn
Here is a link on the commandlike options for SC.EXE
http://msdn.microsoft.com/en-us/library/ms810435.aspx
A possible (far from ideal) code solution:
In you startup method code it as a loop that terminates when you've got a connection. Then in that loop trap any database connection errors and keep retrying as the following pseudo code illustrates:
bool connected = false;
while (!connected)
{
try
{
connected = openDatabase(...);
}
catch (connection error)
{
// It might be worth waiting for some time here
}
}
This means that your program doesn't continue until it has a connection. However, it could also mean that your program never gets out of this loop, so you'd need some way of terminating it - either manually or after a certain number of tries.
As you need your service to start in a reasonable time, this code can't go in the main initialisation. You have to arrange for your program to "start" successfully, but not do any processing until this method had returned connected = true. You might achieve this by putting this code in a thread and then starting your actual application code on the "thread completed" event.
Not a direct answer put some points you can look into
Windows service can be started Automatically with a delay. You can check this question in SO for some information about it.
How to make Windows Service start as “Automatic (Delayed Start)”
Check this post How to: Code Service Dependencies

What is the accepted pattern for an application that can be run as a service or as a console application

I have a project that is deployed to production as a windows service. However for local development purposes it would be useful to run it as a console application. At the moment I have a class Called ReportingHost that provides my core functionality, And a class called ReportingServiceHost that inherits from ServiceBase and allows me to run the application as a service. There is also a program class with a main method that calls ServiceBase.Run on my ReportingServiceHost.
I think I need to write a ReportingConsoleHost class that allows me to run the functionality in a console. Then I need to modify my Main to react to a command line switch and choose one or the other. These are the two bits I am having trouble with.
I have had a look at this and attempted to use that code but my app exits immediately, it doesn't show a console window and it doesn't wait for Enter before closing.
Part of the problem is that I dont have a deep understanding of how these things work. a definitive pattern for splitting my functionality, my two different ways of running that functionality, and a main method that chooses one of these ways based on a command line argument is what I am hoping to achieve.
I suspect your test project was configured as a windows exe, not a console exe. With a windows exe Console.ReadLine will return immediately.
To have a console exe that works both as a service and at the command line, start it as a service project (in Visual Studio) - and add a check on Environment.UserInteractive - i.e.
static void Main() {
if(Environment.UserInteractive) {
// code that starts the listener and waits on ReadLine
} else {
// run the service code that the VS template injected
}
}
You can of course also use a command line switch. I have example on microsoft.public.dotnet.languages.csharp that acts as:
an installer / uninstaller
a service
a console-mode app
depending on the switches
I have done this before by implementing a normal Windows Service (by deriving from ServiceBase), but putting a check in the main method to check for a command line argument.
If the args contain /console, start the console version, otherwise start the service.
Something like this:
internal class MyService : ServiceBase
{
internal static void Main(string[] args)
{
if (args.Length == 0)
{
// run as a service....
ServiceBase[] servicesToRun = new ServiceBase[] {new MyService()};
Run(servicesToRun);
}
else
{
// run as a console application....
}
}
}
My advise? Put all your logic for your service in a separate assembly. (A class library or DLL.) Then create one project as service which references your class library and puts the code to use as services. Create a second console project which also references your class library but which will make it available as a console application.
You would end up with three different projects in your solution but it does allow you to keep things separate. Actually, this would make it possible to extend your service in several other shapes too. You could, for example, create a 4th project as a web service and thus call your service from a web browser on a client system. Because the software logic is separated from the usage logic, you gain lots of control over it.
Be aware that a service will possibly run with more limitations than a console application. In general, services don't have network access by default, don't have a monitor assigned to them to display error messages and in general run with a limited user account or system account. Your service might work as a console yet fail as a service because of this.
There are already two good answers above - but I thought I'd post a link to Brian Noyes' Debuggable Self-Host Windows Service Project blog post - it talks about WCF but should apply to any 'Windows Service'.
The best thing is the sample code - if you can't figure out where the above examples 'fit', grab the complete project and see how it works. Thanks Brian!

Categories

Resources