Resolved Redirect pgdump.exe output into RichTextBox

giodepa

Member
Joined
Nov 23, 2021
Messages
17
Programming Experience
1-3
Hi all,
I created a form in order to backup my postgres DB.
I'm using pg_dump.exe and executing it as process and setting CreateNoWindow = false and UseShellExecute = true in processStartInfo I can see opening DOS shell, I can see all single messages of pg_dump and Backup is successfully completed.
Now I'm trying to redirect all messages from dos shell into richTextBox without success.
With following code, backup is completed but I cannot see any message into richTextBox

redirect:
private void start_btn_Click(object sender, EventArgs e)

        {
            
            Task.Factory.StartNew(() =>
            {
                
                Process proc = new Process();
                ProcessStartInfo info = new ProcessStartInfo();
                //info.FileName = Application.StartupPath + @"\pg_dump.exe";
                info.FileName = "cmd.exe";
                info.CreateNoWindow = true;
                info.UseShellExecute = false;
                info.RedirectStandardInput = true;
                info.RedirectStandardOutput = true;
                info.RedirectStandardError = true;
                //info.Arguments = @"cmd.exe /k tracert www.google.it";
                //info.Arguments = @" --verbose --host=172.0.0.1 --port=5432 --username=radio --format=c --compress=6 --schema=dbo -d RNO --file C:\backupDB\RNO202111231008 ";
                info.Arguments = @"cmd.exe /c C:\Backup_PostgreSQL\pg_dump.exe --verbose --host=172.0.0.1 --port=5432 --username=radio --format=c --compress=6 --schema=dbo -d RNO --file C:\backupDB\dump-RNO-20211123";
                proc.StartInfo = info;
                proc.OutputDataReceived += new DataReceivedEventHandler(OutputHandler);
                proc.ErrorDataReceived +=  new DataReceivedEventHandler(ErrorHandler);
                proc.SynchronizingObject = richTextBox1;
                proc.Start();
                proc.BeginOutputReadLine();
                proc.WaitForExit();
                proc.Close();
            }
                 );
            
        }

  
        private void OutputHandler(Object source, DataReceivedEventArgs outLine)
        {
            // Collect the sort command output.
            if (!String.IsNullOrEmpty(outLine.Data))
            {
                richTextBox1.AppendText(outLine.Data + "\r\n");
            }
        }

        private void ErrorHandler(Object source, DataReceivedEventArgs outLine)
        {
            // Collect the sort command output.
            if (!String.IsNullOrEmpty(outLine.Data))
            {
                richTextBox1.AppendText(outLine.Data + "\r\n");
            }
        }

As further check, if I consider as arguments tracert command, I can see in the richTextBox all messages in realt time
I specified also verbose option as reported in postGres documentation: "specifies verbose mode: This will cause pg_dump to output detailed object comments and start/stop times to the dump file, and progress messages to standard error."

Any suggestion?
Thank in advanced
gio
 
You have "cmd.exe" also in arguments, remove that.
 
You have "cmd.exe" also in arguments, remove that.

Hi John,
without cmd.exe inside arguments pg_dump isn't executed and in richTextBox following messages are shown:
Microsoft Windows [Versione 10.0.19043.1348]
(c) Microsoft Corporation

As well as using :
C#:
info.FileName = @"C:\Backup_PostgreSQL\pg_dump.exe";
and as arguments:
C#:
 //info.Arguments = @" --verbose --host=127.0.0.1 --port=5432 --username=radio --format=c --compress=6 --schema=newradio -d RNO --file C:\backupDB\RNO20211123";

Code enters in OutputHandler only when backup is finished and outline.Data is null
 
Your arguments line looks to be commented out.
 
The correct approach is to have the Filename point to pg_dump.exe (with the full path), and for the Arguments be set to the normal arguments you would use if you writing this at the command line. UseShellExecute should be set to false, and RedirectStandardOutput and RedirectStandardError set to true. If needed also set the WorkingDirectory.

As to why "pg_dump.exe" is behaving that way, maybe it has some code that detects whether the standard output and error is being redirected or not. I recall using some only console programs that had some fancy progress updates (without having to fallback to using ANSI ESC codes), but did not output any of the progress update information if the output was piped to another program or redirected to a file.

I would suggest trying to run the following at the command line,
C#:
C:\Backup_PostgreSQL\pg_dump.exe --verbose --host=127.0.0.1 --port=5432 --username=radio --format=c --compress=6 --schema=newradio -d RNO --file C:\backupDB\RNO20211123 > output.txt 2>errors.txt

Check the contents of output.txt and errors.txt. Do they contain the expected progress information you were hoping to display into your rich text box?
 
.... Do they contain the expected progress information you were hoping to display into your rich text box?
I executed line command.
Only errors.txt is filled and it contains all informations that I need:
Rich (BB code):
...
pg_dump: last built-in OID is 16383
pg_dump: reading extensions
pg_dump: identifying extension members
pg_dump: reading schemas
pg_dump: reading user-defined tables
pg_dump: reading user-defined functions
pg_dump: reading user-defined types
pg_dump: reading procedural languages
pg_dump: reading user-defined aggregate functions
pg_dump: reading user-defined operators
pg_dump: reading user-defined access methods
pg_dump: reading user-defined operator classes
pg_dump: reading user-defined operator families
pg_dump: reading user-defined text search parsers
pg_dump: reading user-defined text search templates
pg_dump: reading user-defined text search dictionaries
pg_dump: reading user-defined text search configurations
pg_dump: reading user-defined foreign-data wrappers
pg_dump: reading user-defined foreign servers
pg_dump: reading default privileges
pg_dump: reading user-defined collations
pg_dump: reading user-defined conversions
...

How do you suggest to proceed?

Thx
gio
 
Last edited:
Also call BeginErrorReadLine()
 
Solution
I looked into this and had some trouble with passwords too, during research I found 3 ways that worked and 1 that didn't.
I was not able to make proc.StandardInput.WriteLine("password") work.
These alternatives did work:
  1. Environment variable for ProcessStartInfo:
    C#:
    info.EnvironmentVariables["PGPASSWORD"] = "password";
  2. --dbname switch with connection uri. With this switch the (--host --port --username and -d) switches can also be omitted.
    C#:
    --dbname=postgresql://username:password@host:5432/dvdrental
  3. Using a password file in local account folder: The Password File
 
...
  1. Using a password file in local account folder: The Password File

Hi John,
I used 3rd method creating pgpass.conf file in case I wanna connect to several servers without writing passwd each time.
This is code(maybe it can be useful):
pgpass:
String user = Environment.UserName;
            String user1 = System.Security.Principal.WindowsIdentity.GetCurrent().User.ToString();

            if (! System.IO.Directory.Exists(@"C:\Users\"+user+@"\AppData\Roaming\postgresql"))
            { System.IO.Directory.CreateDirectory(@"C:\Users\" + user + @"\AppData\Roaming\postgresql"); }

            //check if file is present
            if (!File.Exists(@"C:\Users\"+user+@"\AppData\Roaming\postgresql\pgpass.conf"))
            {
                using (StreamWriter sw = File.CreateText(@"C:\Users\" + user + @"\AppData\Roaming\postgresql\pgpass.conf"))
                {
                        sw.WriteLine(ipserver_textbox.Text + ":" + port_textBox.Text + ":*:" + user_textBox.Text + ":" + Passwd_textBox.Text);
                }
            }
            else
            { //MessageBox.Show("File pgpass.conf already configured.");
            }

gio
 
C#:
var dir = Path.Combine(@"C:\Users\", user, @"AppData\Roaming\postgresql");
var confFile = Path.Combine(dir, "pgpass.conf");
 
C#:
var confPath = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"postgresql\pgpass.conf");
 
Back
Top Bottom