Why do I get "No process is associated with this object." when calling process.Close() or process.Kill()? - process

I have a C# program that is launching TShark.exe which is the background equivalent of WireShark. I would like to close all instances that I start. It appears to start just fine, run in the background and log network traffic to a file as it should. However, when I try to close it, I get a "No process is associated with this object." exception.
Here is how I'm starting the processes:
ProcessStartInfo processStartInfo = new ProcessStartInfo
{
Arguments = $"-i {nic} -t ad -w {GenerateLogPath(nic)}",
FileName = "\"C:\\Program Files\\Wireshark\\tshark.exe\"",
CreateNoWindow = true,
WindowStyle = ProcessWindowStyle.Hidden,
UseShellExecute = false
};
WireSharkProcesses.Add(System.Diagnostics.Process.Start(processStartInfo));
I've tried several methods to close/kill these processes. First, I kept a list of all processes that I had started in my app and called the following on them without success:
process.CloseWindow();
process.Close();
process.Kill();
I kept getting the "No process is associated with this object." exception.
So, I used:
var processes = System.Diagnostics.Process.GetProcesses();
And got a list of all processes on my machine and looped through them and attempted to close those who's process name was "tshark" or "dumpcap". I attempted this with .CloseWindow(), .Close(), and .Kill() all of which failed and threw the above exception.
I even went into TaskManager and attempted to END TASK on them. They appeared to be removed, but upon closing and re-opening TaskManager, they magically reappeared. There are also now several instances of "tshark" and "dumpcap" that show up when I call GetProcesses(), but are not in the list of processes that Task Manager shows.
What am I missing here?? Short of rebooting my machine, how do I get these processes to exit? Is this just a wireshark problem, or a general problem with killing processes?

Are you using WinPcap or Npcap? If you're using WinPcap, you could try switching to Npcap and using that instead. See Gerald Comb's comment #32 on the recently closed Wireshark Bug 14701.
By the way, in case you weren't aware, tshark is capable of capturing on more than one interface at a time, so in theory only a single instance is required. I understand that this can sometimes cause reassembly problems though, so if that's what you're trying to avoid or if you just want to keep packets separated by interface, then yes, you'll have to start multiple instances.

Related

How to get Process object of already running process?

I want a create a C++ program that can find an already running process and then redirect its Standard Output to my own stream for re-direction. I can find countless examples on how to start a new process but I want to try and do something like:
Process^ proc = new Process();
proc->Attach("notepad.exe");
And then have control over the already running notepad.exe process.. Is this possible? If not then I guess I can find a way to start the process from within my application, however then my question would be how can I start a process and send command-line arguments to the process as if I were starting it up in console.
I believe you want GetProcessesByName. It will return an array of all the processes that match the name you give.
array<Process^>^ notepadProcesses = Process::GetProcessesByName("notepad");

Allow only one running instance of a program

How can i restrict my program to run only instance? Currently i'm running my program as daemon(starts and stops automatically), and when user clicks and tries to launch again(which is not a valid usecase), process gets launched in user context and i would like to avoid this for many reasons.
How can i achieve this?
As of now i'm getting list of processes and doing some checks and exiting at the begining itself but this method is not clean, though it solves my problem.
can someone give me a better solution?
And i'm using ps to get process list, is there any reliable API to get this done?
Use a named semaphore with count of 1. On startup, check if this semaphore is taken. If it is, quit. Otherwise, take it.
Proof of concept code: (put somewhere near application entry point)
#include <semaphore.h>
...
if (sem_open(<UUID string for my app>, O_CREAT, 600, 1) == SEM_FAILED) {
exit(0);
}
From the sem_open documentation,
The returned semaphore descriptor is available to the calling process until it is closed with sem_close(), or until the caller exits or execs.

Erlang/OTP, how to signal an application startup error without a crash

So I have this application that has a process that requires some gen_servers to be alive somewhere else in the cluster.
If they are up it just works, if they are not, my gen_server fails in init with {error,Reason}, this propagates through my supervisor into my applications start function.
The problem is that if I return anything other than {ok,Pid} I get a crash report.
My intention here would be to somehow signal that the application couldn't start properly and that all the processes are down and because of that the application should not be considered active, however, I can only choose to return {ok, self()} and see my application listed as active when it is not, or return {error, Error} and see how it crashes with:
{gen_server,init_it,6},{proc_lib,init_p_do_apply,3}]}},{ancestors,[rtb_sup,<0.134.0>]},
{messages,[]},{links,[<0.135.0>]},{dictionary,[]},{trap_exit,false},{status,running},
{heap_size,377},{stack_size,24},{reductions,255}],[]]:\n"
The problem seems to be bigger than this, basically there is no way to tell to the application framework that the app failed. It may look like one of these things that are handled by let the process die in erlang, but allow for an {error, } return value on application:start seems like a good tradeoff.
Any hints?
Application will crash at any moment, so application's dependence relationship at the start time can not provide helpful dynamic crash information.
Before I have read part of rabbitmq project source code, it is also a cluster-based program.
I think rabbitmq has faced your similar question as you said, because cluster need collect related nodes's application "is live" information and memory water highmark information and then make decision.
It's solution is
to register the the first main process of the application in the node locally, the name is "rabbit" in the rabbitmq system, you can find it is rabbit.erl file, and in the function "start/2".
start(normal, []) ->
case erts_version_check() of
ok ->
{ok, SupPid} = rabbit_sup:start_link(),
true = register(rabbit, self()),
print_banner(),
[ok = run_boot_step(Step) || Step <- boot_steps()],
io:format("~nbroker running~n"),
{ok, SupPid};
Error ->
Error
end.
And the other 4 modules, rabbit_node_monitor.erl, rabbit_memory_monitor.erl,
vm_memory_monitor.erl, rabbit_alarm.erl to use two erlang technique, one is monitor process to get "DOWN" message of the registered process, the other is alarm handler to collect these information.

vb.net - Problem remaking com object after program has closed

Have been searching for a solution to this problem for days with no luck so I decided to post here and hope someone can help me. What makes it even harder is that I can't replicate this problem on my computer very consistently. Sometimes I will get the error but most of the time I won't.
Basically what is happening is I am creating an IE object which my program then controls for a long period of time. What is happening is, if a user exits the program it calls oIE.Quit() then closes the program. This should close internet explorer and all processes associated with it.
But, the iexplorer process doesn't end up closing. Then when the user tries to run the program again we get this error "System.Runtime.InteropServices.COMException (0x80004005): Creating an instance of the COM component with CLSID {0002DF01-0000-0000-C000-000000000046} from the IClassFactory failed due to the following error: 80004005.".
To fix this we simply close the any iexplorer.exe processes that are open and it will let us create our ie object again. This happens also if the program crashes and they try to restart it.
I am not sure what is causing this or if I am missing something that has to do with com objects. But I am simply stuck.
Here is some code although plugging in this code likely won't reproduce any errors:
'create ie object
oIE = New SHDocVw.InternetExplorer
oIE.Navigate("http://www.google.com")
oIE.Visible = False
oIE.Silent = True
'kill ie object
oIE.Quit()
The exception you get is hopeless, that's E_FAIL, "Unspecified error". There isn't any obvious reason why this would fail, starting another instance of IE when your program starts back up shouldn't be a problem. Well, short from those ghost instances of IE that keep running forever. I would guess that you got this exception for the same reason that IE didn't quit when you called Quit() the last time.
Do consider the kind of mishap you'll create when your program aborts and doesn't get around to cleanly shutting down IE. Using Environment.Exit() would be quite unhealthy for example. Or any other kind of nasty kaboom that doesn't let the finalizer thread run at termination. Maybe that has already happened many times before, now IE just refuses to create any more instances? How many instances do you have to kill when you need to get it going again?
The much better mousetrap here is to run IE in-process in your own program rather than out-of-process with SHDocVw. So that when your program terminates, it takes IE with it. It is also much more efficient, there's a lot of overhead involved in making out-of-process COM server calls.
You do this by using WebBrowser in your program.

Restart Service when Exception is thrown

I am writing a windows service that needs to be running 24/7. It is a pretty simple service that monitors a directory where files are dropped into and processes those files. I need to restart the service if an unhandled exception is thrown.
Is there a way for a service to restart itself in the event of an unhandled exception?
The Services applet has many different recovery features:
It can take different actions on the first, second, and subsequent failures:
Restart the service, after a configurable delay
Run a Program (passing command line parameters, possibly including the failure count)
Restart the Computer (after a configurable delay, and with a particular message being sent)
The program that runs should be able to look in the event log and see the reason for failure (especially if you log it), and should therefore be able to disable the service if the exception is one that is not recoverable.
And, of course, in the meantime, the service should be logging what's going on, which should enable any management tool to notify Operations of what's going on.
I agree that you should probably not configure "third and subsequent" to be "restart service", or you could wind up in a loop.
Have you tried using the Recovery tab of the Service entry - you can set rules for failures, including "Restart the Service" - by default this is on "No Action"
This is able to be done programatically if you wanted, this code was not written by me. I am posting the link to the Authors CodeProject page that contains the source / binaries. Below the link I have explained how I implemented the authors code.
http://www.codeproject.com/KB/install/sercviceinstallerext.aspx
Add a reference to the DLL.
Open ProjectInstaller.Designer.vb in notepad
In the InitializeComponent Sub
CHANGE
Me.ServiceProcessInstaller1 = New System.ServiceProcess.ServiceProcessInstaller
Me.ServiceInstaller1 = New System.ServiceProcess.ServiceInstaller
TO
Me.ServiceProcessInstaller1 = New System.ServiceProcess.ServiceProcessInstaller
Me.ServiceInstaller1 = New Verifide.ServiceUtils.ServiceInstallerEx
With the Friend Declarations in the ProjectInstaller.Designer.vb
CHANGE
Friend WithEvents ServiceProcessInstaller1 As System.ServiceProcess.ServiceProcessInstaller
Friend WithEvents ServiceInstaller1 As System.ServiceProcess.ServiceInstaller
TO
Friend WithEvents ServiceProcessInstaller1 As System.ServiceProcess.ServiceProcessInstaller
Friend WithEvents ServiceInstaller1 As Verifide.ServiceUtils.ServiceInstallerEx
CHANGE
Me.Installers.AddRange(New System.Configuration.Install.Installer() {Me.ServiceProcessInstaller1, Me.ServiceInstaller1})
TO
Me.Installers.AddRange(New System.Configuration.Install.Installer() {Me.ServiceInstaller1, Me.ServiceProcessInstaller1})
Import The Namespace On ProjectInstaller.vb
In ProjectInstaller.vb in the Public Sub New Function After Initialize component function has been called
ADD
'Set Reset Time Count - This Is 4 Days Before Count Is Reset
ServiceInstaller1.FailCountResetTime = 60 * 60 * 24 * 4
'ServiceInstaller1.FailRebootMsg = "Houston! We have a problem"
'Add Failure Actions
ServiceInstaller1.FailureActions.Add(New FailureAction(RecoverAction.Restart, 60000))
ServiceInstaller1.FailureActions.Add(New FailureAction(RecoverAction.Restart, 60000))
ServiceInstaller1.FailureActions.Add(New FailureAction(RecoverAction.None, 3000))
ServiceInstaller1.StartOnInstall = True
Build installer and install. Voila
Wrap your service code in a runner which can catch any errors and restart your service.
The best way is to wrap Try / Catch blocks around the methods in the service you can afford to let throw exceptions.
However, there may be serious exceptions thrown that should result in the service being stopped immediately. Don't ignore these! In these cases, handle the exception, log it, email it and then rethrow it. That way you will be informed that the exception has occurred and will know what went wrong. You can then fix the problem and re-start the service manually.
Just ignoring it could cause a major failure in your system which you would not know about. It could also be very expensive on CPU/RAM if the service stops then restarts then stops ad infinitum.
As suggested by "John Saunders" and "theGecko", you can monitor the service and restart it when it fails. The builtin Windows Service Recovery functionality will get you a long way, but if you find that you need some more advanced features (for example, CPU hogging and hang detection) then please check out Service Protector. It is designed to keep your important Windows Services operating 24x7.
Good luck!