I have a few Windows Services written in C# that I have setup to support being run from the command line as a console app if a specific parameter is passed. Works great but I would love to be able to detect whether the app is being run by the service control mananger or from a command line.
Is there any way to tell at runtime if my app was started by the SCM?
Environment.UserInteractive will return false if the process is running under the SCM.
The SCM will call your OnStart method, so you could mark that event and make sure when you run from the command line, you don't call OnStart. Or, you could check the startup parameters to see how the application was started.
In C the function StartServiceCtrlDispatcher() will fail with ERROR_FAILED_SERVICE_CONTROLLER_CONNECT. This is the best way in C, wonder if C# exposes any of this?
ERROR_FAILED_SERVICE_CONTROLLER_CONNECT
This error is returned if the program is being run as a console application rather than as a service. If the program will be run as a console application for debugging purposes, structure it such that service-specific code is not called when this error is returned.
Related
We are using Spring XD for executing some batch jobs and considering to use Spring Cloud Dataflow. For this I wanted to remote debug a execution of a Task and I was not able to make it working.
I tried to export the following environment variable before the SCDF server is started:
spring.cloud.deployer.local.javaOpts=Xdebug -Xrunjdwp:transport=dt_socket,address=12201,server=y
Also tried to pass as argument in the GUI while invoking the task:
app.<appname>.local.javaOpts=Xdebug -Xrunjdwp:transport=dt_socket,address=12201,server=y
Nothing seems to be working.
I'm able to debug the composed-task-runner launched by SCDF using the listen debugger mode, this will also work for your task as well.
Run Debugger in your IDE in listen mode on port 5006. (this project's classpath should have composed-task-runner sources, put break point some where )
Run SCDF with -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005 option, attach debugger to the SCDF process in your IDE on port 5005 (attach mode).
Put breakpoint at this line :
String javaOptsString = getValue(deploymentProperties, "javaOpts");
in JavaCommandBuilder class (for spring-cloud-deployer-local v.1.3.0.M2 it's line #83).
Launch your task - debugger stops at breakpoint.
Step Over once in your IDE, the value of javaOptsString is null now. Using IDE, set the value of javaOptsString to
-agentlib:jdwp=transport=dt_socket,server=n,address=localhost:5006,suspend=y
Press Resume in IDE.
Your breakpoint set in #1 should be hit in few seconds.
If you know how to pass javaOpts as deployment properties of your task - you will be able to debug in listen mode without this nightmare ;-). I've not found a way to escape = and , characters in the -agentlib:jdwp=transport=dt_socket,server=n,address=localhost:5006,suspend=y javaOpts deployment property.
We are working on an improved solution for the local-deployer - you can follow spring-cloud/spring-cloud-dataflow#369 for tracking purpose.
There is, however, the following option that exists to aggregate all the application logs into the server console directly, which might be useful while in active development.
stream deploy --name myStream --properties "deployer.*.local.inheritLogging=true"
Finally I was able to remote debug a composed task or regular task. Follow the below steps:
In scdf UI go to tasks and click on the definition section
Click play button (invoke) on the task/composed task that you want to invoke.
On the launch task page define your task arguments
Add the following properties by clicking 'Add Property' button:
- deployer.composed-task-runner.local.debugPort=12103
- deployer.composed-task-runner.local.debugSuspend=y
Now launch the task
You can now see in the log that when the composed task's java process is launched it is called with the debug parameter.
If you want to control the heap memory or any java options you can do by adding the following property:
deployer.composed-task-runner.local.javaOpts=Xmx2048M
Note that 'composed-task-runner' is the name of the App (Not the name of the task).
Whenever a specific Windows service fails I want to run a program I've created myself. However, I simply can't find a way to make it fail on purpose, so that I can actually test that everything works correctly.
Note that the service in question is not something I've written myself, so I can't make it fail programmatically from inside the code. I wouldn't, however, mind writing a program that can make a service fail.
Of course I would prefer just having a "Make service fail" button somewhere in services.msc ... ;)
The server I'm doing this on is running Windows Server 2012.
If you don't want to use command line :
As an admin open the Windows Task Manager, in the Services tab find the service you want to test. Right click the service and click on Go to process. The selected process (if any) is the one corresponding to your service. Kill this process to simulate a service failure.
Be aware that killing a process this way can lead to problems.
Define "fail". If you want the process to end, just use pskill or a similar tool that can terminate a process elevated (as an admin).
I'm very new to IDL (trying to do a POC for someone using it) and I am trying to run an external command. The line of code I have added is this:
spawn, 'C:\Program Files\ITT\IDL\IDL80\products\envi48\save_add\visual.exe'
I thought this was all that was needed to launch an external command. When I run the app, i can use the debugger to step through the code, and when I get to this line and Step over, my executable does not run. I see no messages in the debugger indicating any type of error.
I put the file visual.exe in the directory and can run it by hand with no issues. It just seems to step right over the code without executing it or reporting any error.
You can use the form:
spawn, cmd, result, errResult
to get the any error messages that might be generated from the cmd. In your particular case, I think you need to quote the path to the executable because of the space in the path.
Your usage of the spawn command is correct. Perhaps visual.exe is exiting prematurely
for some reason (for example, maybe the working directory when run via spawn isn't what
your external program is expecting.)
You might try writing a little script that starts visual.exe, then does a pause,
and then spawn the wrapper script instead of visual.exe directly. That might
give you a chance to see any error messages before the DOS window disappears.
I am thinking the modified dlls will create a log file some where in the remote system so I can open it later after load test but all I found was a log file in $(SystemRoot)\Temp\EQATECProfilerLogs saying nothing other than app started. Do I need to install EQATEC profiler on the remote server?
Thanks
This scenario is adressed in this EQATEC forum thread:
A profiled app needs to be told when we want it to produce its profiling report. For plain apps this is simple and has therefore been automated: when Main exits. But your web-service has no similar "exit point" - it just keeps on running until you kill it.
Therefore you have to explicitly/manually tell the profiled web-service to take a snapshot. The easiest way is to simply run the profiler on the same machine as the web-service is running on: when the web-service is starting up it will automatically connect to the profiler and you can then run your tests and control/dump timing info at will using the "take snapshot" and "clear counters"-buttons.
Alternatively, you can make a reference to the supplied runtime-module from within your code and make explicit calls to the API (TakeSnapshot etc) precisely where you want in your code. The runtime-modules reside in C:\Program Files\EQATEC\EQATECProfiler\RuntimeDLL.
This question already has answers here:
Can one executable be both a console and GUI application?
(9 answers)
Closed 6 years ago.
Is it possible to (and if so, how do I) make a single program work both as a console application and a GUI version using Delphi 2007?
What I am after is that if the program is run with the appropriate command-line options, it should function as a console program, printing output to the console using WRITELN, but if no command line arguments are given it should run as a normal Delphi GUI application?
The catch is that when running as a console application, the command line interpreter waits for the application to terminate before allowing you to enter a new command, whereas a GUI application started from the command line immediately returns you to the command line and the GUI application is started in a detached process. I want this behaviour retained.
I don't mind something like this:
IF GUI THEN StartApplicationAsGUI(ParamStr(0))
ie. I don't mind that I'll have to restart the application using some form of EXECUTE call to start it in GUI mode if needed, as long as the command line interface returns to the command line input when the GUI version is started.
I'd prefer a solution/suggestion that is along the lines of:
<Parse Comnand Line>
IF ConsoleMode THEN
RunConsole(Parameters)
ELSE BEGIN
Application.Initialize;
Application.CreateForm(...)
Application.Run;
END
(or vice-versa, ie. doing things a special way if GUI mode)
so that I can still use Delphi's IDE and VCL when making the GUI interface...
On Windows this is a little bit tricky. Actually the distinction between a console application and a GUI one is a single flag in the PE header. You can easily write console applications that create windows but that way you always have the console window around (you could hide it, though, but that wouldn't be nice when people run your program from cmd).
You can, however write a GUI application that creates a console if it needs to, using the AllocConsole function:
A process can be associated with only one console, so the AllocConsole function fails if the calling process already has a console. A process can use the FreeConsole function to detach itself from its current console, then it can call AllocConsole to create a new console or AttachConsole to attach to another console.
If the calling process creates a child process, the child inherits the new console.
AllocConsole initializes standard input, standard output, and standard error handles for the new console. The standard input handle is a handle to the console's input buffer, and the standard output and standard error handles are handles to the console's screen buffer. To retrieve these handles, use the GetStdHandle function.
This function is primarily used by graphical user interface (GUI) application to create a console window. GUI applications are initialized without a console. Console applications are initialized with a console, unless they are created as detached processes (by calling the CreateProcess function with the DETACHED_PROCESS flag).
However, when run from cmd this will likely cause another console window to appear instead of re-using the existing one. I don't know whether a good solution exists there.
IMO, the best approach here is to have non-visual classes that actually do the work of the program. Then you can call that from a GUI program, and you can also call it from a separate command line program. Both programs are just wrappers around the functionality of your class(es).
This forces the design to be clean too - your classes necessarily are separated from the GUI layer of your application.
http://blogs.msdn.com/oldnewthing/archive/2009/01/01/9259142.aspx
Windows has different values in executable's header for console and UI application (see more details here). So it seems to be impossible to make the same executable to work in both modes.
As an alternative, you can open a console in you UI app, but it will be new console, not the one you've started app from.
AttachConsole() may be used to get a hold of the parents console.
E.g. if the application is started from a cmdline shell, AllocConsole() can be avoided:
if not AttachConsole(ATTACH_PARENT_PROCESS)
then AllocConsole;
More info here:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms681952(v=vs.85).aspx