This question already has answers here:
How to make GUI wait for windows service?
(5 answers)
Closed 3 years ago.
I want to start 2 related applications. First, I want to start my "Service" application and then my "Client" application. It does not consistently work. Sometimes the client starts up too fast and ends up not being connected to the service. Can someone show me where I need to change my code to work correctly and have the client only start after the service has completely started?
public class Program
{
public static void Main(string[] args)
{
Console.WriteLine("Starting Service");
StartService();
if (IsServiceRunning())
{
Console.WriteLine("Starting Client");
StartClient();
}
Console.ReadLine();
}
private static void StartClient()
{
ProcessStartInfo startInfo = new ProcessStartInfo()
{
WorkingDirectory = #"C:\Client",
FileName = "Client.exe"
};
Process.Start(startInfo);
}
private static bool IsServiceRunning()
{
Console.WriteLine("Check to see is running...");
Process[] pname = Process.GetProcessesByName("MyCommonService");
int runningCheck = 0;
if (pname.Length == 0 || runningCheck < 10)
{
Console.WriteLine("Did not find the process. Check again...");
runningCheck += 1;
Thread.Sleep(250);
IsServiceRunning();
}
Thread.Sleep(1000);
return true;
}
private static void StartService()
{
Console.WriteLine("Starting Service");
ProcessStartInfo startInfo = new ProcessStartInfo()
{
WorkingDirectory = #"C:\Service",
FileName = "MyCommonService.exe"
};
Process.Start(startInfo);
}
}
Looks like that'll always depend on how long it takes for the service to "completely start". If the service needs to do network operations to "completely start", you might have no guarantee of when the service has "completely started". Instead of simply waiting what it looks like 3,500 milliseconds, you can use interprocess communication.
What is the simplest method of inter-process communication between 2 C# processes?
Basic idea is to get your service process to communicate back to your program, and if it gives back a string that shows the service has started, only then start your client process.
I have one console application for testing purposes like following:
static void Main(string[] args)
{
do
{
for (int i = 0; i < 10000000; i++)
{
Console.WriteLine("Doing some endless loop");
Console.WriteLine(i.ToString());
}
} while (true);
}
As you can see the code is very basic, and I've set it up to endless loop in order to test what I would like to achieve.
The other console application is called "Updater" and I would like to to pause the "EndlessLoop" console application once the "Updater" application is started.
Does anyone knows if this is doable in c# .NET?
public static bool IsAppRunning()
{
foreach (Process process in Process.GetProcesses())
{
if (process.ProcessName.Contains("Updater"))
{
return true;
}
}
return false;
}
If you call this in while loop it tells you if Updater is running or not.
Not easy to communicate between 2 application
One proposition: When your console Updater starts, you create a file in folder C:\Temps\token.txt. Then, if your console EndlessLoop detects a file names token.txt in C:\Temps, you pause EndlessLoop
Have C# Console application which read/writes on standard input and output.
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Console application");
while(true)
{
int input = Console.Read();
Console.WriteLine(input.ToString());
}
}
}
I have other native application which launch above console application and read/writes with help of pipe communication.
C# console application writes are read successfully in external application and also initial writes from external application works fine and then it loops to read from the C# console application.
After that writes from external application on the pipe doesn't work.
Absurd thing is problem is happening on some of the operating system and few it is working fine.
C# Console application compile with .NET Framework 4 / Client Profile.
Known issue from MS :
http://support.microsoft.com/en-us/kb/2675468
Please check the KB for more details along with sample provided.
Try
static void Main(string[] args)
{
Console.SetIn(new StreamReader(Console.OpenStandardInput()));
while (Console.In.Peek() != -1)
{
string input = Console.In.ReadLine();
Console.WriteLine(input);
}
}
Does it work that way?
EDIT: I have updated my answer.
Sample usage/output:
dir /B | ConsoleApplication1.exe
produces:
ConsoleApplication1.exe
ConsoleApplication1.exe.config
ConsoleApplication1.pdb
ConsoleApplication1.vshost.exe
ConsoleApplication1.vshost.exe.config
ConsoleApplication1.vshost.exe.manifest
When I try your original code, it ends up spamming -1 constantly.
You can also try:
while (true)
{
int input = Console.Read();
if (input != -1) { // -1 = no input
Console.WriteLine(input.ToString());
}
}
Now it handles every character separately.
This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
How to get command line from a ClickOnce application?
I was working on a console application and manually added the string[] args inside of Main() after I had already done a bunch of other work. Is that all I have to do to accept command line arguments? Or do I need to configure something elsewhere also? I keep doing Console.WriteLine("{0}",args.Length) and get zero no matter what I send after the exe..
class Program
{
static void Main(string[] args)
{
Console.WriteLine("{0}", args.Length);
}
}
then I run ...\setup.exe yes no maybe and get 0 for length. What more do I need to do?
MORE INFO:
I tried to break after setting command line arguments in the properties page and I get the following error.:
I am thinking that someone's comment about ClickOnce deployment is my problem. How can I deploy in VS2010 to allow this?
MORE INFO:
I disabled "ClickOnce security settings" under Properties -> Security and was able to debug successfully, but when I click on Publish, it automatically turns this setting back on.. How do I prevent that?
This example:
using System;
namespace ConsoleApplication1
{
internal class Program
{
private static void Main(string[] args)
{
Console.WriteLine("Number of command line parameters = {0}", args.Length);
for (int i = 0; i < args.Length; i++)
{
Console.WriteLine("Arg[{0}] = [{1}]", i, args[i]);
}
}
}
}
When executed as ConsoleApplication1.exe a b c will output:
Number of command line parameters = 3
Arg[0] = [a]
Arg[1] = [b]
Arg[2] = [c]
See Command Line Parameters Tutorial
Update: this code
class Program
{
static void Main(string[] args)
{
Console.WriteLine("{0}", args.Length);
}
}
When executed as ConsoleApplication1.exe a b c outputs
3
Above all, make sure you're executing the correct .exe.
Perhaps you can do something like this in a for loop to check what the values if any of the command arguments are
public class CountCommandLineArgs
{
public static void Main(string[] args)
{
Console.WriteLine("Number of command line parameters = {0}",
args.Length);
foreach(string s in args)
{
Console.WriteLine(s);
}
}
}
I want to build my application with the function to restart itself. I found on codeproject
ProcessStartInfo Info=new ProcessStartInfo();
Info.Arguments="/C choice /C Y /N /D Y /T 3 & Del "+
Application.ExecutablePath;
Info.WindowStyle=ProcessWindowStyle.Hidden;
Info.CreateNoWindow=true;
Info.FileName="cmd.exe";
Process.Start(Info);
Application.Exit();
This does not work at all...
And the other problem is, how to start it again like this?
Maybe there are also arguments to start applications.
Edit:
http://www.codeproject.com/script/Articles/ArticleVersion.aspx?aid=31454&av=58703
I use similar code to the code you tried when restarting apps. I send a timed cmd command to restart the app for me like this:
ProcessStartInfo Info = new ProcessStartInfo();
Info.Arguments = "/C ping 127.0.0.1 -n 2 && \"" + Application.ExecutablePath + "\"";
Info.WindowStyle = ProcessWindowStyle.Hidden;
Info.CreateNoWindow = true;
Info.FileName = "cmd.exe";
Process.Start(Info);
Application.Exit();
The command is sent to the OS, the ping pauses the script for 2-3 seconds, by which time the application has exited from Application.Exit(), then the next command after the ping starts it again.
Note: The \" puts quotes around the path, incase it has spaces, which cmd can't process without quotes.
Hope this helps!
Why not use
Application.Restart();
??
More on Restart
Why not just the following?
Process.Start(Application.ExecutablePath);
Application.Exit();
If you want to be sure the app does not run twice either use Environment.Exit(-1) which kills the process instantaneously (not really the nice way) or something like starting a second app, which checks for the process of the main app and starts it again as soon as the process is gone.
You have the initial application A, you want to restart.
So, When you want to kill A, a little application B is started, B kill A, then B start A, and kill B.
To start a process:
Process.Start("A.exe");
To kill a process, is something like this
Process[] procs = Process.GetProcessesByName("B");
foreach (Process proc in procs)
proc.Kill();
A lot of people are suggesting to use Application.Restart. In reality, this function rarely performs as expected. I have never had it shut down the application I am calling it from. I have always had to close the application through other methods such as closing the main form.
You have two ways of handling this. You either have an external program that closes the calling process and starts a new one,
or,
you have the start of your new software kill other instances of same application if an argument is passed as restart.
private void Application_Startup(object sender, StartupEventArgs e)
{
try
{
if (e.Args.Length > 0)
{
foreach (string arg in e.Args)
{
if (arg == "-restart")
{
// WaitForConnection.exe
foreach (Process p in Process.GetProcesses())
{
// In case we get Access Denied
try
{
if (p.MainModule.FileName.ToLower().EndsWith("yourapp.exe"))
{
p.Kill();
p.WaitForExit();
break;
}
}
catch
{ }
}
}
}
}
}
catch
{
}
}
Winforms has the Application.Restart() method, which does just that. If you're using WPF, you can simply add a reference to System.Windows.Forms and call it.
Another way of doing this which feels a little cleaner than these solutions is to run a batch file which includes a specific delay to wait for the current application to terminate. This has the added benefit of preventing the two application instances from being open at the same time.
Example windows batch file ("restart.bat"):
sleep 5
start "" "C:\Dev\MyApplication.exe"
In the application, add this code:
// Launch the restart batch file
Process.Start(#"C:\Dev\restart.bat");
// Close the current application (for WPF case)
Application.Current.MainWindow.Close();
// Close the current application (for WinForms case)
Application.Exit();
My solution:
private static bool _exiting;
private static readonly object SynchObj = new object();
public static void ApplicationRestart(params string[] commandLine)
{
lock (SynchObj)
{
if (Assembly.GetEntryAssembly() == null)
{
throw new NotSupportedException("RestartNotSupported");
}
if (_exiting)
{
return;
}
_exiting = true;
if (Environment.OSVersion.Version.Major < 6)
{
return;
}
bool cancelExit = true;
try
{
List<Form> openForms = Application.OpenForms.OfType<Form>().ToList();
for (int i = openForms.Count - 1; i >= 0; i--)
{
Form f = openForms[i];
if (f.InvokeRequired)
{
f.Invoke(new MethodInvoker(() =>
{
f.FormClosing += (sender, args) => cancelExit = args.Cancel;
f.Close();
}));
}
else
{
f.FormClosing += (sender, args) => cancelExit = args.Cancel;
f.Close();
}
if (cancelExit) break;
}
if (cancelExit) return;
Process.Start(new ProcessStartInfo
{
UseShellExecute = true,
WorkingDirectory = Environment.CurrentDirectory,
FileName = Application.ExecutablePath,
Arguments = commandLine.Length > 0 ? string.Join(" ", commandLine) : string.Empty
});
Application.Exit();
}
finally
{
_exiting = false;
}
}
}
This worked for me:
Process.Start(Process.GetCurrentProcess().MainModule.FileName);
Application.Current.Shutdown();
Some of the other answers have neat things like waiting for a ping to give the initial application time to wind down, but if you just need something simple, this is nice.
For .Net application solution looks like this:
System.Web.HttpRuntime.UnloadAppDomain()
I used this to restart my web application after changing AppSettings in myconfig file.
System.Configuration.Configuration configuration = WebConfigurationManager.OpenWebConfiguration("~");
configuration.AppSettings.Settings["SiteMode"].Value = model.SiteMode.ToString();
configuration.Save();