Click here to Skip to main content
15,898,222 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I have a C# program (which runs either as a service or a windows app) that starts either .exe's or .bat files on a Windows machine - it uses the PROCESS class to do this. I also capture standard output from it - all of this works to my satisfaction.

When I run the bat file (it transfers a file from a share to the local d-drive), as a logged on user by simply double-clicking on it via Windows Explorer, it works fine. However, if I start this same bat file from my program, the bat file does not do what it is supposed to do. The bat file does run but is not successful in transferring the file.

I have looked at all possible attributes for StartInfo with no success. I have had success by changing the bat file to include a "NET USE " command to map the drive - but that requires changing the bat files which I may not always have the luxury to do. I want the bat file to run as is.

The bat file contents are:

cd C:\
copy s:\eftsource\cards041210 d:\eftrans\outgoing

The lines of code from my C# program are:
C#
// Current Process
currentProcess = new Process();
currentProcess.StartInfo.FileName = strJobFilename;
currentProcess.StartInfo.Arguments = strJobArguments;
currentProcess.StartInfo.WorkingDirectory =
Path.GetDirectoryName(strJobFilename);
strExtension = Path.GetExtension(strJobFilename);
currentProcess.StartInfo.

currentProcess.StartInfo.UseShellExecute = false;
// Redirect Standard Output
currentProcess.StartInfo.RedirectStandardOutput = true;
currentProcess.OutputDataReceived +=
              new DataReceivedEventHandler(StandardOutputHandler);
// Redirect Standard Error
currentProcess.StartInfo.RedirectStandardError = true;
currentProcess.ErrorDataReceived +=
              new DataReceivedEventHandler(StandardErrorHandler);
// Other StartInfo properties
currentProcess.StartInfo.CreateNoWindow = true;

try
{
    dtBeforeStartTime = DateTime.Now;
    bProcessStarted = currentProcess.Start();
}

Regards
Chai.
Posted
Updated 14-Apr-10 8:12am
v2

Have you tried passing any variables into the bat script as parameters?

Then you would not have to changed the script, just the StartInfo.

Also, if you can configure the security, could you use UNC paths instead of mapping a drive?

Nick
 
Share this answer
 
You can put the following in your code;

if(Directory.Exists("s:/") == false)
{
  Process.Start("net", "use s: \\UNCPATH PASSWORD /user:DOMAIN\USERNAME")
}
 
Share this answer
 
The code that I have pasted is part of a bigger program which is meant
to start ANY .exe's or .bat files. I don't have the luxury of knowing what the bat file is going to do. It must be a general solution.

Rod, doing a Directory.Exists("s:/" == false) is not a viable option.

Nicholas, can you expand on the UNC paths solution that you have mentioned ? I assume you mean "//servername/pathname" followed by the User/password combination. I guess that the program can have a config file to specify the user/password, but then what if it uses shares to different servers which may have different logins ? Also, where would I specify all this in StartInfo ? Would it be the "Domain" attribute along with the "Username & Password" attributes ?

Basically, what I want to do is supply enough privileges to the PROCESS object being started, so that it works exactly the same way as if the user were starting it when logged in.

Thanks & regards

Chai.
 
Share this answer
 
Chai Rao wrote:
Nicholas, can you expand on the UNC paths solution that you have mentioned ? I assume you mean "//servername/pathname" followed by the User/password combination. I guess that the program can have a config file to specify the user/password, but then what if it uses shares to different servers which may have different logins ? Also, where would I specify all this in StartInfo ? Would it be the "Domain" attribute along with the "Username & Password" attributes ?


Yes, it sounds like you want to run your script with the privileges of a particular user. You can do this using the Domain, UserName and Password properties of StartInfo. I haven't tested, but this probably also works from a service running under a system account. Then you can rely on normal file sharing permissions.

You can then use a UNC path like //server/share/dir/file.dat instead of mapping a drive, which could cause problems. For instance, what happens if a user runs your windows app from his desktop session that already declares a mapping for the drive letter you choose?

Just some ideas - you'll have to do some testing!

The major problem with all this, as you say, is storing the account passwords securely.

Nick
 
Share this answer
 
If as you specified you can't or don't always have the ability to change the batch files you actually have a couple of problems.

1. Permissions
2. Mapped Drives

Permissions can be fixed by specifying the account details in the StartInfo properties OR change the account the program runs under as a service.

Mapped Drives, if there is no user logged in then no mapped drives will exist regardless of the user account specified in the StartInfo properties or used to run the service. The only way to get the mapped drives back is to use to following before you run the process for the batch or executable file;
C#
if (Directory.Exists(driveletter) == false)
{
   System.Diagnostics.Process.Start("net", string.Format("use {0} {1} /user:{2}\\{3}", driveletter, uncpath, domain, username));
}


I have had to use this same method previously with a windows service to get access to Timberline data stores that could only be accessed from mapped drives and while the service was running under an account with permissions to access the network resources without the mapped drives it couldn't do anything.

If you have multiple mapped drives then a config file would be a good idea so that you can recreate those drives you need.
 
Share this answer
 
Rod, thanks for your suggestion - it worked. I intend to add a config file which contains all the driveletters & their mappings. Temporarily, I added 2 shares during intialization of my service using the Process.Start as suggested by you. It allowed my .bat files to run perfectly and access these shares by drive-letter.

However something interesting came up. For some reason "xcopy" in the .bat file does NOT copy the file over, but a simple "copy" does (when run from my program). When I run the .bat file from Windows Explorer, the xcopy does work. What gives ?

Regards
Chai.
 
Share this answer
 
In response to your question about xcopy

Xcopy doesn't behave at all well when there is no standard input stream, which is the case when UseShellExecute is false. No error message is sent to either output stream and it just quits quietly with an exit code of zero.

Setting RedirectStandardInput to true will make it work as long as no prompts are issued. I found that these do not show up in either redirected output stream making any sensible response a bit difficult.

Alan.
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900