user1271551
user1271551

Reputation: 97

File copy started from aspnet webforms and implemented using batch, pstools and robocopy doesn't work

I have 4 independent servers (not in domain): IIS, SQL1, SQL2, SQL3

I want to copy a database backup from SQL1 to SQL2 or SQL3 (depending on parameters) by button click on webpage hosted on IIS

I wrote a button click method for that, which is calling batch file located in inetpub folder on IIS

Batch is using pstools to run robocopy on SQL1 which should copy required file to destination server (SQL2 or SQL3)

This solution works if I execute batch directly on IIS (cmd as Administrator) or when I debug it on my local machine, but it doesn't if it is called from the running site. It even doesn't spend any time between the following lines:

        batchProcess.Start();
        batchProcess.WaitForExit();

Here is my copy method:

private bool ProcessCopy(string file, string destinationIp)
    {
        SecureString password = ConvertToSecureString("myPassword");

        try
        {
            string batchPath = Server.MapPath(".") + "\\CopyFile.bat";
            string cmd = @"c:\Windows\System32\cmd.exe";

            ProcessStartInfo processInfo = new ProcessStartInfo
            {
                FileName = cmd,
                UseShellExecute = false
            };

            Process batchProcess = new Process {StartInfo = processInfo};

            batchProcess.StartInfo.Arguments = $"/C {batchPath} {file} {destinationIp}";
            batchProcess.StartInfo.Domain = "";
            batchProcess.StartInfo.UserName = "Administrator";
            batchProcess.StartInfo.Password = password;
            batchProcess.StartInfo.RedirectStandardOutput = true;
            batchProcess.StartInfo.RedirectStandardError = true;
            batchProcess.StartInfo.CreateNoWindow = true;

            batchProcess.Start();
            batchProcess.WaitForExit();
            string response = batchProcess.StandardOutput.ReadToEnd();
            response += batchProcess.StandardError.ReadToEnd();
            statusStringAppend($"response: {response}");

            return true;
        }
        catch (Exception ex)
        {
            statusStringAppend($"Failed: {ex.Message}. {ex.StackTrace}");
        }
        return false;
    }

Batch body is:

@echo off
c:\qa\tools\pstools\psexec64.exe -accepteula -u Administrator -p myPassword \\SourceIP robocopy \\SourceIP\qa\db_backup\ \\%2\qa\db_backup\ %1 /is

My questions are:
1. Why the file was not copied?
2. Is there any better way to get it copied?

CODE UPDATED ACCORDING TO SUGGESTIONS BELOW

Upvotes: 1

Views: 269

Answers (1)

Harry
Harry

Reputation: 1263

My guess is that you never executed pstools as the user that your IIS service is running as before, so the EULA dialog is blocking your execution.

If you remember, you always got a window and needed to press the accept button when running any sysinternals tool like pstools the first time.

I guess this should work for you:

c:\qa\tools\pstools\psexec64.exe -accepteula -u Administrator -p myPassword \\SourceIP robocopy \\SourceIP\qa\db_backup\ \\%2\qa\db_backup\ %1 /is

[EDIT] You would most likely have hit this problem later on, anyway it did not work for you, so i have to list what else could be wrong with your code:

  • starting a .bat file needs cmd.exe as mother process, you cannot just start a .bat file as process directly. Instead you can for example use another method than ProcessStartInfo that spawns the system default script interpreter automatically: Executing Batch File in C#

  • the process for executing batch files is "cmd.exe", first parameter "/C", second parameter the batch file you are executing

  • when executing typical commandline tools, you might consider reading the SDTOUT (standard output) of the process you are executing, like this: Capturing console output from a .NET application (C#)

Upvotes: 1

Related Questions