Showing posts with label Batch Files. Show all posts
Showing posts with label Batch Files. Show all posts

Tuesday, August 28, 2012

PowerShell: Redirecting Console Output and Error Output to a Variable and E-mailing it

I recently had the need to script the execution of a command-line utility and thought it would be a good learning experience to try doing it with PowerShell.  The utility would sometimes output to the STDOUT, but would also send its output to STDERR if there was a problem.  This seemed to involve many different problems all at once including:

  • Running an EXE with a space in the path and multiple command-line parameters
  • Capture both STDERR and STDOUT to a variable
  • Escaping special characters/using special characters
  • Doing string concatenation
  • Doing explicit type conversion
  • Sending an email
  • Joining a string array to a single string variable
  • Doing a "FOR" loop (optional but fun).

Anyway, here's the script I came up with that runs a command-line app and takes all the output (including the error stream) and joins it into a string and then sends it in an email to me.  It's a bit ugly because I am a PowerShell novice, but it does work.  The only trouble I've noticed is that sometimes the error lines will be a bit out of sequence from the corresponding stdout lines.  If someone knows how to fix that, please let me know in the comments!!!

 

#Setup the command string - notice the `" to escape the double-quotes inside the string (deals with spaces in path)

# and the old batch file trick of doing 2>&1 to ensure STDERR is piped to STDOUT.

$command = "& `"C:\Users\myprofile\Documents\visual studio 2010\Projects\TestOutput\TestOutput\bin\Debug\testoutput.exe`" someparameter -xyz someotherparameter -abc someotherthing -rfz -a somethinghere 2>&1"
#Execute the command and put the output in an array.

$console_output_array = invoke-expression $command

#loop through the array and print out the results to the command line (optional)

for ($i=0; $i -lt $console_output_array.length; $i++)
{
    [string]$i + "=<" + $console_output_array[$i] + ">"
}

#create a single string by joining together the array

$console_output_string = [string]::join("`r`n",$console_output_array)

#send an email with the results

$emailFrom = "fromemail@example.com"
$emailTo = "toemail@example.com" 
$subject = "Email subject goes here"
$smtp = new-object Net.Mail.SmtpClient("yoursmtpserver.example.com", 25)
$smtp.Send($emailFrom, $emailTo, $subject, $console_output_string)

Thursday, May 10, 2012

One Way to Work Around the .NET Setup Project’s Picky Version Number Behavior

If you don’t change the version number of your .NET project output every time you create a setup package, you may have found that it’s difficult to have the Setup program reliably uninstall the existing version of your software before installing your update.

Here’s how to add a batch file to your setup project to accommodate this.

First, left-click to select your Setup project in the Solution Explorer, and copy the “ProductCode” field’s value (it will be a GUID) from the properties window (if you don’t see it, hit F4 to bring up the properties listing).

image

Next, right-click your Setup project and choose Open Folder in Windows Explorer.

Create a file there called RunMeToSetup.BAT with the following content (substituting the GUID below with the one you copied):

MsiExec.exe /uninstall {00000000-0000-0000-0000-000000000000} /qb!-
"%~dp0setup.exe"

Save the batch file.  Then go back into Visual Studio.

If your Setup project is under source control you may have to right-click it and do “Check Out for Edit…” prior to completing the next step.  (If it is not, dude WTF?)

Right click your Setup project and choose Add… File… and add the .BAT file.

Then select the .BAT file  in the list and hit F4 to show the properties window for it.  You need to change the “PackageAs” property to “vsdpaLoose” which is the non-intuitive way of saying that this should be copied into the installer directory, but not zipped up into the MSI.  (Stay classy, MSFT!)

Then when you right-click and build your Setup project, the output will be the setup.exe, the MSI file, and your new batch file.  When you double-click the new batch file, it will run a “bare” uninstaller first for your application’s GUID (non-interactive UI), and then run the setup program.  The crazy %~dp0 thing is just to work around the command-line not fully understanding UNC paths as a starting point (if you double-click the batch file starting in \\myserver\myshare, the “%~dp0setup.exe” will resolve to “\\myserver\myshare\setup.exe”).

If you wish to customize the uninstaller behavior, you can find the switches that MSIEXEC accepts here:  http://msdn.microsoft.com/en-us/library/windows/desktop/aa367988(v=vs.85).aspx

Once you test this successfully on a VM or however else you test your install software, check your setup program and the new batch file back into source control.