Pass parameters to previously started program instance - c#

I need to write program that will be given some path as a parameter, and play audiofile, located in that path. But after i call that program second time-i need first one to finish playing file and after that-play second file, that was passed as a parameter to second instance. How to pass second parameter as queue to first program instance if its possible..?

I guess you're describing the following strategy:-
instance A of your app is open and playing track X.
the user double clicks track Y in explorer
windows starts instance B of your app, passing in the filename as a parameter
instance B detects instance A
instance B sends a message to instance A to play track Y
instance B shuts down
instance A receives the message, stops playing track X and starts playing track Y
Evidently this is the way VLC media player works. If you try the above, you will see a new VLC process appear for a short time before your current instance starts playing the new track.
This kind of very simple cross process communication can be achieved using something like System.Threading.Mutex. E.g. you could use one mutex to indicate the existence of a currently running instance and another for passing the new track name to the current instance.
In fact, this article describes something quite similar.

I don't think you need second instance of program for this purpose. You can simply ask the first program to play the new audio file once it has finished playing the first. You can achieve this via several ways.
You can host a WCF Service inside your program which plays the audio file. It will be playing audio and will be listening to WCF Service in parallel. Program that sends the second parameter will pass the new path via WCF Service.
Similarly you can use sockets for communication
A third way could be to use Windows Message Queues. Audio player will be continuously pooling the queue for the new paths. The second program will send the new file path via adding a message in Windows Message Queue
You can also use files for communication. Audio player can look for changes in file and other program can write paths to that file

Related

Rest API restore last connection

I am working on a Rest API. So far I build a Webview where the user can make inputs and send them to the server. When the server receives the information it will start a program and do some calculations. The problem here is that opening the program needs a lot of time. So the user has to wait for +20 seconds.
The point is that the user will change data of the same object and send them back to the server. When the server gets these data again it has to open the program again so that the user has to wait for another 20 seconds.
The program is referenced as a library. I create an instance of it within the controller class. So each time the server gets a new request it will open an instance, pass the data to the program and return the result to the client.
My question here is: Is there a way to avoid opening an instance for each request and instead open an instance temporarily for each user?
Edit:
The program is written in VBA. It is a configurator which calculates whether an option works out or not. I will access it by creating an instance of it:
Configurator conf = new Configurator
After that you can either create a new position or recall an old one by passing an ID like this:
conf.ID = id;
This process needs a lot of time because the program is collecting a lot of data from a database.
So this is the process I want to skip and instead use the object I created before.
After that you can pass other data to the program/object like height etc.
You can use dependency injection engines like Autofac. Register your program instance onApplicationStart as a singleton instance. Then whenever you want an instance of the program.dll, autofac will give you the same instance according to your defined registration config which is singleton.

DLL doesn't store string C#

I have an application that can be launched from the explorer context menu for a Windows drive. When you click the menu item the drive letter is passed to the new instance. I want to make sure that any old instance is closed.
I also want to make sure that the last drive that was selected is persisted, so that when I start the application again from the start-menu, it will remember the drive I originally selected.
It would be best if the already running application would receive an event so that it can update without having to kill and restart.
I tried the following, but that doesn't seem to be working:
This is my Class library method(it is just a line that define a variable so just i have a DLL that there a variable in it and no more)
namespace Dispatch
{
public class cls_get_drive_letter
{
public static string drive_letter;
}
}
This is my loading form code: (Here i will fill the DLL's variable)
private void Frm_loading_Load(object sender, EventArgs e)
{
Dispatch.cls_get_drive_letter.drive_letter = "XXX";
Process currentProcess = Process.GetCurrentProcess();
if (Process.GetProcessesByName(currentProcess.ProcessName, currentProcess.MachineName).Length >1)
{
currentProcess.Kill();
}
}
So when i run this for first time the "XXX" will be stored in DLL but when the current instance of application is running and i am going to run next instance of it the application will be closed because of this code:
Process currentProcess = Process.GetCurrentProcess();
if (Process.GetProcessesByName(currentProcess.ProcessName, currentProcess.MachineName).Length >1)
{
currentProcess.Kill();
}
So when closing code occurs with this code the new "XXX" will not stored in DLL and the last string will be in dll.
All variables, in this case a static field, will only remain the same for the running instance of your application.
When the application is started again the field is empty
A static variable is not stored 'inside a dll' but is stored inside the memory of the application that loads the dll. When a second instance of the application starts, it will have its own memory space and it will have its own version of the string variable. The variable is also not kept between instances, so as soon as you start a new instance it will have its own, empty string variable.
When the application is stopped, the memory for that instance is released and the variable is 'forgotten'.
If you want to share state between applications, there are all kinds of solutions, one could be the System.Configuration.Settings API, a file somewhere, a memory mapped file shared between multiple processes, a Named Pipe, a Kernel Semaphore. Options aplenty.
Until we understand exactly what it is you're trying to accomplish with this shared state, we can't provide you with a better alternative than the explanation that what you're doing right now, will not work do to the way static variables work.
Update based on new information:
You can store your currently selected drive in a Settings file for your project. You can add such file from the project properties in Visual Studio. There's a tab called settings. Create a new setting for "Selected Drive" and make it a User setting (that way you can update it without Admin rights).
To communicate a new drive letter to your already running application, you have a number of options.
For one, you could check whether your executable is already running (like you're doing now) and in that case update the settings file and exit the new instance. Your already running instance could periodically refresh the settings to pick up new values.
When your application starts, you can open a named pipe on your machine on which you listen for drive changes. When the 2nd instance starts, it can detect that the pipe is already there, write the new drive to the pipe and close. The already running application can pick up this message and change its configuration.
You can send a WindowMessage to the other application
You can host a simple WCF service to receive the notification
You can write the new drive letter to a file stored in a known location and have the other instance use a FileSystemWatcher to detect the changes to that file.
As I said the possibilities are endless.
If I were you I'd first make sure that the value is persisted between relaunches by implementing the Settings file in your application. Then investigate the options I described above, do some experimentation and then ask new questions when you cannot figure out how to make it work.

How to resend args to an app if its already running and have it refresh with those args

I have an issue. I'd have a video player that takes in simple parameters as a c# form app. As an experiment to better understand programming, I'd like to have only one instance of the app running and have it refresh with the new args if the open command is given. I could program it so that when it gets the signal, to refreshVideo() or something like that.
Pseudo example:
//app is started from cmd line
//open app for first time
vidViewer.exe("lotr.avi", "44:44");
//keep instance open but have it refresh with new movie
vidViewer.exe("star_wars.avi", "22:32")
As it stands right now a new app with embedded video player will open, so I could have 100 open flicks if I passed it enough args. I'd just like to keep it at one.
Can provide more info if needed.
Thanks all,
Kevin
My suggestion would be to design your application such that, when launched, it would attempt to acquire a system resource that is mutually exclusive (meaning that only the first instance would succeed). Since, in your scenario, you will also require a means of interprocess communication (to transmit the name and start-time of new videos), you may use the same mechanism for achieving this.
You could, for example, use a self-hosted WCF service, bound to a fixed TCP port, that each application instance attempts to register upon being started. Due to the way ports work, only the first instance will succeed; subsequent instances would fail with a “port already in use” exception.
If an instance manages to register the WCF service, then you may assume it to be the “principal” instance and proceed to play the video on it. It should, however, listen for incoming messages from the WCF service and update the video being played accordingly (see below).
If an instance finds that the port is already in use, it should assume that another instance is already running. It would then initialize a WCF client that sends the name and start-time of the new video to be played to the WCF service. Finally, it should terminate itself without displaying any window, assuming that the principal instance will take care of playing its video.

C# program parameters from the command line?

I'm trying to start a C# program running, and then give it command from the cmd.exe after it's started running. For instance, suppose I started my .exe from the command line (C://FILEPATH/my_program.exe). I'd then like to have that program continue running, and then have me be able to pass commands to it that it is capable of handling. In my ideal world this would be something like "C://FILEPATH/my_program.exe run_my_command()" which would execute the run_my_command function, or "C://FILEPATH/my_program.exe k", which would do something in response to the char k that I'd pre-programmed in. I know that, as I've typed, would start a new copy of my_program.exe. I'd only like to have one running while I pass something like that in.
Does anyone know how to do this? Sample code would be wonderfully appreciated. Thanks!!
The simplest solution would be for your second instance of "my_program.exe" to look for an existing instance that's already running, "pass" the message over to it and then exit immediately.
The usual way this is implemented is via named pipes (System.IO.Pipes in .NET 3.5+). When your program starts up, listen on a named pipe with a given name. If there's something else already listening on that pipe, send the message to it and exit.
You are describing a typical service and command tool. The service (demon) runs in the background and executes commands. The command tool takes user commands and passes them to the service. See Windows Service Applications. Having a service instead of starting several processes takes care of some issues your approach has, like security isolation between the processes (eg. one user starts the a command, another user starts another command and gets executed in the context of the first user) and process lifetime issues (user launches a command and then closes his session).
The command tool would communicate with the process via classic IPC (local RPC, pipes, shared memory, etc).

Proxying Videos locally with a TCP Socket

I've been really interested in adding support for video podcasts to Media Browser.
I would like users to be able to navigate through the available video podcasts and stream them from the internets. That's really easy cause media player etc.. will happily play a file that lives in the cloud.
The problem is that I want cache these files locally so subsequent viewings of the same episode will not involve streaming and instead will play the local file.
So... I was thinking, why not host an HttpListener and as media player asks it for bits of the file, have the HttpListener download and store it locally. Next time a user plays the file we will already have portions of the file locally.
Does anyone know of example code that uses HttpListener for proxying?
EDIT
The idea would be only to proxy simple streamable content like MP3 or Mov.
The bounty will go to an actual implementation.
Here is the API I would like:
// will proxy a uri on the local port, if cacheFile exists it will resume the
// download from cacheFile.
// while the file is downloading it will be name cacheFile.partial, after the
// download is complete the file will be renamed to cacheFile.
// Example usage: ProxyFile("http://media.railscasts.com/videos/176_searchlogic.mov", 8000, #"c:\downloads\railscasts\176_searchlogic.mov")
//
// Directly after this call http://localhost:8000 will be the proxy stream, it will be playable locally.
void ProxyUri(Uri uri, int port, string cacheFile)
Edit 2
HttpListener is looking pretty unpromising I will probably need to do the work at a TCP socket level as HttpListeners seem to require the program runs as admin which is going to be really tricky.
I hadn't done anything with HttpListener before, so I thought this would be a nice little exercise to bring myself up to speed with it - and so it proved. I implemented it as a single ProxyListener class whose constructor takes the parameters of the ProxyUri function you specified. Once you obtain an instance, you start it listening (and potentially downloading) by calling its Start method. When you're done with it, call Cleanup.
There are one or two rough edges but basically it works as per your question. To test it, I built it up as a console application with a Program class which accepts input lines consisting of (uri, port, filename), space-separated, creates the ProxyListener instances and starts them. You can run this console application, type in a suitable line, and the downloader will start (printing out progress to console). Simultaneously you can e.g. fire up IE and fetch the file from the specified port, and you will be able to download it while the downloader is still working. The "uploader" progress will be printed to console, too.
I'm having a bit of trouble pasting it in here, maybe due to size (it's not that big, but bigger than the snippets you normally see here - the ProxyListener class is a tad under 200 lines). Does it sound interesting? If so, I'll post it to a pastebin and update this answer with a link.
Update: Posted as a gist.
Note that you will need Administrator privileges to run the program, since HttpListener requires this.
Update 2: Under certain circumstances, it is not necessary to have admin privileges to run HttpListener. See this link and this one. The idea is, if you can reserve an URL namespace during installation time, then the user does not have to have admin privileges if listening against that namespace.
Streaming was not designed to be saved, and also these protocols are very custom and very complex to implement, streaming sessions do lots of validation and synchronization which will be extremely difficult to imitate. Of course it is not an impossible task, but its fairly big task to do. Only other way is to read and save it as local media file, and use that as a reference. Because you can use windows media encoder to read stream and write stream data as local file, but it still may not allow you to do copy protected data.
Did you consider using HTTP proxy with caching features?
Like:
Apache httpd with mod_proxy and mod_cache
Squid
See also Web Cache # wikipedia
If you want your application to have such web cache component, I suggest you look for Web Cache implementation in .Net, and not code it from scratch.

Categories

Resources