I'm executing command lines containing passwords in C#, if I display the optional "Command Line" column in the windows task manager ("Processes" tab) it contains all the arguments including the passwords,
could you think of a way to hide this, like only showing the ".exe" file or something ?
Thanks
If you have control over the program you are calling, you could modify it to read the data from standard input instead of passing the passwords on the command line. This would prevent it from being part of the command line itself, which would "hide" it.
If you cannot change the program, there will be no way to hide the command line used to start the process, as there are Windows API calls that can query this for open processes (which is what is being used by Task Manager).
Well, fist off: In my opinion you should really not do something like passing credentials in a human readable format! Passing a path to a file containing encrypted credentials is not hard to do and much safer.
I don't think that hiding the commandline is even possible. Correct me if I'm wrong.
See: What is the easiest way to encrypt a password when I save it to the registry?
Related
I am trying to save the username and password of user at c# console application. Hence there will be just one username and password that must be saved (It is like pin code). I don't want to use a Database for this. Using .txt will be irrational because anyone can see and find txt file and enter program.
I tried to use Properties.Resources but because of Resources are read-only, there is no way of changing password at runtime if user wants to change its password.
Properties.Resources.Admin_Mail = Reading;
It gives error because of the reason I mentioned above.
What should I use, I cannot find any suitable way for this problem on the internet.
I am not sure where you are at in your development journey.
You'll need system.io to read and write to the text file. I would give in a different extension then .txt.
https://learn.microsoft.com/en-us/dotnet/api/system.io?view=net-6.0
Consider using a SecureString type in C#
https://learn.microsoft.com/en-us/dotnet/api/system.security.securestring?view=net-6.0
Encrypt the data stored in the file.
https://learn.microsoft.com/en-us/dotnet/standard/security/encrypting-data
Decrypt the users entry to ensure it matches the file.
https://learn.microsoft.com/en-us/dotnet/standard/security/decrypting-data
There is a StackOverFlow link talking at the actually input.
Password masking console application
Sorry for just linking to references instead of a straightforward code answer, but I not sure of your intent and level of security you wish to provide.
I have a requirement to execute several commands with elevated rights, something like:
call program that modifies a .config file of a service (needs admin rights)
net stop myservice (needs admin rights)
net start myservice (needs admin rights)
All of this dynamic, e. g. the first line could contain proxy settings, including user name and password, or any other modification to the settings file. (Settings file is in program folder, program to modify the settings file is externally provided. The actual info would be user entered through a GUI.)
I thought to create a very flexible solution, using a cmd.exe process with redirected stdin and stdout. But.. it looks like "runas" (needs ShellExecute) and redirected in-/output are exclusive.
(Also, I noticed that redirection and cmd.exe are quite hard to handle.. I had to write my own functions e. g. as a replacement for ReadLine, since the ReadLine expects a NewLine at the end and waits e. g. if there is a command prompt (meaning you have text in the line like c:\bla> but no NewLine. Still, not knowing what one gets as a result makes writing something generic difficult.)
There are 3 alternatives I can think of:
get the UAC prompt for every single command (I would not like that)
start a process that is elevated, this can then call whatever it wants -> needs an additional project (.exe) which I would like to avoid, also makes deployment more difficult (additional file)
create a batch file on the fly, run it elevated. This I also want to avoid, since there could be password information in plain text in that file (e. g. user/password for proxy). I would at least have to make sure to always overwrite its contents and then delete it.
How to handle this?
I think you've already diagnosed the issue, and enumerated your available options. To my mind the best option is to use runas to create a new elevated process, and get that process to do the work.
The other process need not be a different executable it could be your existing executable started with particular command line arguments. Once you have another process running elevated, you can certainly use cmd with redirected stdin/stdout to do the work. However, why use net stop/start rather than the service API? And can you do the .config file modification without starting a separate process?
I want to create a command executor like Start > Run. The application has a TextBox and when a user enters a command eg : notepad "C:\test.txt" it should open notepad with this file or %PROGRAMFILES% it should open 'Programs Files' directory.
For %PROGRAMFILES% and other Windows variables I can use Environment.ExpandEnvironmentVariable and get their path and pass to Process.Start
and for notepad, I can split the with space and first part goes in FileName and rest of string goes in Arguments of ProcessStartInfo.
But what I want to know is, how does Start > Run work ? is there something like I can execute the whole command without splitting command-line or expanding the variables ? Maybe with pinvoke ?
To the very best of my knowledge, the run dialog is implemented with a call to ShellExecuteEx. You can achieve the same with Process.Start and UseShellExecute. You do need to expand the environment variables, and split the command into filename and arguments. You already describe how to do that in your question, and, again to the best of my knowledge, there is no programmatic interface to the functionality of the Run dialog.
However, what you can do programmatically is show the Run dialog. Create an instance of the Shell object requesting the IShellDispatch interface, and then call the FileRun method.
I am looking to convert a C# (Windows platform application) into a commandline version.
The scenario is: I have implemented a C# (Windows application) in VS 2010. The output of this application is to generate a txt (log) file (in simple explanation).
Now the case is, there is one other application which need to use my this C# application, by calling my C# application from the command line at the run time.
My question is, how is it possible to convert an already existing C# application into commandline application, so that this C# application can be called from the calling (other) program? There is one input parameter which need to be passed on the commandline to my C# application. And then this C# application will process the data according to input parameter and then generate the output log(txt) file.
Added explanation
I am really impressed by the solutions here. Just a bit more expertise is required from readers. I want one application only to work as both commandline application as well Windows-application (forget to mention it before, sorry!), depending on the number of input parameter pass to the application. From this point of view, I have two options to implement it,
1) Make separate functions for both applications (commandline and windows-forms). Call them according to the input parameter pass. In each function implement the complete functionality of each application without disturbing (or going into the code of other application). Also I will be able to re-use 2 main functions, already built in windows-form application into my commandline application after some editing.
Disadvantage: This will make the code size nearly 50% more than case 2.
2) The second idea is same as describe by one of the expert here, to use the same application/functions for commandline as that of already built windows-form application. The only way to distinguish is to look at the input parameter pass, and decide accordingly whether to show the GUI interface or just use the commandline input (and do processing).
Disadvantage: This case will make the code bit messy and difficult to maintain/implement due to extra adding of check for number of input parameter decisions.
Which strategy should I follow for implementation?
Sure - just:
Create a new VS2010 command-line project
You'll now have a "main ()" (or, in MS-Land, "_tmain()") function instead of a root class.
Cut and paste the relevant code into "main()" (or into a function called by main (), or into a class created from main() - your choice).
Do a search-and-destroy mission to find anyplace where you're doing GUI input, and substitute command line parameters instead.
Parse your command line.
Voila! Done!
You don't have to convert it. Your application can stay as a Windows application. You simply need to handle command line arguments.
To get the command line arguments from ANYWHERE in the application, just use Environment.GetCommandLineArgs();
You want to get value from command line is not a good reason to convert winform app to console app. You may use,
string[] args = Environment.GetCommandLineArgs();
However you can change application type by opening project properties (right click on project name) and change the Output type.
Just don't show the GUI if you get paramater passed in, as when called from the other program.
I've been working on a small and simple program that I drop files onto and, based on certian rules, they are moved to diffrent places.
The program works fine unless I drop more than a few files, then it kicks back an error (that appears to be more Windows than anything) that the start up command "c:\myapp.exe \file \file \file" is too long.
I realize I could set up a background proccess, but I really would prefer that this program not run in the backround (where it would be idle most of the time).
Is there a way around this limitation?
From this blog:
The maximum command line length for the CreateProcess function is 32767 characters. This limitation comes from the UNICODE_STRING structure.
If you are using the CMD.EXE command processor, then you are also subject to the 8192 character command line length limit imposed by CMD.EXE.
If you are using the ShellExecute/Ex function, then you become subject to the INTERNET_MAX_URL_LENGTH (around 2048) command line length limit imposed by the ShellExecute/Ex functions.
The maximum size of your environment is 32767 characters. The size of the environment includes all the variable names plus all the values.
So you're gonna have to settle with some of the mentioned workarounds (also, there's another workaround on the msdn blog I linked).
If you want to drop files with respect of Windows Explorer, then you can implement your own Drop Handlers as a Shell Extension Handlers see:
How to Create Drop Handlers (Windows)
Creating Shell Extension Handlers
On The Complete Idiot's Guide to Writing Shell Extensions you will find a good introduction how to write such extensions.
The part VI gives an example of Drop Handler (for a little other use case, but it dose not matter).
With respect of Drop Shell Extension Handler your program will receive full information about all dropped files and you need not start a child program with all the files as command like parameters.
I think the drag and drop handler is possibly one way to go, but it seems quite heavy.
An alternative solution is to use a Explorer Context Menu handler. With this in place, you would select all the files, but rather than dragging them, right click, and choose your new menu item "Send to ".
When the menu item is selected, it passes the list of commands to your program. There are a couple of ways of doing this:
launch your program, and feed the list of files to standard input
write the list of files to a temporary file, and launch your program with just one command argument - the temporary file listing the files to process. List files are usually prefixed with '#' on the command line to distinguish them from ordinary file names.
When the files are drag&dropped onto your application write the list of files names out to a text file, then give the location of this file to your program. The target program can then read in this file and process it line-by-line. This way you only ever pass a single file name.
I'd modify the application to pick up the files from a specific location (e.g. specific folder on a filesystem) rather than specifying each file on the command line.
UPDATE:
If the requirement is to be able to drag an item onto an .exe via Windows Explorer to start the application as Mark mentioned then you could put all of your files into one folder and drop the entire folder on the .exe.
I think the easiest solution is to modify your application to accept a directory as the parameter as opposed to a list of files. This would allow you to copy the multiple files into a single directory. You can then drag and drop the folder onto your executable. It would then run a command like "c:\myapp.exe \folder-with-files-in-it" which should not run into the command line parameter limitation that you are experiencing now.
I experienced a similar issue when I was trying to get security details on a long path.
My solution was to map drives whenever the path length got too long. Check out my solution on
How do I get the security details for a long path?
Unix commands frequently have one or two parameters that can be of unbounded length. Several of these commands have added parameters which can source those arguments from a file, or from standard input. So you have one command which gins up the list of arguments, and either pipes them to a temporary file, or pipes them to stdout.
See also, xargs, which can take a list of arguments and either invoke your command with all of the parameters, or in batches.
How to get around the command line length limit? Write your whole command to a batch file, e.g. to "C:\Users\Johnny\Documents\mybatch.bat". Write it as you would in the cmd (no need to escape anything). Then, in your code simply call that file:
strCmdText = "C:\\Users\\Johnny\\Documents\\mybatch.bat";
ProcessStartInfo ProcessInfo = new ProcessStartInfo("cmd.exe", "/K " + strCmdText);
ProcessInfo.CreateNoWindow = true;
ProcessInfo.UseShellExecute = true;
Process.Start(ProcessInfo);