I'm using this method: How to make a .NET Windows Service start right after the installation?
The post starts with "posted a step-by-step procedure". How can I pass parameters to the OnStart function without using registry?
I can pass parameters on this method Main(string[] args). I'm calling myapp.exe -install.
I want to call myapp.exe -install path="c:/bla bla".
And also move the path parameter to "OnStart". My OnStart exist on the YourService object in the example.
From http://msdn.microsoft.com/en-us/library/system.serviceprocess.servicebase.onstart.aspx...
The arguments in the args parameter array can be set manually in the
properties window for the service in the Services console. The
arguments entered in the console are not saved; they are passed to the
service on a one-time basis when the service is started from the
control panel. Arguments that must be present when the service is
automatically started can be placed in the ImagePath string value for
the service's registry key
(HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\).
You can obtain the arguments from the registry using the
GetCommandLineArgs method, for example: string[] imagePathArgs =
Environment.GetCommandLineArgs();.
Using your example, you'd want to put -install path="c:/bla bla" in the Services console, but this is hardly satisfactory since it's not going to be saved, i.e., you'd have to do it every time your service started. You could go the registry route, but you said you don't want to do that. The only other option that comes to mind is some kind of service configuration file.
you would pass the application name
myapp.exe /i then in your params check check to see if /i was in the command line args within that code you assign the application path you could propbably pass the path as well surrounded by " " do a google search on passing params to a console application.. same theory applies..
Related
I have a console application that will optionally self-install itself as a service. This works fine, but I'd like to embed some arguments into the service startup - similar to (for example) Google's Update Service (which has the parameter /medsvc)
So let's say I'd like my service to start
MyService.exe RUN Test1
.. so that'd start up MyService.exe with the parameters RUN and Test1.
I can install the service fine, using
ManagedInstallerClass.InstallHelper(new[] {Assembly.GetExecutingAssembly().Location});
However, there's no parameters on the service. So if I try:
ManagedInstallerClass.InstallHelper(new[] {Assembly.GetExecutingAssembly().Location +" RUN Test1"});
I get a FileNotFoundException. Giving that it's a array, I thought I'd try:
ManagedInstallerClass.InstallHelper(new[] {Assembly.GetExecutingAssembly().Location,"RUN","Test1"});
.. which gives the same exception, except that it's trying to find the file RUN now.
I can't find any specific documentation on how to achieve this - does anyone know if it is possible to embed parameters in with the service executable path? As another example, here's Google's Update Service with parameters - I'd like to ultimately achieve the same.
It took me a while to find this out, I hope it's still useful to someone.
First I found out, that you are not supposed to run ManagedInstallerClass.InstallHelper according to MSDN docs:
This API supports the product infrastructure and is not intended to be
used directly from your code.
Then I found out I could just use my own ProjectInstaller (a component class I added containing a Service Installer and a Service Process Installer) to install the service like this:
ProjectInstaller projectInstaller = new ProjectInstaller();
string[] cmdline = { string.Format("/assemblypath={0} \"/myParam\"", Assembly.GetExecutingAssembly().Location) };
projectInstaller.Context = new InstallContext(null, cmdline);
System.Collections.Specialized.ListDictionary state = new System.Collections.Specialized.ListDictionary();
projectInstaller.Install(state);
Be sure to encapsulate your parameters in quotes and escape the quotes, otherwise your parameters will become part of the executable path and fail to start.
The end result will be a new service with the specified properties in your Service Installer and Service Process Installer, and a path just like in your screenshot (with the /medsvc parameter for example).
I use a console application inside my windows service. The Main method in Program.cs processes the command line args. The OnStart method starts the console application. It works great.
Windows Service to Run Constantly
HybridService Easily Switch Between Console Application and Service
Only parameters before location are being passed into the context for the installer.
Try this:
args = new[] { "/ServiceName=WinService1", Assembly.GetExecutingAssembly().Location };
ManagedInstallerClass.InstallHelper(args);
Reference from another answer: Passing Parameter Collection to Service via InstallHelper
I am writing an c# services in VS 2015 and I need to pass a parameter when the service starts. I entered the parameter like this:
enter image description here
and my code in the service looks like this
protected override void OnStart(string[] args)
{
System.Diagnostics.Debugger.Launch();
try
{
base.OnStart(args);
WriteToFile("args = " + args[0].ToString());
When I start the services I get the following error: "Index was outside the bounds of the array" which tells me that the argument is not read. Where am I going wrong.
thanks;
The key thing to know is that a process can contain more than one service.
The arguments passed to Main are typically used to instruct the process to do things like install itself, uninstall itself, perform maintenance tasks, or enter the service control loop (i.e. to call ServiceBase.Run).
The arguments passed to OnStart on the other hand come from the Service Control Manager, not from the command line. They are typically used to instruct the process which process to start (if there is more than one service managed by the process).
The Main parameters are configured as part of the "path to executable".
The OnStart parameters are configured as "Start parameters" in the service settings.
You need to pass the arguments otherwise args[0] is null .. in debug mode goto project settings pass the build arguments,check how it's working
The steps of my application are:
Go to the setting page first, and the setting page will register the Registry Log (as 'regedit' in command line) in the background (people may seldom go to the setting page).
When users clicks the URL in a web page, it will trigger the registry and open my application.
The appplication reads the parameter that it gets and does things depending on the parameter value.
User may click on different links to send different parameters to my application
That is, if the application is not opened, it should be launched it and reads the parameter. If the application is already opened, it should just read the parameter.
The problem is: how could find out the different situations of my application - whether it is opened or not - and then use the parameter correctly?
The part of registry( in setting page):
Registry.ClassesRoot.CreateSubKey("MyApp").SetValue("", "URL:MyApp Protocol");
Registry.ClassesRoot.CreateSubKey("MyApp").SetValue("URL Protocol", "");
Registry.ClassesRoot.CreateSubKey("MyApp\\DefaultIcon").SetValue("", "\"" + Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName) + "\\" + "MyApp.exe" + ",1\"");
Registry.ClassesRoot.CreateSubKey("MyApp\\shell\\open\\command").SetValue("", "\"" + Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName) + "\\" + "MyApp.exe" + "\" \"%1\"");
%1 is the parameter I will get( from url to my application).
And the web link may be:
Call for Function 1
Call for Function 2
So there are many links in the web page to call same application.
But I cannot let my application be opened every time (that is, there should be only one application opened, and other clicks on links will only send parameters to the app).
I know how to find out whether the application is opened or not by the code:
Mutex mul = null;
bool is_createdNew;
try
{
string mutexName = Process.GetCurrentProcess().MainModule.FileName.Replace(Path.DirectorySeparatorChar, '_');
mul = new Mutex(true, "Global\\" + mutexName, out is_createdNew);
if (!is_createdNew)
{
// application be opened already, I close the application originally
Environment.Exit(Environment.ExitCode);
}
else
{
// the application is first run, open my MainWindow
}
}
catch (Exception ex)
{
throw ex;
}
finally
{
}
Is it possible to send the parameter as a method of registry when the application is opened?
I even think about reading registry by Registry.GetValue, when my application starts up,
to use timer to read registry value per second......
This is my first time face this situation of user's request,
hope someone can give me any direction!
Thanks in advance.
When you find out that another instance of your application is already running (which you do in your code above using Mutex), you can programatically pass the parameter (of the second app instance) to the first, already running app instance and then just close the second app instance. This code for passing parameter to the first app instance would then be just before Environment.Exit(Environment.ExitCode);
(Presuming that your app is relatively small and does not loads lots of libraries on startup - in that case it would be better to create a separate small launcher app)
The problem is, how to pass the parameter between two independent processes - two instances of your app.exe. There are of course several options, look here:
Send/Receive message To/From two running application
I would use FileWatcher or Memory mapped file as it is specified in that answer.
The solution with timer and changing registry values is not good (registry operations require admin access, registry operations are not so fast etc.).
Here is a nice library that shows, how to pass parameters between 2 processes using Memory mapped file.
http://code.msdn.microsoft.com/windowsdesktop/Inter-process-communication-e96e94e7
I found another way to solve my problem,
just simply add 'static' before Mutex.
See the detail: C# static
I want to restart a set of windows services which are running on my local computer.
I want to restart all these services at once when i click a button in my asp.net application ?
I would appreciate if any one can help me out .
As of now i am able to implement the scenario for restarting a single windows service by using
Service Controller Class.
Just put a loop in iterating through each service name. Create a ServiceController for each service name and restart it there.
List<string> serviceList = //however you get all of the services you want to start, put them in here.
foreach(string serviceName in serviceList)
{
ServiceController controller = new ServiceController(serviceName);
....
controller.Restart();
}
To use a batch file use:
System.Diagnostics.Process.Start(pathToBatchFile);
You can manage the process by using intellisense and a little curiosity. Also, here is an msdn article I found for you.
http://blogs.msdn.com/b/csharpfaq/archive/2004/06/01/146375.aspx
To hide the command prompt and have more control over the process, use the System.Diagnostics.ProcessStartInfo class and pass its object to the Process.Start method. You can even catch the output from the batch file inside your program.
I am trying to start an external process from a .NET Windows service. In the past I have used the Process.Start() overload that takes the executable path and a command line string. This works. But now I would like to start the process and have it run in the context of a particular user. So I call this version of Start()
public static Process Start(
string fileName,
string userName,
SecureString password,
string domain)
However, when I call the method, the application I am trying to run generates an unhandled exception:
The application failed to initialize properly (0xc0000142). Click on OK to terminate the application.
I have tried to start different applications and they all generate the same exception. I have run the code outside of the Windows service and the application starts correctly.
So is there a way to get this to work in a Windows service?
Maybe the user has to have, "logon as a service" security right. This is done with the "local security policy" application. And/or "logon as a batch job".
This is very similar to this question here. The answer is usually due to security issues with the desktop and window station in which the process is being run. See this article for an explanation and some sample code.
This is just a shot in the dark, but perhaps you can try to run the Windows Service in Interactive mode. If that works, though, this can't be done in Windows Vista (because of Session 0 Isolation).
Use Filemon and see if it is trying to open a config file and not finding it. I once had this error due to a malformed config.