C#: Restrict how a console app can be called - c#

We have a product that is a C# console app. Is it possible to restrict it to run from the command line only? In other words, users wouldn't be able to call it from a script or another app.
If it is, some example code would be much appreciated. Thanks.

You can check the process that created your application using the code given here: http://msdn.microsoft.com/en-us/netframework/aa569609.aspx#Question3 . To be started at the DOS command line the parent process should be cmd.exe. Note however as pointed out by Colin this can be bypassed easily using a batch script. You can disable that as well by making sure that the command prompt arguments to cmd.exe are null. For this you will need to use WMI :
http://skysanders.net/subtext/archive/2010/04/11/using-wmi-to-fetch-the-command-line-that-started-all.aspx
You should also check the cmd.exe image is from system32 folder.

I don't think it is possible to tell the difference.
Certainly the parent process is not a useful indicator. This is what you get in the parent process:
1. type app name into Command Prompt: cmd.exe
2. call app from batch script: cmd.exe
3. Double click on app or shortcut: explorer.exe
4. type app name into Run dialog box: explorer.exe
If you intend for 1. to be a valid way to start your program, then I don't think you can stop 2. which means your app can be called from any script or any program (since it's simple for another program to create a 1 line batch script and execute it)
(BTW, does anyone know a way to get a table on StackOverflow?)

#swisston if you start your console application from your another own application, than i want to recommend you "named kernel objects". For example mutex. You can create named mutex in your parent app. Then in main thread of your child console app try to open this mutex. If mutex not opened (not found): console app has no permissions to continue and must be closed;) wait, i'll make some code for you;)
Edit:
So it is very easy tactics. In parent app create your named mutex:
Mutex mutex = new Mutex(true, "MyPermissions");
Then in your child console application check if your mutex exists:
static bool CheckPermissions()
{
try
{
Mutex mutex = Mutex.OpenExisting("MyPermissions");
}
catch (Exception ex)
{
return false;
}
return true;
}
If your console application was run without your parent application CheckPermissions method will return false and console must be closed;)

I don't agree with what you're trying to do, but here is an idea that could work: require some sort of user input at the beginning of the program, maybe some sort of CAPTCHA (difficult to do in command line, but theoretically possible. Think ASCII art).

Related

Is there a way to kill a process automatically by filtering its name?

I have a process in my Task Manager, which is end-able, but keeps starting up again.
No Anti Virus has found this ad-ware virus yet, and I'm starting to think the only way to stop it from opening is to filter out its name in a program.
This is a very brief example of what I want
If process.XXX Alive = True;
{
Get process.XXX.PID;
PID.End();
}
Please ask me for any additional information.
Edit: Changed 'id' to 'pid'
// Sub adware with the name of the process
// Do not include .exe in the process name
Process p[] = Process.GetProcessesByName("adware");
foreach(Process pr in p) pr.Kill();
Internally Task Manager uses the Windows Management API. From the command line you can kill processes by name, using the built-in wmic windows management console program.
For example, this will kill all instances of notepad:
wmic process where "name like '%notepad%'" call terminate
It can do other things too:
wmic process where "name like '%notepad%'" get executablepath
Then you can find that file and delete it.
Note: To kill processes not owned by you, you must use an elevated command prompt.
Note 2: You don't say what the process is, so there is a danger that I am helping you destroy your system without realising it. Before doing this, find out what the executable path and command line are, and investigate whether they are actually problem software.
wmic process where "name like '%program%'" get executablepath,commandline

Conditions for running the program

I wrote a main program in C#, and I worte also a small tool program also in C#.
I want that the tool program will be able to execute under some conditions:
When called from my main program.
When called from open some suffix of file (e.g. "*.abc")
But if the user open my program directory he can run the tool program, and I do not want him to be able to do it. I want him to be able to run the program under the conditions above. And if he ran the program manually, the program automatically shut.
Is there any way to do that?
To check if your main program called it, you could pass the main program's ProcessID as a commandline argument, then in your small program, check if that ProcessID exists and if its process name is the name of your main program. This isn't spoof-proof, but might be a bit trickier to fake than just passing a static number/string.
In addition, you could encrypt the number and pass that, then decrypt it and check the above. It's pretty much impossible to prevent a determined hacker from running your program on its own, but you can raise the bar of how tricky it is to do it. You'd also want to obfuscate your code, otherwise a quick Reflector call will show exactly what characters are being passed.
Alternatively, if possible, you could just make the small program a DLL and call it from your main program like that. This would need a bit of refactoring, but would force your program to be open. As for opening a *.abc file, your program can check the command line arguments to see if a filename was passed through. This can then be processed automatically by your app and the DLL calls can be made.
There is nothing exposed to the process/executing environment that tells it how it was invoked, so there is no foolproof way to do this.
You can have your main program pass in a flag on the command line - this and the suffix are things that you can check for and if either one does not exist you terminate immediately.
However, if the user ever guesses the flag, they can still call the application directly.
Other mechanisms could involve writing a value to a file from your main program just before invoking the second program and checking that file from your second program (and deleting it after execution), as a messaging mechanism. There are other messaging mechanisms that would do similar things (private MSMQ queues for instance).
You can use a named mutex with some hard-to-guess name to make sure that the "small tool" program was called by the main program. So, you create a Mutex in your parent program:
bool requestInitialOwnership = true;
bool mutexWasCreated;
Mutex m = new Mutex(requestInitialOwnership,
"MyMutex",
out mutexWasCreated);
Then in your child program you write the exact same code to check if the parent program executed it. If mutexWasCreated==true, then it was not called by the parent program. Otherwise, it was.
Checking the arguments passed to the program will help to determine whether the filename's extension is .abs or not.

How to track open instances of an application in C#

I want to insure mutual exclusion in my project for installing updates.
The project is multi-instance means one can open a instances without closing the other open instances. There is a function called installUpdates() which installs the available updates. Since several instances are there so only one of them need to install the updates. I want to insure that only one instance will install the updates.
I am taking a variable globally called noOfInstances(semaphore) initialized to 0. Once a new instance is opened the variable will be incremented by 1. If there are 4 open instances then the value of noOfInstances will be 4. Once a instance is closed the value will be decreased by 1. For installing the updates I am writing:-
if(noOfInstances == 1)
{
InstallUpdates();
}
Now my problem is that how to track programmatically that there is an instance opened of my project? There may be some unique Id for each instance which I am not able to identify. I am using windows environment to develop my c# application.
A global Mutex is probably a better mechanism to gate access to exactly-once-only functions. In this instance I'd try acquire a mutex with a short timeout. If you fail to acquire it - someone else has it. If you succeed, test if updates are necessary, and if so install updates.
An optimization might be to move the test outside of the mutex - but you'll still need to retest if updates are required inside the scope of the mutex.
What is a good pattern for using a Global Mutex in C#?
You can use Process.GetProcesses to get processes by name
var processes = Process.GetProcesses Method (ProcessName)
if (processes!= null)
{
int runningInstances = processes.Length;
}
While I've implemented #stephbu's mutex-pattern in the past, requirements recently have been that the running instance should be brought to the front if the program was started twice.
To do so, I try to connect to a named pipe. If I can not connect, this is the first instance and I create the named pipe and then do things normally. If I can connect, this is a second instance and I send a command via the pipe and quit.
Receiving a command on the named pipe I can do anything I want, like bring the main window to the top.
This solution, however, only makes sense if you actually want to do something with the pipe as described above. If you only want to prevent the application from being run twice, #stephbu's mutex answer is the way to go.
You can get the Running Processes like this :
using System.Diagnostics;
int GetInstanceCount(ExeName)
{
Process[] processlist = Process.GetProcessesByName(ExeName);
int NoOfInstances = processlist.Count;
return NoOfInstances;
}
Now Implement Like This:
string ExeName = "notepad.exe"//Say Notepad
if(GetInstanceCount(ExeName) == 1)
{
InstallUpdates();
}

Restart other application. C#, .net

I want to restart some process. Lets call it someApp.exe.
How can I restart that process? It's not my application. It's some external program.
What you want to do is:
Kill the process
Start it again
There are some ways of obtaining a Process instance in C#. Let's suppose you know the name of the process:
var process = Process.GetProcessesByName("notepad++")[0];
Then you can do:
process.Kill();
But to start it again, you need to know the path of the process, so before killing it, save the path of the executable:
var path = process.MainModule.FileName;
And then you can do:
Process.Start(path);
You should check if GetProcessesByName returns elements before taking the first element, but I just wanted to focus on the important thing here.
You can use the Process.Start.
http://msdn.microsoft.com/en-us/library/53ezey2s.aspx#Y1400

Kill process started with System.Diagnostic.Process.Start("FileName")

I am trying to create an app that will perform actions on specific times (much like the Windows Task Scheduler). I am currently using Process.Start() to launch the file (or exe) required by the task.
I am initiating a process by calling a file (an .mp3) and the process starts WMP (since it is the default application). So far so good. Now I want to kill that process. I know that it is normal behavior for the Process.Start(string, string) to return nothing (null in C#) in this case.
So I am asking how can I close WMP when I called it through Process.Start(string, string)??
Edit:
Please note that I am not opening WMP directly with Process.Start() and this is the line with which I run the process:
VB: Me._procs.Add(Process.Start(Me._procInfo))
C#: this._procs.Add(Process.Start(this._procInfo))
_procInfo is a ProcessStartInfo instance. _procInfo.FileName is "C:\route\myFile.mp3". That is why WMP opens. In any case, all of the Start() methods, except for the instance-one which returns a boolean, return nothing (null in C#), because WMP is not the process that was directly created (please note that WMP is run and the song does play).
Process.Start(string,string) returns you a Process resource that you can use to further control the new process.
Process newProcess = Process.Start("param1", "param2");
if (newProcess != null && !newProcess.HasExited)
newProcess.Kill();
The same structure works if you use Process.Start(string), or any other static Process.Start overload.
Process.Start() is a member function and associates a new or reused Process with the Process component identified by this. Behaviour of this method depends on the properties of the Process identified by this.
Don't do it this way.
It's not clear whether the intent of your program is 'Always launch with Windows Media Player' or 'Launch with the registered MP3 player', which might be, say, iTunes.
If you need WMP, use Process.Start with the full path to windows media player.
If you need the registed MP3 player, you can find out the correct exe using the code shown here. Again, start the process with this exe path, passing the MP3 as a parameter.
Two ways:
1-
Process customProc = Process.Start("ExecutablePath", "Argument(s)");
customProc.Kill()
2-
Dim pProcess() As Process = System.Diagnostics.Process.GetProcessesByName("ProcessName")
For Each p As Process In pProcess
p.Kill()
Next
If you are letting the registered windows program to open the file, rather than picking the program you want. Then I advise you do not kill the process.
The reason for this is what say your program does use the default application, but that application is already in use, and contains unsaved data. A user would not be happy for your program to overtake there application with the new file and then kill off the process that was already in use by the user for another purpose. Sure, it might not be in use but you must consider the worst case.
As such, I recommend what has been suggested. use Process.Start() with the full path to the program to be used and the file to be opened.
I tried to open .txt file and the process of my text editor was returned, also I tried .mp3 by WMP and it returned null. So it depends on the application. Do you need to run you mp3 only with WMP? If not, you definitely can create the application which will return the Process object.
proc = Process.Start(filename) should work, but like you say, it returns null instead of a process.
That seems to be inherent to Windows Media Player. Other applications return the process. You can get Windows Media Player's process by specifying the application in the start method.
proc = Process.Start("C:\Program Files\Windows Media Player\wmplayer.exe", filename)
Then you can kill it normally.
proc.Kill()
You will probably need to get the location of the application assiciated with .mp3 files from the registry.

Categories

Resources