Execute remote batch file from within a C# forms application - c#

I am working on a VPN dialer that will execute a login script when the connection is successfull using the following method.
Process p = new Process();
try
{
p.StartInfo.UseShellExecute = true;
p.StartInfo.FileName = #"\\serverName\NETLOGON\Script Test.cmd";
p.Start();
p.WaitForExit();
}
}
catch (Exception ex)
{
}
The batch file execute properly according to the logging methods in the batch file, but the drives are not acctualy mapped for the user to use. Other batch files tested (local & remote) have the same result.
I am assuming this has something to do with the application domain or UAC. The finished application will run on Viata/7 and is being tested on Windows 7.
Any help here would be greatly appreciated.
Regards
Bert

Mapped Drives are stored in a users profile. Which typically gets loaded when the person logs in. The most common way to get access to profile associated resources is to impersonate the user.
There is a relationally poor (PInvoke) example of how to do this here:
http://support.microsoft.com/kb/306158#4
But generally using mapped drives from a script is asking for trouble. IMHO :)
Hope that helps,
Jan

You can check if there is any exception happened. I see catch(exception ex) swallows you exception.

Related

.Net unauthorized access exception after deployment

I deployed my internal web application to server A and got an error when creating a file to a network drive on server B. If I run locally, the file got created on server B successfully.
System.UnauthorizedAccessException: Access to the path '\\b\folder\test.pdf' is denied.
The identity of the application pool is networkservice. And I gave networkservice full control on the destination folder on server B. I even gave Everyone full control, but it still got the error.
Server A runs .NET 7.5. Code to create file:
var byteArray = generateArray();
var destination = "\\\\b\\folder\\test.pdf";
try {
var destinationFile = new FileInfo(destination);
if (destinationFile.Exists) {
destinationFile.Delete();
}
System.IO.File.WriteAllBytes(destination, byteArray);
} catch (UnauthorizedAccessException) {
//
}
I've seen someone got the exact same problem here. But it didn't solve mine.
Solution:
I changed the identity to administrator account instead of using network service for the application pool. It works but I don't fully understand why it works. Because the network service on A is different than the one on B?
Even though you provided access to everyone, certain applications have to receive specific permission. This was apart of the UAC System introduced in Window's Vista. This move was to increase security, so an application couldn't run under any user and basically have full access.
What you should do, is on the directory provide the following access:
IIS AppPool\NameOfAppPool
That will provide specific access to your hosted web application to that directory, for IIS will be able to correctly manipulate the directory. Some code you could implement to help validate before you write or read, would be:
public static bool ValidateIOPermission(string path)
{
try
{
if(Directory.Exist(path))
return true;
else { Directory.CreateDirectory(path); }
}
catch(Exception ex) { return false; }
}
The above code is a small sample, basically try to perform the action and catch the exception, that way you know if you have access or not.

Running command from ASP.NET App Pool Identity

I am running an executable process from my ASP.NET application when a user clicks a button. This process creates several files and serves them up to the end-user. I can't really see what the process is or isn't doing, but it didn't work until I specified the admin user as the application pool identity on the server. I am using IIS7.
using (var proc = new Process())
{
proc.StartInfo.FileName = Server.MapPath("~/Testing/Demo/MyExe.exe");
proc.StartInfo.Arguments = String.Format("\"{0}\"", commandFilePath);
proc.StartInfo.UseShellExecute = true;
proc.Start();
proc.WaitForExit();
}
I'm assuming that this is generally a bad thing to do. Can you give me insight into what needs to be done in order to enable this for the normal ApplicationPoolIdentity account?
Thanks!
First of all, why you need the Shell to execute it ? Isn't a console application - do you open any window ?
Second you need to redirect the input and the output.
And final, what you need to do, is to place on the directory that your script runs, permission for the user under witch your pool is run. And remove the Admin from your pool.
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.CreateNoWindow = false;
proc.StartInfo.RedirectStandardError = true;
proc.StartInfo.RedirectStandardOutput = true;
proc.StartInfo.RedirectStandardInput = true;
proc.Start();
proc.StandardInput.Flush();
proc.StandardInput.Close();
proc.WaitForExit();
proc.Close();
So for example, if you add your pool to run under the UserA, then go to your directory that your program runs and add permission for the UserA to been able to execute programs on that directory. If your program also use other directories to read and write, also add permission to the UserA for that ones.
I can't really see what the process is or isn't doing
You can take a look if you use on the server the Process Explorer and see if its runs, if its close, if its stop but stay there.
It is likely a file/execution permissions issue.
Try granting execute permissions to the ApplicationPoolIdentity to ~/Testing/Dema/MyExe.exe and read permissions to commandFilePath. You mentioned that your process creates files. You will need to grant either modify or full control permissions to the ApplicationPoolIdentity on the folder where the files will be created. Here is a matrixed list of permissions.
See assign permissions to ApplicationPoolIdentity account for information on granting permissions.
The security event log should capture permission denied errors. Check there to see if you have access permission issues. The System and application logs might also contain information on the problem.
Process Explorer can also show File Access requests. Here is a technet article on troubleshooting with Process Explorer.
Whenever you run any process from an ASP.NET page, it runs under the security context of the worker process, the privilege of your app pool account. It is not like you normally running the MyExe.exe, in that case it will run using logged in account. It is because of this, your code worked when you gave Admin account to app pool.
There are many ways to solve this issue.
One of the easiest would be to change your app pool identity to Network Service and add the Network Service to permissions of the folders in which the MyExe.exe will be accessing files form.
Hope it helps.
Thank you all for your help. All I needed to do was set the StartInfo.WorkingDirectory to somewhere that I was able to write.
using (var proc = new Process())
{
proc.StartInfo.FileName = Server.MapPath("~/Testing/Demo/MyEXE.exe");
proc.StartInfo.Arguments = String.Format("\"{0}\"", commandFile);
proc.StartInfo.WorkingDirectory = savePath;
proc.Start();
proc.WaitForExit();
}
This causes the temp files to be written to a non-system folder and thus does not need any elevated permissions for the application pool.

Running bat file on IIS server

I'm trying to run a .bat file on a windows server 2008 R2 64bit with IIS version 6.1 SP1.
On my local machine everything goes well but on server nothing happens, except for a process that gets created (cms.exe *32).
From my search the main problem is permissions. I read in several places that IIS for default blocks access to batch files for security reasons. I do understand the problem but in my case there would be no security issue so i would like to still run my file.
The solutions i found passed by implementing impersonation which means:
Change web.config
-> identity impersonate="true"
Change IIS Site Authentication
-> ASP.NET Impersonation Enabled
Give permissions to the file and folders
Even tried a different version of step 1
-> identity impersonate="true" userName=**********
Give permissions to the IIS User:
set allow service to interact with desktop on the IIS Admin Service
To call the batch i use the following code in C#:
private void StartPervasive(string npu)
{
try
{
ProcessStartInfo startInfo = new ProcessStartInfo(ConfigurationManager.AppSettings.Get("PervasivePath"));
//startInfo.UseShellExecute = true;
//startInfo.WorkingDirectory = ConfigurationManager.AppSettings.Get("PervasiveWorkingPath");
//startInfo.WindowStyle = ProcessWindowStyle.Normal;
//startInfo.RedirectStandardInput = true;
//startInfo.RedirectStandardError = true;
//startInfo.RedirectStandardOutput = true;
//startInfo.FileName = ConfigurationManager.AppSettings.Get("PervasivePath");
startInfo.Arguments = npu;
Process myProcess = Process.Start(startInfo);
//StreamReader sr = File.OpenText(ConfigurationManager.AppSettings.Get("PervasivePath"));
//StreamWriter sw = myProcess.StandardInput;
//while (sr.Peek() != -1)
//{
// string readed = sr.ReadLine();
// readed = readed.Replace("%1", npu);
// sw.WriteLine(readed + Environment.NewLine);
//}
//myProcess.WaitForExit();
//myProcess.Close();
}
catch (Exception ex)
{
throw ex;
}
}
It should also be of note that i tried to execute other files including .exe files but with no results.
Would appreciate any advice, help and or corrections to the steps described.
This may not be what your looking for, but may help. I would suggest you create a Scheduled Task on the Server to run the BAT file, you can set the User Permissions and then schedule when you wish to run it.
Hope this helps.
Below is a link to another Stackoverflow article that appears to have a very detailed response to the same problem.
IIS7 does not start my Exe file...

Why Process.Start doesn't work from asp.net web service?

Why this code runs perfectly on my development computer (win7 32bit) and on target server(2008r2 64bit) as console app. But when I try to run it as a web service on the target server it does nothing. No error, nothing.
If I remove
exitMsg = proc.StandardOutput.ReadToEnd();
then it fail with error:
System.InvalidOperationException:
Process must exit before requested
information can be determined.
[WebMethod]
public string GetRunningProcesses()
{
ProcessStartInfo pInfo = new ProcessStartInfo();
pInfo.FileName = #"E:\bin\PsList.exe";
pInfo.WindowStyle = ProcessWindowStyle.Hidden;
pInfo.CreateNoWindow = true;
pInfo.UseShellExecute = false;
pInfo.RedirectStandardOutput = true;
string exitMsg = "";
int exitCode = 1;
using (Process proc = Process.Start(pInfo))
{
exitMsg = proc.StandardOutput.ReadToEnd();
proc.WaitForExit(1000);
exitCode = proc.ExitCode;
}
return exitMsg;
}
I think there must be something about user under which code runs. As web service this code runs under asp.net user and this might couses the problems.
Please advice me how to fix this. Thank you very much.
RESOLVED
The problem was with EULA dialog, which poped up but it was invisble due to ProcessStartInfo settings.
When I run PsList.exe via CMD under account which is also used for Application pool for this web service, I get prompted for an EULA agreement and after that everthing works fine.
The strange thing is that I have "pInfo.Arguments = "/accepteula";" in my real code. This should prevent my probem, but it didn't and I don't know why.
If any of you knows why, please tell me.
Thank you very much for all the help. You are trully good peoples here.
I think your only problem is with:
proc.WaitForExit(1000);
Which instructs the program to wait for a second for the process to finish. On your machine, the process finishes fine. On another machine, though, it may take longer. Try changing to:
proc.WaitForExit();
Which will wait indefinitely for the program to exit.
You may also want to redirect the output of the Process to see if the programming is hanging or waiting for something else from you (or, in this case, your code).
In addition, the process may be hitting an error and writing a message to StandardError rather than StandardOutput. Try setting pInfo.RedirectStandardError = true; and reading that as well to see if there's anything you're missing.
The problem was with EULA dialog, which poped up but it was invisble due to ProcessStartInfo settings.
When I run PsList.exe via CMD under account which is also used for Application pool for this web service, I get prompted for an EULA agreement and after that everthing works fine.
The strange thing is that I have "pInfo.Arguments = "/accepteula";" in my real code. This should prevent my probem, but it didn't and I don't know why.
If any of you knows why, please tell me.
Thank you very much for all the help. You are trully good peoples here.
Try wrapping your business logic in a try / catch block that catches any exception and either writes it to the output or to a log file.

How to control network client pc

In my local network ,I have more than 10 pc.I need to take care all of the pc.I want to know all pc’s hardware informations.I also want to control those pc,Suppose ,at this moment I want to restart one of my client pc.Is it possible in C#.if have any question plz ask.Thanks in advance
I use bellow syntax to execute command.
try
{
// create the ProcessStartInfo using "cmd" as the program to be run,
// and "/c " as the parameters.
// Incidentally, /c tells cmd that we want it to execute the command that follows,
// and then exit.
System.Diagnostics.ProcessStartInfo procStartInfo =
new System.Diagnostics.ProcessStartInfo("cmd", "/c " + "shutdown /r /m \\172.16.1.3 /t 1 /");
// The following commands are needed to redirect the standard output.
// This means that it will be redirected to the Process.StandardOutput StreamReader.
procStartInfo.RedirectStandardOutput = true;
procStartInfo.UseShellExecute = false;
// Do not create the black window.
procStartInfo.CreateNoWindow = true;
// Now we create a process, assign its ProcessStartInfo and start it
System.Diagnostics.Process proc = new System.Diagnostics.Process();
proc.StartInfo = procStartInfo;
proc.Start();
// Get the output into a string
string result = proc.StandardOutput.ReadToEnd();
// Display the command output.
Console.WriteLine(result);
}
catch (Exception objException)
{
// Log the exception
}
Using the above code I get the message "The network path was not found."
Pls check the url.
http://support.microsoft.com/kb/317371
If you want to make a program which u can able to get the remote system information. You have to use Microsoft's Remoting.Here we can able to create an object in the remote system and we can able to control it.
It is possible to get System's information by executing the System.Diagnostics.ProcessStartInfo.
It is possible to get system information using "systeminfo" .It is possible to take the output using C#
Pls chk the this.
I hope this will be useful for you.
I don't think this is a C# question, cause this can be done much more elegant with things like Group Policy Editor, System Management Server, System Center Operations Manager, etc.
To do some simple tasks on a remote machine you can take a look into the PsTools.
With those requirements my first stop would be WMI. There's for example the Win32_OperatingSystem class with its Reboot and Shutdown methods and the Win32_Processor with all kinds of information about the CPU.
This MSDN section shows you how to use it from .Net: Getting Started Accessing WMI Data
This MSDN section has quite a lot of short VBScript samples for doing various things using WMI, and even if the code is different, at least you can see which WMI classes/methods/properties you should be looking at: WMI Tasks for Scripts and Applications
Please note RB's comment though, you'll need to have the correct permissions for it to work.
Edit: Forgot that since you'll want to connect to other computers, this sample will be useful: How To: Connect to a Remote Computer

Categories

Resources