Visual Studio delay between multiple startup projects? - c#

how to add some delay between startup projects in solution?
I want Client project to be started after 2-3 seconds from starting WindowsService.
Why I need this?
WindowsService runs socket server and Client runs socket to connect to server. WindowsService loads slowly than Client, and this causes an exception on client side when connecting to server which is not run yet

I would probably add a retry mechanism within the client. That way not only does it help in the "starting up from Visual Studio" case - it also helps if the server happens to be restarting while the real client connects. The fact that the server is on a faster machine doesn't mean the server will never need to restart, does it?
Indeed, you may well want to add this retry mechanism in such a way that the client can recover even if the server is restarted while it's connected. It depends on what the project is doing, of course.

You can use Mutex locking to sync the two startup project.
Program 1 (StartUp Project 1):
namespace ConsoleApplication1
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
class Program1
{
private static bool isNewMutexCreated = true;
private static Mutex mutex;
static void Main(string[] args)
{
mutex = new Mutex(true, "Global\\ConsoleApplication1", out isNewMutexCreated);
AppDomain.CurrentDomain.ProcessExit += new EventHandler(CurrentDomain_ProcessExit);
Console.WriteLine("Application1 executed on " + DateTime.Now.ToString());
Console.ReadKey();
}
static void CurrentDomain_ProcessExit(Object sender, EventArgs e)
{
if (isNewMutexCreated)
{
Console.WriteLine("Mutex Released");
mutex.ReleaseMutex();
}
}
}
}
Program 2 (StartUp Project 2):
namespace ConsoleApplication2
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Threading;
class Program2
{
static void Main(string[] args)
{
Mutex mutex = null;
Thread.Sleep(5000);
while (mutex == null)
{
try
{
mutex = Mutex.OpenExisting("Global\\ConsoleApplication1");
}
catch (Exception)
{
Console.WriteLine("Mutex not found on " + DateTime.Now.ToString());
Thread.Sleep(3000);
}
}
Console.WriteLine("Application2 executed on " + DateTime.Now.ToString());
Console.ReadKey();
}
}
}

Another simpler option for testing is to just delay the client if the debugger is attached like this:
if (System.Diagnostics.Debugger.IsAttached)
{
System.Threading.Thread.Sleep(2000);
}
You might wrap that in an #if DEBUG block if you like. Anyway I think this should be the least amount of work :)

In case of multiple start-up projects, they are loaded in the order they are specified neither simultaneously nor randomly. http://msdn.microsoft.com/en-us/library/09138bex(v=vs.90).aspx
So ,may be if you specify "client" after "window service", then it may workout fine. And if you don't want to got the coded way suggested above, then (for testing only) you can manually attach the "client" process to you solution from a different solution after your desired delay.
http://msdn.microsoft.com/en-us/library/c6wf8e4z(v=vs.100).aspx

If the client needs to be started after, you need to adjust your list, as at the moment its started before!
I would also code a "/wait" which on loading app if it finds that flag, waits for it maybe useful in use too.

You can set the server project as the single startup project and use this macro to launch the server and the client with a delay:
Sub DebugServerAndClientWithDelay()
DTE.Debugger.Go(False)
System.Threading.Thread.Sleep(2000)
DTE.Windows.Item(Constants.vsWindowKindSolutionExplorer).Activate()
DTE.ActiveWindow.Object.GetItem("SolutionName\ClientProjectName").Select(vsUISelectionType.vsUISelectionTypeSelect)
DTE.ExecuteCommand("ClassViewContextMenus.ClassViewProject.Debug.Startnewinstance")
End Sub
You can add a button to your toolbar or use a shortcut key to run this macro.

Just add a procedure to check whether the socket is open or not. If the socket is open continue executing your code and try checking again if the socket is not open. This way even if you start the windows service later there will be no problem.

For the n-tier application I am currently working on, I combined the Mutex method suggested by Romil (slightly different code but same principle) and encapsulated it within a method with a [Conditional("DEBUG")] attribute applied (so it gets stripped out in release mode). We also surround the mutex logic with if (System.Diagnostics.Debugger.IsAttached) {...} since QA builds use Debug mode.
We originally just used a Thread.Sleep with a wait period that worked for most developers machines, but we ran into problems because devs' computer speeds vary and as we added more and more to the server bootstrapper, we had to keep increasing the wait period.

Why don't you just pass an argument to the client application which sets the delay?
static void main(string[] args)
{
// Sleep some time
int delay;
if (args.Length > 0 && int.TryParse(args, out delay))
{
Thread.Sleep(delay);
}
// Initialize client
}
Now you can add the delay in milliseconds to the command-line arguments for the project startup.
I also agree that if possible, it's better to solve your problem structurally, so it doesn't matter when your client and server start.

Related

Semaphores and multiple command line processes

I have a C# command line exe that I am trying to limit to a max of 3 occcurrences. I am using Semaphores. The code is below.
private static void Main()
{
using (Semaphore semaphore = new Semaphore(3, 3, "testing"))
{
if (!semaphore.WaitOne(100))
{
Console.WriteLine("Sorry too late");
Environment.Exit(0);
}
}
Console.WriteLine("Hello world");
Thread.Sleep(100000000);
}
I press CTRL-F5 (run without debugging) three times and my processes fire off and all sleep. I then start a fourth occurence and it runs without a problem.
What am I doing wrong?
Semaphore objects are special, in that you can give them "system names", as you have done, to make them synchronize across processes.
This means that I was initially incorrect in thinking each process would create its own version, and that was causing your problem.
However, you are using it in a using block, so after it has done its work, it disposes it. The next process makes a new one, etc. See MSDN for a working example of how to do this correctly.
Remove the using block, or alternatively, don't use a Semaphore for this, just do:
if (Process.GetProcessByName(Process.GetCurrentProcess().ProcessName).Length < 4)
//You are ok!
To check against the number of running instances of your process.
In addition to Bradley's fine answer, I wonder if your code should instead read:
private static void Main()
{
using (Semaphore semaphore = new Semaphore(3, 3, "testing"))
{
if (!semaphore.WaitOne(100))
{
Console.WriteLine("Sorry too late");
Environment.Exit(0);
}
Console.WriteLine("Hello world");
Thread.Sleep(100000000);
}
}
...because whilst the program is essentially running, you want to consume the semaphore not release it right away due to the Dispose()

C#: close process on app's process' killing (with taskman)

I'm very new to C# so my question may sound rediculous. I'm developing an application which sometimes need to run ffmpeg. As you guess, this ffmpeg process must be killed when it's host app was closed. I use such code for this task:
AppDomain.CurrentDomain.ProcessExit += new EventHandler(OnProcessExit);
private void OnProcessExit(object sender, EventArgs e)
{
proc.Kill();
}
This works fine, when the app is closed correctly (via it's interface or with Taskman - Applications). The problem is that OnProcessExit event won't trigger, if the program's process was killed (with Taskman - Processes). As far as I know, killing process and closing program actions are not the same on the low level, but I guess, killing process is a command to it and it can be handled with C# tools. So, is it possible, to close child process in this case?
I think Try this
Application.Exit();
I recommend to use job objects (as per Scott Miller suggestion).
Another option can be have special helper app for your app, which does following:
Start your app
When your app crashed, clean up after it.
But job objects is definitely better option, it specifically made for this
let your host program submit its program ID as parameter,
and then listen if the program exits.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
static class Program
{
[STAThread]
static void Main(string[] args)
{
if (args.Length != 0)
new System.Threading.Thread( new System.Threading.ParameterizedThreadStart(handelexit)).Start(args[0]);
// your code here
}
static void handelexit(object data)
{
int id = System.Convert.ToInt32(data.ToString());
System.Diagnostics.Process p = System.Diagnostics.Process.GetProcessById(id);
while (!p.HasExited)
System.Threading.Thread.Sleep(100);
System.Environment.Exit(0);
}
}
}

Windows Shell Integration with multiple files

I'm making a program that is using Windows Shell Integration, and the registry changes I do are these:
For example, for .txt, I see that the value for HKEY_CLASSES_ROOT\.txt > (Default) is txtfile. I add to HKEY_CLASSES_ROOT\txtfile\shell the key myprogram > (Default) with the value Open with MYPROGRAM. to myprogram I add command > (Default) with the value *path-to-my-program* %1. Now when I right click a .txt file there is an option to open it with my program.
But when I do that with multiple .txt files Windows opens my program many times with each time another file as argument. But I want to open my program one time with all the files as many arguments. Is there an option to do that with changing stuff in registry?
If not, I also could not find a way to make a program that can be opened multiple times and combine all of them to one, so I can also do it that way if someone can help me with it. I'm making this program with C#, by the way.
You have to make your application "Single Instance".
Something like this should do the trick:
(untested code, just for reference)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;
namespace YourApp
{
class Program
{
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool SetForegroundWindow(IntPtr hWnd);
[STAThread]
static void Main()
{
bool createdNew = true;
using (Mutex mutex = new Mutex(true, "MyApplicationName", out createdNew))
{
if (createdNew)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Form1 frm = new Form1();
frm.SetNewData("send command line here");
Application.Run(frm);
}
else
{
Process current = Process.GetCurrentProcess();
foreach (Process process in Process.GetProcessesByName(current.ProcessName))
{
if (process.Id != current.Id)
{
SetForegroundWindow(process.MainWindowHandle);
// send message to that form or use .Net remoting
break;
}
}
}
}
}
}
}
For a better example see this CodeProject solution.
The standard way to handle this is to use a mutex to ensure that only a single instance of your program runs. Then when the shell attempts to start up a new instance to open each file, the new instance simply passes the message on to the already running instance and lets it open the file.
One possible option is to check if another instance of your program is already running. If so, you pass the file path to that instance to open. For program inter-communication you can use whatever you like, e.g.: .NET remoting, named pipes, DDE, custom window messages, etc..
That's the default. you have told the shell that when clicking 'open with MYPROGRAM' invoke application %1 for each file that is selected.
The simplest way to fix this is to make your application single instance, and to send messages to the instance that is already running when another file is selected. This way one instance of your application is launched to open one file and it receives a request to open each of the other files. This is how it is generally accomplished using C++
if you look at the Developer Documentation there is also the recommendation to use DDE. I don't know how accessible DDE is from within C#, and it's use is deprecated.

Checking if a console application is still running using the Process class

I'm making an application that will monitor the state of another process and restart it when it stops responding, exits, or throws an error.
However, I'm having trouble to make it reliably check if the process (Being a C++ Console window) has stopped responding.
My code looks like this:
public void monitorserver()
{
while (true)
{
server.StartInfo = new ProcessStartInfo(textbox_srcdsexe.Text, startstring);
server.Start();
log("server started");
log("Monitor started.");
while (server.Responding)
{
if (server.HasExited)
{
log("server exitted, Restarting.");
break;
}
log("server is running: " + server.Responding.ToString());
Thread.Sleep(1000);
}
log("Server stopped responding, terminating..");
try
{ server.Kill(); }
catch (Exception) { }
}
}
The application I'm monitoring is Valve's Source Dedicated Server, running Garry's Mod, and I'm over stressing the physics engine to simulate it stopping responding.
However, this never triggers the process class recognizing it as 'stopped responding'.
I know there are ways to directly query the source server using their own protocol, but i'd like to keep it simple and universal (So that i can maybe use it for different applications in the future).
Any help appreciated
The Responding property indicates whether the process is running a Windows message loop which isn't hung.
As the documentation states,
If the process does not have a MainWindowHandle, this property returns true.
It is not possible to check whether an arbitrary process is doing an arbitrary thing, as you're trying to.

Best way of determining a remote computer has booted and running

I am writing a test application which is controlling another computer. The test computer is started by sending a command string via the RS-232 port (from a control computer running Windows XP SP2 using a C# application), at which time the test computer will power-on and boot into Windows XP. I would like to know what would be the best method to determine when that computer has completed it boot process and running normally.
I was thinking of the following:
1) I was either thinking of pinging that computer, or
2) Have a shared drive and if able to access that shared drive, or
3) Writing a small service which I can communicate with
Is there different/better approach?
Mark
It all depends on what you consider "completed its boot process and is running normally". For instance, if all you care is the moment the network card is initialized, pinging might be good (as long as the ECHO port isn't closed).
A share is not a good idea as they generally only become available when a user is logged in, which may or may not be the case depending on your situation. But even if, what if you change the configuration or decide it is a security breach to open up a share?
If you want to play it certain or if you just need to wait until all services have started, you should consider your third option. It's easiest to do. Let it listen on port 80 and run from IIS. When queried, it can answer with some details of the machine. This will also give you the most flexibility. Using IIS helps you for not having to write your own service and makes it trivial to install and configure.
If IIS is not an option, you can of course consider writing your own service. Not that hard to do, but it'll require you to write the code to listen to certain ports yourself.
I had the exact problem you did, I found writing a custom service was the most useful. (I actually needed to know when a headless machine had the Remote Desktop service ready to accept connections, the program I wrote actually beeps the PC speaker a little tune when it is ready to be logged in.
EDIT: I dug up the source in case you where interested.
using System.ComponentModel;
using System.Configuration.Install;
using System.Runtime.InteropServices;
using System.ServiceProcess;
using System.Threading;
namespace Beeper
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
static void Main()
{
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new Beeper()
};
ServiceBase.Run(ServicesToRun);
}
}
public partial class Beeper : ServiceBase
{
public Beeper()
{
}
protected override void OnStart(string[] args)
{
if (MainThread != null)
MainThread.Abort();
MainThread = new Thread(new ThreadStart(MainLoop));
MainThread.Start();
}
protected override void OnStop()
{
if (MainThread != null)
MainThread.Abort();
}
protected void MainLoop()
{
try
{
//main code here
}
catch (ThreadAbortException)
{
//Do cleanup code here.
}
}
System.Threading.Thread MainThread;
}
[RunInstaller(true)]
public class BeeperInstaller : Installer
{
private ServiceProcessInstaller processInstaller;
private ServiceInstaller serviceInstaller;
public BeeperInstaller()
{
processInstaller = new ServiceProcessInstaller();
serviceInstaller = new ServiceInstaller();
processInstaller.Account = ServiceAccount.LocalSystem;
serviceInstaller.StartType = ServiceStartMode.Automatic;
serviceInstaller.ServiceName = "MyProgram";
serviceInstaller.ServicesDependedOn = new string[] { "TermService" }; //Optional, this line makes sure the terminal services is up and running before it starts.
Installers.Add(serviceInstaller);
Installers.Add(processInstaller);
}
}
}

Categories

Resources