1

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

user1271551
  • 97
  • 2
  • 9
  • 2
    Well anything that avoids hard-coding an admin password in a web application is better. Consider issuing a BACKUP T-SQL command to SQL1 and specifying a shared path on SQL2/3 as the backup destination. – Alex K. Nov 24 '17 at 15:17

1 Answers1

1

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#)

Harry
  • 1,233
  • 10
  • 24
  • Good point! Unfortunately script still doesn't work. Obviously there is something else I do wrong (btw, -accepteula is correct syntax, not /accepteula – user1271551 Nov 26 '17 at 12:03
  • Thanks for the "btw", i corrected it in my answer, also i added additional obvious problems.. – Harry Nov 26 '17 at 20:05
  • 1
    Regarding first 2 points - strange, but it works without cmd /c during debug. Ok, I modified .bat starting as suggested, but this didn't help also. Added STDOUT. Removed domain, user and password from the process StartInfo and it still works under debug - copy - done, STDOUT returns robocopy report. Then deployed to the real server and got Acces denied as STDOUT. Set domain, user, password back. And again nothing has happened - the file was not copied, STDOUT is empty, no time spent between process start and WaitForExit(). – user1271551 Nov 27 '17 at 08:45
  • I am having the same issue as user1271551. Using robocopy inside batch file called from ASP.NET with Process.StartInfo using domain user credentials fails. No msg in STDOUT or STDERROR. Finally noticed error in Windoews server System Event Log "Application popup: Robocopy.exe - Application Error : The application was unable to start correctly (0xc0000142). Click OK to close the application. " – seagulledge Feb 19 '21 at 08:16