System.InvalidOperationException: 'No process is associated with this object.' - c#

public static void Process(string state)
{
Process p = new Process();
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = Global.filepath + #"\PhoenixMiner.exe";
startInfo.Arguments = Global.command;
startInfo.CreateNoWindow = true;
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
p.StartInfo = startInfo;
if (state == "start")
{
p.Start();
}
else
{
Thread.Sleep(2000);
p.Kill(); //Error happens here
}
}
How can I kill the process correctly?
I tried some methods that were given in other answers but none seem to work.

You need to store a reference to the process in between clicks.
private static Process p = null;
public static void Process(string state)
{
if (state == "start" && p == null)
{
p = new Process();
p.StartInfo.FileName = Global.filepath + #"\PhoenixMiner.exe";
p.StartInfo.Arguments = Global.command;
p.StartInfo.CreateNoWindow = true;
p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
p.Start();
}
if (state != "start" && p != null)
{
p.Kill();
p.Dispose();
p = null;
}
}

The error is likely because you are trying to kill a Process which is not yet started, as per your if-else case.
public static void InitProcess()
{
Process p = new Process();
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = Global.filepath + #"\PhoenixMiner.exe";
startInfo.Arguments = Global.command;
startInfo.CreateNoWindow = true;
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
p.StartInfo = startInfo;
p.Start();
Thread.Sleep(2000);
p.kill();
}
If you want to kill the process on condition basis, better to move the process kill block (else block in your case) to separate method and check the running process before you invoke kill.
Process[] runingProcess= Process.GetProcesses();
Also, have a look at overloaded method Process.Kill(false) here

Related

Problem with running batch files from within my application

I've been trying to create a simple application to backup my Windows Server databases aswell as a whole server backup.
For this I want to use batch files which are being executed by my application.
I tried several approaches but for some reason it always fails so I'd be happy if you could help me out.
Batch file BACKUPSERVER:
wbadmin start backup -backupTarget:D: -include:C: -allCritical -quiet
I have to run the bat as administrator or it fails due to missing permissions.
C# code:
static Task<int> RunProcessAsync(string fileName)
{
............
Process p = new Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.Verb = "runas";
p.StartInfo.FileName = "cmd.exe";
p.StartInfo.Arguments = "/C \"D:\\SQLBACKUP\\BACKUPSERVER.bat\"";
p.Start();
string output = p.StandardOutput.ReadToEnd();
p.WaitForExit();
}
Debugging says 'wbadmin wasnt found'. 'runas' activated or not doesn't make any difference.
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = fileName;
startInfo.RedirectStandardOutput = true;
startInfo.RedirectStandardError = true;
startInfo.UseShellExecute = true;
startInfo.CreateNoWindow = false;
// startInfo.Verb = "runas";
var process = new Process
{
StartInfo = { FileName = fileName },
EnableRaisingEvents = true
};
process.StartInfo = startInfo;
process.Exited += (sender, args) =>
{
tcs.SetResult(process.ExitCode);
process.Dispose();
};
process.Start();
Also doesn't work.
Any ideas?
EDIT:
I'm able to run commands like shutdown but wbadmin doesn't work whatsoever...
This is how I solved the problem:
Make sure ure compiling for 64bit if u intend to use your application on 64bit system, otherwise it will redirect to different subfolders and wont find 'wbadmin.exe'.
Run wbadmin with ProcessStart or run a batch but without direct cmd input, so use this with filename = batch file or wbadmin with startInfo.Arguments:
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = fileName;
startInfo.RedirectStandardOutput = true;
startInfo.RedirectStandardError = true;
startInfo.UseShellExecute = true;
startInfo.CreateNoWindow = false;
// startInfo.Verb = "runas";
var process = new Process
{
StartInfo = { FileName = fileName },
EnableRaisingEvents = true
};
process.StartInfo = startInfo;
process.Exited += (sender, args) =>
{
tcs.SetResult(process.ExitCode);
process.Dispose();
};
process.Start();
Make sure u request administrator rights

running cmd in c# answer yes to prompt

I'm running the below command from c#. There is a prompt that will be shown that I want to answer "yes" to how can I do this with the current code
If I run this as a batch script I can just do
echo y | pscp.exe -batch -pw password E:\\Certs\\client.conf me#<ip>:/home/user
which works - but unsure how I can replicate this using the below
string pscpPath="-batch -pw password E:\\Certs\\client.conf me#<ip>:/home/user";
ExecuteCopyCerts("pscp.exe", pscpPath);
Function:
public Boolean ExecuteCopyCerts(string fileName, string arguments)
{
txtLiveHubStatus.Text = "";
try
{
System.Diagnostics.ProcessStartInfo procStartInfo = new System.Diagnostics.ProcessStartInfo(fileName, arguments);
procStartInfo.RedirectStandardOutput = true;
procStartInfo.UseShellExecute = false;
procStartInfo.CreateNoWindow = true;
System.Diagnostics.Process proc = new System.Diagnostics.Process();
proc.StartInfo = procStartInfo;
proc.Start();
string result = proc.StandardOutput.ReadToEnd();
return proc.ExitCode == 0;
}
}
Set RedirectStandardInput to true
procStartInfo.RedirectStandardInput = true
and then write to StandardInput
proc.StandardInput.WriteLine("yes");
To reiterate what Hesam said though the prompt is Y, not yes. This is the prompt for the cert, which only occurs on the first call to each new linux machine. I use this code today in one of our applications.
ProcessStartInfo psi = new ProcessStartInfo();
psi.FileName = "pscp";
psi.RedirectStandardInput = true;
psi.RedirectStandardOutput = false;
psi.Arguments = $"-r -p -pw {passWord} \"{localFileNamePath}\" {userName}#{hostName}:{remotePath}";
psi.UseShellExecute = false;
psi.CreateNoWindow = true;
using (Process process = new Process())
{
process.StartInfo = psi;
process.Start();
process.StandardInput.WriteLine("Y");
process.WaitForExit();
}

Windows auto activate method

I need a windows activate method. My code works, but it create a popup window and I don't want it.
Is there any way to activate in background without any message?
private void tryingActivateWindows()
{
ProcessStartInfo psi = new ProcessStartInfo("cmd", "/c " + "SLMGR -ato");
psi.UseShellExecute = false;
psi.CreateNoWindow = true;
Process p = new Process();
p.StartInfo = psi;
p.Start();
p.WaitForExit();
}
private void tryingActivateWindows()
{
Process activateScript = new Process();
activateScript.StartInfo.FileName = #"cscript";
activateScript.StartInfo.WorkingDirectory = #"C:\Windows\System32\";
activateScript.StartInfo.Arguments = "//B //Nologo slmgr.vbs -ato";
activateScript.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
activateScript.Start();
activateScript.WaitForExit();
}
Run "cscript C:\Windows\System32\slmgr.vbs /ato"
It will prevent the pop-up.

Close Console Window Upon Starting A New Build In Main

In main of my console application I am running an elevated version of my application if the user requests to run it elevated.
the code is doing this
elevated.exe myexe.exe //a /elevated
This code is being run in main so what happens when myexe is ran it opens a console window hits the code below and creates another console window with the new instance.
How do I close the initial window programmatically without closing the new one?
Environment.Exit(0) //closes the entire application THIS WONT WORK
enter code here
public void Run(string[] args) //myexe.exe
{
if (args[0] == "/elevated")
{
_command.RunElevated(path, arguments);
return;
}
}
Here is the meat of the RunElevated code pretty standard..
var process = new Process();
if (workingDirectory != null) process.StartInfo.WorkingDirectory = workingDirectory;
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.CreateNoWindow = true;
process.StartInfo.FileName = fileName;
process.StartInfo.Arguments = arguments;
process.Start();
// deal with output
standardOutput = process.StandardOutput.ReadToEnd();
standardError = process.StandardError.ReadToEnd();
// wait til the process exits
process.WaitForExit();
int exitCode = process.ExitCode;
OK maybe I know what's going on now. When you use UseShellExecute = false, then the program runs in the same command window, which you are closing with Environment.Exit(0).
So change to this:
var process = new Process();
if (workingDirectory != null) process.StartInfo.WorkingDirectory = workingDirectory;
process.StartInfo.UseShellExecute = true;
process.StartInfo.CreateNoWindow = true;
process.StartInfo.FileName = fileName;
process.StartInfo.Arguments = arguments;
process.Start();
Do no redirect output because 1) you can't with UseShellExecute=true, and 2) you are closing your main application anyway so why redirect things to an app that is exiting in a couple milliseconds.
With these changes you spawn your app in its own, hidden, window, then just Environment.Exit(0) your main application which will kill the non-elevated one but won't touch the process you spawned.
Here's an entirely working example:
using System;
using System.Diagnostics;
namespace ConsoleApplication4
{
class Program
{
static void Main(string[] args)
{
if (args.Length > 0 && args[0] == "/elevated")
{
var process = new Process();
/*process.StartInfo.WorkingDirectory = */
process.StartInfo.UseShellExecute = true;
process.StartInfo.CreateNoWindow = false;
process.StartInfo.FileName = "ConsoleApplication4.exe";
process.StartInfo.Arguments = "startedThroughElevatedCodePath";
process.Start();
Environment.Exit(0);
}
if (args.Length > 0 && args[0] == "startedThroughElevatedCodePath")
{
Console.WriteLine("Hello from elevated");
}
else
{
Console.WriteLine("Hello from not elevated");
}
Console.Read();
}
}
}

Git diff gets stuck when run as .NET Process

Running a Git diff gets stuck, till killed when running as a System.Diagnostics.Process.
Code:
class Program
{
static void Main(string[] args)
{
ProcessStartInfo pInfo = new ProcessStartInfo();
pInfo.FileName = "git.exe";
pInfo.Arguments = "diff --name-only --exit-code V2.4-Beta-01 HEAD";
pInfo.WorkingDirectory = #"C:\Git";
pInfo.UseShellExecute = false;
pInfo.CreateNoWindow = true;
pInfo.RedirectStandardError = true;
pInfo.RedirectStandardOutput = true;
Process p = new Process();
p.StartInfo = pInfo;
p.Start();
p.WaitForExit(10000);
if (!p.HasExited)
{
p.Kill();
Console.WriteLine("Killed!!!");
}
Console.WriteLine(p.StandardOutput.ReadToEnd());
Console.WriteLine(p.StandardError.ReadToEnd());
Console.ReadLine();
}
}
How to avoid this and make the program exists normally without expiring its timeout?
The problem is that someone has to consume the stdout buffer or it will get filled and the process gets stucked (see explanation here). The diff I was trying retrieved 983 lines, which was causing a buffer overflow.
The following is a solution to my problem:
class Program
{
static void Main(string[] args)
{
ProcessStartInfo pInfo = new ProcessStartInfo();
pInfo.FileName = "git.exe";
pInfo.Arguments = "diff --name-only --exit-code V2.4-Beta-01 HEAD";
pInfo.WorkingDirectory = #"C:\Git";
pInfo.UseShellExecute = false;
pInfo.CreateNoWindow = true;
pInfo.RedirectStandardError = true;
pInfo.RedirectStandardOutput = true;
string output = string.Empty;
Process p = new Process();
p.StartInfo = pInfo;
p.OutputDataReceived += new DataReceivedEventHandler((sender, e) =>
{
if (!String.IsNullOrEmpty(e.Data))
{
output += e.Data + Environment.NewLine;
}
});
p.Start();
p.BeginOutputReadLine();
p.WaitForExit();
p.Close();
Console.WriteLine(output);
Console.ReadLine();
}
}

Categories

Resources