O R G A N I C / F E R T I L I Z E R: removing lines from repadmin output with powershell

Dec 3, 2008

removing lines from repadmin output with powershell

i challenged a coworker to put his powershell class to good use and come up with a script that would actually have an impact, albeit little, to his day-to-day administrative work. he came up with a little script that would dump repadmin output to a text file and mail him an attachment. here’s the script:

%{repadmin /replsum * /bysrc /bydest} > logfile.txt

$filename = “logfile.txt”
$smtpServer = “mysmtp.mydomain.com”

$msg = new-object Net.Mail.MailMessage
$attachment = new-object Net.Mail.Attachment($filename)
$smtp = new-object Net.Mail.SmtpClient($smtpServer)

$msg.From = “myemail@mydomain.com”
$msg.To.Add(”myemail@mydomain.com”)
$msg.Subject = “Repadmin Report ” + [System.DateTime]::Now
$msg.Body = “The daily Repadmin log file is attached”
$msg.Attachments.Add($attachment)

$smtp.Send($msg)

this is okay, but opening that attachment every time would be irritating… so i thought it might be easier just to get the output into a variable and write it to the body of the email directly. WOW. that proved to be more difficult than i thought! the idea is simple, but the formatting was killing me.

so to begin, i removed the opening line and used the following to create an array to hold the information coming in from repadmin. also, i prefer sorting by delta… so that’s why i modified that.

$myRepInfo = @(repadmin /replsum * /bysrc /bydest /sort:delta)

didn’t need the $filename variable nor the $attachment variable anymore so i dropped both of those. everything else is pretty much the same. once i reached the $msg.body statement is where i had some trouble with it. the first thing i noticed is that $myRepInfo had extra linefeeds once converted [1]. to get around that was actually pretty easy. feeding it through the where object seemed to work.

$myRepInfo | Where-Object { $_ }

now i have something a little more presentable. adding this to $msg.body couldn’t be easier, right? a simple statement like $msg.body = $myRepInfo | ? { $_ } should do fine. it doesn’t though. once i send it to $msg.body, it loses its linefeeds altogether!

Replication Summary Start Time: 2008-12-03 08:49:11 Beginning data collection for replication summary, this may ta
ke awhile:   ..................................................   ............... Source DC           largest delt
a  fails/total  %%  error  myDCServer1               59m:15s    0 / 111    0    myDCServer2                59m:15s
 0 /  38    0    myDCServer3                 59m:15s    0 /  24    0    myDCServer4                59m:15s    0 /
28    0    myDCServer5                 59m:15s    0 /  24    0    myDCServer6                59m:11s    0 /  24   

well, to get around that, we need to modify that statement once more to replace each line with the same line plus a linefeed. here’s the resulting command:

$msg.Body = $myRepInfo | Where-Object { $_ } | ForEach-Object { $_ -replace $_,"$_`n" }

that makes the output a little more favorable like this:

Replication Summary Start Time: 2008-12-03 08:49:11
Beginning data collection for replication summary, this may take awhile:
  ..................................................
  ...............
Source DC           largest delta  fails/total  %%  error
 myDCServer1                 59m:15s    0 / 111    0
 myDCServer2                 59m:15s    0 /  38    0
 myDCServer3                 59m:15s    0 /  24    0
 myDCServer4                 59m:15s    0 /  28    0
 myDCServer5                 59m:15s    0 /  24    0
 myDCServer6                 59m:11s    0 /  24    0

here’s the finished script. a little more compact… not much different. the end product, at least for me, makes it nicer. :)

$myRepInfo = @(repadmin /replsum * /bysrc /bydest /sort:delta)
$smtpServer = "mysmtp.mydomain.com"

$msg = new-object Net.Mail.MailMessage
$smtp = new-object Net.Mail.SmtpClient($smtpServer)

$msg.From = "myemail@mydomain.com"
$msg.To.Add("myemail@mydomain.com")
$msg.Subject = "Repadmin Report " + [System.DateTime]::Now
$msg.Body = $myRepInfo | Where-Object { $_ } | ForEach-Object { $_ -replace $_,"$_`n" }

$smtp.Send($msg)

[1] my understanding from some deep inner circles is that some utilities like repadmin or ipconfig use a printf function. if you want to see the kind of output it displays, you can push this through an octal dump command. this can be accessed from through a unix subsystem (services for unix, etc) or by using the cygwin tools – which is what i did.

this is what a typical output would look like. it’s all the “\r” formatting that junks it up.

repadmin /replsum * /bysrc /bydest /sort:delta | od -c

0000000   R   e   p   l   i   c   a   t   i   o   n       S   u   m   m
0000020   a   r   y       S   t   a   r   t       T   i   m   e   :
0000040   2   0   0   8   -   1   2   -   0   3       0   9   :   3   7
0000060   :   0   9  \r  \r  \n  \r  \r  \n   B   e   g   i   n   n   i
0000100   n   g       d   a   t   a       c   o   l   l   e   c   t   i
0000120   o   n       f   o   r       r   e   p   l   i   c   a   t   i
0000140   o   n       s   u   m   m   a   r   y   ,       t   h   i   s
0000160       m   a   y       t   a   k   e       a   w   h   i   l   e
0000200   :  \r  \r  \n           .   .   .   .   .   .   .   .   .   .
0000220   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .
*
0000260   .   .   .   .   .   .   .   .  \r  \r  \n           .   .   .
0000300   .   .   .   .   .   .   .   .   .   .   .   .  \r  \r  \n  \r
0000320  \r  \n  \r  \r  \n   S   o   u   r   c   e       D   C
0000340                                       l   a   r   g   e   s   t
0000360       d   e   l   t   a           f   a   i   l   s   /   t   o
0000400   t   a   l           %   %           e   r   r   o   r  \r  \r