I have to run a tool from our internal website. There are few inputs that user will provide from UI and then I want to run the tool with user credential. My code works fine when I run it from my local machine, but when I deploy it to production server and try to execute it from there it does not start anything.
Here is my code, any advice will be greatly appreciated.
System.Diagnostics.ProcessStartInfo PSI = new System.Diagnostics.ProcessStartInfo(#"D:\run.bat");
PSI.UserName = "username";
PSI.Domain = "domain";
System.Security.SecureString securePwd = new System.Security.SecureString();
string password = "password";
foreach (char c in password)
{
// Append the character to the password.
securePwd.AppendChar(c);
}
PSI.Password = securePwd;
PSI.UseShellExecute = false;
process.StartInfo = PSI;
PSI.Arguments = SiteId.Text + " " + WebServiceUrl.Text + " " +LogFile.Text;
process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
process.Start();
First:
Check the identity of your application pool (advanced settings).
Switch the identity to "system" and see if the batch file runs from the web app.
If it does:
Change the identity back to network service,
Make sure your batch file has execute permissions applied for user Network Service (or whichever identity you chose)
If it doesn't:
Try opening the file with your code and appending some harmless text to the end.
If that works, you can at least rule out permissions and web-app view-ability concerns.
I want to close this thread as my problem of running an application from production server solved. But I'm facing issue to run that application using specific user name & password. It always run with whatever identity is set in apppool. So for now if I only use this line it works on app pool default identity
Process.Start("notepad");
But if I use this line of code it don't even start a notepad in that server
string password = "XXXXX";
System.Security.SecureString securePwd = new System.Security.SecureString();
foreach (char c in password)
{
// Append the character to the password.
securePwd.AppendChar(c);
}
Process.Start("notepad", "username", securePwd, "domain");
I'm going to ask a separate question on this. Thanks for all who replied.
Related
I need to write a file while impersonated as another user John (Member of administrator).
What happens:
File is written and created, then all Access Control is removed and added (Full Control).
No matter where in this process i try to Encrypt file access is denied
using FileOptions
Using File.Encrypt.
my worked around to at least encrypt was with opening another impersonation later on.
But No matter what i do, i can't Decrypt or even read the encrypted Text file.
If file is encrypted reading or decrypting fails, even though i can read or write just fine while impersonated.
In some scenarios Everything works fine, But after a system restart or logout, again fails with access denied.
For impersonation i used this answers Impersonation
using (impersonate = new ImpersonateUser(ImpersonationType.WinIdentity, Domain, User, SecurePassword))
{
System.Diagnostics.Debug.WriteLine($"Before Impersonation: {Environment.UserName}");
done = impersonate.RunImpersonated(() =>
{
System.Diagnostics.Debug.WriteLine($"After Impersonation: {Environment.UserName}");
//if (Util.IsWindowsEncrypted(ConfigFullPath)) File.Decrypt(ConfigFullPath);
var json = File.ReadAllText(ConfigFullPath);
var configFile_data = SerializationUtil.Deserialize<Config>(json);
//if (!Util.IsWindowsEncrypted(ConfigFullPath)) File.Encrypt(ConfigFullPath);
});
}
A working repository to reproduce is available here Repository containing full sample,
See CreateConfig or ReadConfig method in Config.cs
(if you were able to create and read a encrypted file, check if after
restart it is the same)
A Workaround i just found was to create a Process before doing any impersonation.
using (Process cmd = new Process())
{
ProcessStartInfo startInfo = new ProcessStartInfo
{
FileName = "cmd.exe",
Arguments = $"/c",
UseShellExecute = false,
UserName = user,
Password = pass,
LoadUserProfile = true
};
cmd.StartInfo = startInfo;
cmd.Start();
}
I would like to check if State is DISABLED or ENABLED.
I opened the file D:\TOOLS\Security.bat and run it.
In addition i must insert password in CMD to continue program
and I want to C# write that password. Is that possible?
How can I insert password into open process in CMD?
The file must be opened with D:\TOOLS\Security.bat
Process process = new Process();
process.StartInfo.FileName = "D:\\TOOLS\\Security.bat";
process.StartInfo.CreateNoWindow = false;
process.StartInfo.RedirectStandardInput = true;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.UseShellExecute = false;
process.Start();
process.StandardInput.WriteLine("password");
process.StandardInput.Flush();
process.StandardInput.Close();
process.WaitForExit();
Console.WriteLine(process.StandardOutput.ReadToEnd());
Here is Security.bat file:
runas /user:Administrator c:\utility\info.bat
cls
Here is info.bat file:
ewfmgr c:
pause
When I write password in CMD I got that data.
From that data I would like to get State value.
But I don not know how to save this console data to string.
How can I get all data from last console call?
Here is my code for get state data.
string check= #"State(.)*DISABLED";
if (Regex.IsMatch(output, check)) {
// SECURE IS OFF
}
Thanks for help.
No, it's not possible to insert the password into the command prompt. it's specifically designed to prevent that.
What you CAN do is save the password in the credential cache on that particular machine. You do this with the runas command by using the /savecred switch. After you enter your password, it will no longer ask for it when you runas this app as that user.
I have been having trouble passing input programmatically to the system net user program using C#. I am trying to activate and set a password for a certain user account. By my investigations, it seems like the process finishes before anything can be passed. I do not know why the background net user program does not wait for input before exiting.
Here is the command I am running programmatically to accomplish this:
net user username /active:yes & net user username *
The output of the second command is as follows:
Type a password for the user:
Retype the password to confirm:
The command completed successfully
If you were to run the above command manually, it would ask you for the password and hide what you're typing from the screen. However, the program doesn't seem to stop when ran programmatically.
To call the program, I have a function that starts the program and returns the process to another function, which sends input to the process. Here is the first function:
static Process RunCommandGetProcess(string command)
{
Process process = new Process();
ProcessStartInfo psInfo = new ProcessStartInfo();
psInfo.FileName = "CMD.exe";
psInfo.Arguments = "/C " + command + "& PAUSE";
// Allow for Input redirection
psInfo.UseShellExecute = false;
psInfo.RedirectStandardInput = true;
// Window style
psInfo.WindowStyle = ProcessWindowStyle.Normal;
// Start the mothertrucker!
process.StartInfo = psInfo;
process.Start();
return process;
}
And the Calling function:
static int ActivateUserWithPassword(string password)
{
// Start net user with that other function
Process process = RunCommandGetProcess("net user username /active:yes & net user username *");
StreamWriter streamWriter = process.StandardInput;
streamWriter.WriteLine(password); // First Prompt
streamWriter.WriteLine(password); // Second Prompt
process.WaitForExit();
return process.ExitCode;
}
However, When I run the debugger, the commands complete successfully before the two streamWriter.WriteLine(password); lines are even met! I have tried Googling, but came to no avail.
You people are my only hope.
Okay! I have been highly motivated to solve your issue as soon as i saw it!. after 2 hours of non-stop debugging, i have a solution for you!.
Issue No .1 : Your application does not have Administrator privileges, that is why the command exits right after you start. Start the .exe with Admin Privileges.
Issue No. 2 : Since the password is masked in the input, Even if i did a streamWriter.WriteLine(password) once,The output is "Command Executed Successfully". There is no way of knowing if the password was actually passed or it took empty string as the password.
Solution
You can use the net user command with a parameter for password like this
net user user_name password. No need to prompt the user for password i.e Don't use '*' after username ,since you are passing it through the program.
So this is how it works
Process proc = new Process();
ProcessStartInfo start = new ProcessStartInfo();
start.FileName = "cmd";
start.Arguments = "/k";
start.RedirectStandardInput = true;
start.WorkingDirectory = Environment.CurrentDirectory;
start.UseShellExecute = false;
proc.StartInfo = start;
proc.Start();
proc.StandardInput.WriteLine("net user \"username\" password");
Very Very Important!!
Start the exe as an administrator OR you will have to do this
start.UseShellExecute = true;
start.Verb = "runas";
But then you wont be able to redirect the Output/Input streams!.
I am running one batch file every few seconds to do timesync with server using following code:
Process process = new Process();
process.StartInfo.WorkingDirectory = Environment.GetFolderPath(Environment.SpecialFolder.System);
process.StartInfo.FileName = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System), "cmd.exe");
process.StartInfo.Arguments = #"/C C:\TimeSync.bat";
process.StartInfo.CreateNoWindow = true;
process.StartInfo.UseShellExecute = false;
process.StartInfo.WindowStyle = ProcessWindowStyle.Minimized;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.UserName = "username";
SecureString pwd = new SecureString();
Char[] pwdCharacters = "password".ToCharArray();
foreach (char t in pwdCharacters)
{
pwd.AppendChar(t);
}
process.StartInfo.Password = pwd;
process.Start();
string output = process.StandardOutput.ReadToEnd();
The problem is it flashes the command windows on the screen which I don't want. How can I prevent that?
One behavior I have seen is if I run the same code with UseShellExecute = true and don't provide username and password then the command window doesn't flash.
So basically I want to run .bat file using c# code as different user silently.
Because you are passing a user name and password, the CreateNoWindow parameters are not respected. This is a feature (i.e. bug) in windows. Here's the five year old connect details:
http://connect.microsoft.com/VisualStudio/feedback/details/98476/cmd-windows-shows-using-process-with-createnowindow-when-using-username-password-option
Process.Start() calls advapi32.dll's
CreateProcessWithLogonW in the event
that a user supplies a username and
password, and CreateProcessWithLogonW
always opens a new window.
Unfortunately, there is no workaround
for this behavior
An excellent overview of the create no window option is given here:
http://blogs.msdn.com/b/jmstall/archive/2006/09/28/createnowindow.aspx
which also points out errors in the msdn documentation on this topic.
And there's a very good overview in this stackoverflow answer:
How to hide cmd window while running a batch file?
In the end, I think you want to create a separate little app that you call out to only once, and it runs the whole time, as the escalated user. It can then perform the time sync as often as you want, in the same manner as you've described above, but without having to specify username and password. Thus there will only be one 'flash' of a console window for the entire duration of the application.
Hope this helps
lb
Change your line:
process.StartInfo.WindowStyle = ProcessWindowStyle.Minimized;
to
process.StartInfo.WindowStyle =
ProcessWindowStyle.Hidden;
That will hide the window and never show it.
Hope that helps!
Phil
Did you try to just specify:
process.StartInfo.CreateNoWindow=true;
?
You could use impersonation. I've written an impersonation class that implements the IDisposable interface and is rather straightforward to use, I hope.
I have to start a command line program with System.Diagnostics.Process.Start() and run it as Administrator.
This action will also be run by a Scheduled Task every day.
I've just try to use :
Process p = new Process();
p.StartInfo.Verb = "runas";
this works fine if I'm running my program as Administrator, but when the Scheduled Task runs it, it doesn't take the 'runas' in consideration I think.
A better secure option to run a process with login and password is use the SecureString class to encrypt the password. Here a sample of code:
string pass = "yourpass";
string name ="login";
SecureString str;
ProcessStartInfo startInfo = new ProcessStartInfo();
char[] chArray = pass.ToCharArray();
fixed (char* chRef = chArray)
{
str = new SecureString(chRef, chArray.Length);
}
startInfo.Password = str;
startInfo.UserName = name;
Process.Start(startInfo);
You must allow unsafe code in your project properties.
Hope this help.
If you are using scheduled tasks, you can set the user and password for the task to run under.
Use the administrator credentials on the task and you will be fine.
With Process.Start, you need to supply the UserName and Password for the ProcessStartInfo:
Process p = new Process("pathto.exe");
p.StartInfo.UserName = "Administrator";
p.StartInfo.Password = "password";
p.Start();
Be aware that storing a password in clear text in a program is never secure as long as someone can peruse the application and see what is in it. Using SecureString to convert a stored password into a SecureString password does not make it more secure, because the clear text password would still be present.
The best way to use SecureString is to pass a single character for conversion at a time in someway that does not require having the complete unencrypted password anywhere in memory or on the hard drive. After that character is converted, the program should forget it, and then go on to the next.
This could be done I think only by passing characters through for translation as they are being typed into the console by the user.
I found it, I need to set the Scheduled Task to run the application with highest privileges in General settings.