Tuesday, April 5, 2016

Gear Oil

I enjoy doing mechanical things working with my hands.  Ten years ago, taking my new duramax in for service and finding the dealer had elected to forgo lubricating the chassis, a decision they say was made by a rogue mechanic, I decided to take the maintenance of my vehicles on myself.  This way, I would become more familiar with my vehicles and right or wrong I became responsible.  Not to mention saving money.

I simply do not drive that much, most of my maintenance comes down to annual vs by mile.   Everything gets an annual service from my two vehicles, motorhome and generators.  I have stayed ontop of all schedules maintenance including transmission service,  radiator flushes, replacing radiator hoses, thermostats, idler/tensioner pulley and serpentine belts at five years.  It is cheap insurance to avoid both costly repairs and breakdowns.  I can do this work for 25%, with AC/Delco and Mopar parts, verses taking it to the dealer.  Moreover, I have the pride in doing it myself.

The subject of this post is differentials.  It is easy to ignore the differential in your vehicle.  Front wheel drive with a transaxle is handled by scheduled transmission fluid changes, but on a rear wheel drive or 4x you have one and two traditional differentials.  For me, I have a 3/4 GM Sierra, a TJ Rubicon and a Workhorse w-20.  GM built the differential, but the Jeep and W-20 have Dana, specifically Dana 44 and Dana Spicer S110.

There are three types of differentials, open, limited slip, and gear based posi-traction.  A differentials job is to compensate of the delta in wheel speed when you go around a corner.  Without this, the inside tire would have to break traction.  From "My Cousin Vinnie" an open differential is when you get the stuck in the mud and one tire spins and spins and the other tire does 'nothen.  Limited slip attempts to provide traction to both wheels when one side loses traction.  Performance cars do this, it helps distribute power output to both wheels.  Off-road vehicles do this to provide better traction.  Locking differentials, unlike limited slip, use a collar that make the axle solid, this makes going around a corner nearly impossible with out something giving like snow, rain or dirt or the tread of your tire.  This is why it hard on your 4x to drive in four wheel drive on dry pavement.  Mechanical devices suffer from non-use as much as abuse.  It is important to make it habit to shift your 4x in and out of four wheel drive and high and low range.  Rainy days are a good time to run in four wheel drive.

Fluid.  Unlike motoroil the type of fluid is not backward compatible.  Manufacturers will recommend a weight, 75w90 synthetic GL/5.  Oil comes in thickness, the lower the number the thinner the oil.    GL/5 is not an improvement of GL/4.  In fact using GL/5 in a GL/4 application can destroy the "soft or yellow" metals like brass found in older vw differentials and manual transmissions.  Manual transmissions contain soft metal "synchros" these floating gears help to align the gear to shift without grinding, it makes shifting smooth and requires less "double-clutching" techniques.  

Clutch based differentials require a limited slip agent.  Regardless of what Jeep says, I finally called Dana and gave them the build numbers from the diffs on my Jeep.  Because of the air-lockers these differentials are open and have no limited slip, therefore, the additive is a waste.  On a light duty vehicle, the additive on an open differential will not make any difference.  Keep in mind this is not the only error Chrysler has in the owners manual.  They list GL/5 for a manual transmission, the sulfer in GL/5 which helps the oil stick to the gear will eat the syncrhos.  Two strikes...

The Dana Spicer 110 is a different animal, this is heavy duty axle rated at 15,500#.  This is an open differential and used in a variety of over the road (OTR) applications.  What Dana recommends is GL/5 75W-90 synthetic, no additive.  In a heavy duty environment the LS additive can oxidize and has a shorter life with diminished efficacy cushioning the gears.  Only problem is trying to find it without buying a 50 gallon drum.  I called Mobile1, Lucas, Royal Purple, they all arbitrarily add some ls additive.  Finally, I stumbled onto Mobile Delvac in one gallon at Zoro (my fav anti-amazon site).  This is rated to 500k miles between drains.  For an RV this interval would never happen, but oil breaks down over time.  My rig has 40k miles on it, but its 10 years old.  I was shocked at the sludge and gunk that I vacuumed out of my s110.  Part of this may have been related to the sloppy stove pipe vent that was updated, that I never knew about.




Be kind to your differential.


Using google business and drive to automate db backup

In this example, I create a Windows service that manages Google Drive.  The service calls a batch file to create an Oracle backup using EXP, manages space on Google Drive and then uploads the backup to google, finally sending an html email via smtp.

The school of hard knocks is a great teacher.  Having a hosting provide fail can be a nightmare.  Invariably this happens without notice and suddenly you are in scramble mode and without sleep for days moving.  There are ways to hedge the dependency on your hosting provider.   One way is to host your DNS with a third party.  This way should things go sideways, you can readily change your DNS settings.  Another good practice is to keep a scheduled cold backup of your database independent of your hosting provider.  Google Drive is a great choice for this.  Not only has google made a commitment to putting their servers up on 10gbs, if your servers are on 1gbs or 10gbs copying large files to google is smoking fast.  The db using the code in this example creates an 800gb cold backup, it takes under 15 seconds to put up on google drive.

Automating this backup process with google drive and Google Business is a bit convoluted, there are security issues and settings that are simpler with a gmail account, or no associated account.  Using Google Business to host your transnational mail is a smart move.  No one messes with Google for mail delivery into the inbox.  Why struggle with a shared ip or building an ip reputation for transnational mail, marketing mail is a different story, but for transnational mail there is no better choice then Google for Business for a small company.  Drive allocation on Google Business, per user, is 30gb vs 15 with gmail.

This examples uses the Google REST API v3, Visual Studio 2012 in C#
Reference https://developers.google.com/drive/v3/web/about-sdk

In a user scenario Google authenticates via a challenge via the browser, unfortunately, that will not work here because we are creating a Service Application, in this case a Windows Service.  Services do not have access to an active user session, fortunately, Google anticipated this need and supports offline authentication for service accounts.

Setup a Service Account on Google
Access console.developers.google.com using admin credentials for your business account.
Locate (the every changing) section for Google Apps APIs
Select Drive (formerly google docs)
Enable Google drive from the API Manager.
Select Credentials (left pane)
Create Credentials as a Service Account key using a project name, this project uses "ServerBackup" but you can name it whatever you want just set in the config.
Under permissions, assign the user name user@yourdomain Permission to use "ServerBackups"  this is how google knows which user account for drive.  From this step you need the internal service-account google created, this is in the form of an email address, it is not the same as a user email address, which is assigned permission to use the service account.  These values go in the config file. This is the connection between the internal service account and the user account.  It is possible to omit the user account in your code when you create the credentials, the service account is created with 15gb of storage, but there is no way to access the service account other than the api.  This is the only way I could this to work was without the user name until I figured out how to associate a user name to the service account.   If you do not care, nor need to access what you are uploading via drive.google.com and 15gb is fine, skip it.  The final step is to create the p12 key for the service account.  Under credentials, select the service account, then manage service accounts, then select create key and download in p12 format.  This is the private key, handle as you wish.  Because google is forever changing their interfaces, screen shots have the lifespan of a fruit-fly.

To implement, this example creates a basic windows service which calls an assembly.

This example only shows how to create the assembly using VS 2012 and 4.0 of the assembly for x64.

Create a new class library and open the Package Manager Console.
PM>Install-Package Google.Apis.Drive.v3
(only do this for the assembly. not the service exe)

Below is the code:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using System.Configuration;
using System.IO;
using System.Data;
using System.Net;
using System.Net.Mail;
using System.Threading;
using System.Security.Cryptography.X509Certificates;
using Google.Apis.Auth.OAuth2;
using Google.Apis.Drive.v3;
using Google.Apis.Drive.v3.Data;
using Google.Apis.Services;
using Google.Apis.Util.Store;
 
namespace GPHousekeepingServer
{
 
    public class SMTPRec
    {
        public bool processConfirmations;
        public string host;
        public string hostUserName;
        public string hostPassword;
        public int hostPort;
        public string to;
        public string from;
        public string htmlSource;
        public string rawHTML;
        public string bcc;
        public string subject;
        public bool useSSL;
        public SMTPRec(string passedhtml, string passedSubject)
        {
            try
            {
                //because this is running from an assembly, cannot use ConfigurationManager directly.
                useSSL = false;
                string path = System.Reflection.Assembly.GetExecutingAssembly().Location;
                Configuration config = ConfigurationManager.OpenExeConfiguration(path);
 
                host = config.AppSettings.Settings["SmtpHost"].Value;
                string sPort = config.AppSettings.Settings["SmtpPort"].Value;
                if (sPort.Equals(string.Empty))
                    throw new Exception("SmtpPort is null");
                if (!int.TryParse(sPort, out hostPort))
                    throw new Exception("Unable to convert SmtpPort to an int.");
 
                if (config.AppSettings.Settings["SmtpHostUserName"] != null)
                {
                    hostUserName = config.AppSettings.Settings["SmtpHostUserName"].Value;
                    if (config.AppSettings.Settings["SmtpHostPassword"] == null)
                        throw new Exception("SmtpHostUserName set, however SmtpHostPassword is null");
                    hostPassword = config.AppSettings.Settings["SmtpHostPassword"].Value;
                }
 
                if (config.AppSettings.Settings["SmtpUseSSL"] != null)
                    useSSL = config.AppSettings.Settings["SmtpUseSSL"].Value.Equals("1");
 
                to = config.AppSettings.Settings["ToEmail"].Value;
                from = config.AppSettings.Settings["FromEmail"].Value;
                bcc = string.Empty;
 
                if (passedSubject.Equals(string.Empty))
                    subject = config.AppSettings.Settings["subject"].Value;
                else
                    subject = passedSubject;
 
                rawHTML = passedhtml;
 
            }
            catch (Exception E)
            {
                throw new Exception("Exception raised in SMTPRec constructor, " + E.Message);
            }
        }
    }
 
    public static class HouseKeeping
    {
 
        private static CollateralClass c = null;
        private static Thread thread = null;
 
        public static void Start()
        {
            try
            {
                if (c != null)
                    throw new Exception("Thread is already running.");
 
                c = new CollateralClass();
                c.bTerminated = false;
 
                thread = new Thread(new ThreadStart(c.Worker));
                thread.Start();
 
            }
            catch (Exception E)
            {
                Utility.SendEventLogError("Fatal error in Housekeeping (stopping), " + E.Message);
            }
        }
 
        public static void Stop()
        {
            try
            {
 
                if (c == null)
                    throw new Exception("Thread is not running, call Execute to start thread.");
                c.bTerminated = true;
 
            }
            catch (Exception E)
            {
                Utility.SendEventLogError("Exception raised in Stop, " + E.Message);
            }
        }
 
 
        class CollateralClass
        {
            public bool bTerminated = false;
            EventLog eventLog = new EventLog();
            Hashtable htReported = new Hashtable();
            public void Worker()
            {
 
                int iLongerJobCounter = 361;
                try
                {
                    while (!bTerminated)
                    {
                        Thread.Sleep(1000 * 5);
                        iLongerJobCounter++;
                        //runs every five minutes
                        if (iLongerJobCounter > 60)
                        {
                            iLongerJobCounter = 0;
                            RunDBBackupJob();
                        }
                    }                 }                 catch (Exception E)                 {                     Utility.SendEventLogError("Exception raised in HousekeepingsServer (thread), " + E.Message);                 }             }         }         private static void RunDBBackupJob()         {             try             {                 DateTime dtLastTime = new DateTime(Utility.GetLastBackup());                 bool bBackup = (DateTime.Now > dtLastTime.AddMinutes(Utility.GetBackupEvery()));                 if (bBackup)                 {                     string sFileName = Utility.GetBackupPrefix()+ DateTime.Now.ToString("yyyyMMdd_HHmm");                     string sPathName = Utility.GetBackupLocation();                     Utility.SendEventLogInfo("GPHousekeepingServer:RunDBBackUpJob to "+sPathName+sFileName);                     var proc = new Process                     {                         StartInfo =                             new ProcessStartInfo                             {                                 FileName = Utility.GetBackupBatchFile(),                                    Arguments = sPathName+sFileName,                                 UseShellExecute = false,                                 CreateNoWindow = false                             }                     };                     proc.Start();                     proc.WaitForExit();                     int successExitCode = 0;                     if (proc.ExitCode == successExitCode)                     {                         Utility.SendEventLogInfo("GPHousekeepingServer:RunDBBackUpJob done with exp, setting up drive");                         var certificate = new X509Certificate2(Utility.GetBackupP12File(), "notasecret"X509KeyStorageFlags.Exportable);                         var serviceAccountEmail = Utility.GetBackupServiceAccount();                         var userAccountEmail = Utility.GetBackupUserAccount();                         ServiceAccountCredential credential = new ServiceAccountCredential(                             new ServiceAccountCredential.Initializer(serviceAccountEmail)                             {                                 Scopes = new[] { Google.Apis.Drive.v3.DriveService.Scope.Drive },                                 User = userAccountEmail                             }.FromCertificate(certificate));                         // Create the service.                         using (DriveService driveService = new DriveService(new BaseClientService.Initializer()                             {                                 HttpClientInitializer = credential,                                 ApplicationName = Utility.GetApplicationName()                             }))                         {                             var about = driveService.About.Get();                             about.Fields = "storageQuota,user";                             User user = about.Execute().User;                             StringBuilder sb = new StringBuilder("<!DOCTYPE><html><head><title></title></head><body>");                             sb.Append("User " + user.DisplayName + ", " + user.EmailAddress + "<br/>");                             if (!System.IO.File.Exists(sPathName + sFileName + ".dmp"))                                 throw new Exception("Unable to location: " + sPathName + sFileName + ".dmp, did " + Utility.GetBackupBatchFile() + " run?");                             FileInfo fi = new FileInfo(sPathName + sFileName + ".dmp");                             //upload to drive.google                             var storageQuota = about.Execute().StorageQuota;                             if (storageQuota.Limit == null)                                 sb.Append("StorageUsage: " + Math.Round((double)(storageQuota.Usage / Math.Pow(1024, 2)), 1).ToString() + "mb, StorageLimit: Unlimited<br/>");                             else                             {                                 sb.Append("StorageUsage: " + Math.Round((double)(storageQuota.Usage / Math.Pow(1024, 2)), 1).ToString() + "mb, StorageLimit: " + (storageQuota.Limit / Math.Pow(1024, 3)) + "gb, Space Available: " + Math.Round((double)((storageQuota.Limit - storageQuota.Usage) / Math.Pow(1024, 2)), 1).ToString() + "mb<br/>");                                 if (fi.Length > (storageQuota.Limit - storageQuota.Usage))                                 {                                     //clean up some space by removing the oldest files.  need to remove fi.length                                     sb.Append("drive.google is full, making space by removing:<br/>");                                     FilesResource.ListRequest listDelete = driveService.Files.List();                                     // listRequest.Spaces = "appDataFolder";                                     listDelete.PageSize = 100;                                     listDelete.Fields = "nextPageToken, files(id, name, size, createdTime)";                                     listDelete.OrderBy = "createdTime asc";                                     IList<Google.Apis.Drive.v3.Data.File> files = listDelete.Execute().Files;                                     long fucking=(long)storageQuota.Limit;                                     long stupid = (long)storageQuota.Usage;                                     long lBytesDeleted = fucking-stupid;                                     if (files != null)                                     {                                         foreach (var file in files)                                         {                                             if (file.Name.ToUpper().Contains("BBB_"))                                             {                                                 sb.Append("Deleted: " + ((DateTime)file.CreatedTime).ToString("MM/dd/yyyy HHmm") + " " + file.Name + " " + file.Id + " size: " + file.Size + "<br/>");                                                 driveService.Files.Delete(file.Id).Execute();                                                 lBytesDeleted += (long)file.Size;                                                 if (lBytesDeleted > fi.Length)                                                     break;                                             }                                         }                                     }                                 }                             }                             //upload file                             Utility.SendEventLogInfo("GPHousekeepingServer:RunDBBackUpJob " + sFileName + " uploading to drive");                             Google.Apis.Drive.v3.Data.File fileMetaData = new Google.Apis.Drive.v3.Data.File();                             fileMetaData.Name = sFileName + ".dmp";                             using (FileStream uploadStream = new FileStream(sPathName + sFileName + ".dmp"FileMode.Open, FileAccess.Read))                             {                                 FilesResource.CreateMediaUpload request = driveService.Files.Create(fileMetaData, uploadStream, "application/octet-stream");                                 request.Fields = "id,size";                                 request.Upload();                                 uploadStream.Close();                                 uploadStream.Dispose();                                 Utility.SendEventLogInfo("GPHousekeepingServer:RunDBBackUpJob File Uploaded to drive, ID: " + request.ResponseBody.Id + ", size: " + request.ResponseBody.Size + "<br/>");                                 sb.Append("File Uploaded, ID: " + request.ResponseBody.Id + ", size: " + request.ResponseBody.Size + "<br/>");                             }                             {                                 FilesResource.ListRequest listRequest = driveService.Files.List();                                 // listRequest.Spaces = "appDataFolder";                                 listRequest.PageSize = 100;                                 listRequest.Fields = "nextPageToken, files(id, name, size, createdTime)";                                 listRequest.OrderBy = "createdTime desc";                                 IList<Google.Apis.Drive.v3.Data.File> files = listRequest.Execute().Files;                                 if (files != null)                                 {                                     sb.Append("FILES on drive.google.com<br/>");                                     foreach (var file in files)                                         sb.Append(((DateTime)file.CreatedTime).ToString("MM/dd/yyyy HHmm") + " " + file.Name + " " + file.Id + " size: " + file.Size + "<br/>");                                 }                             }                             Utility.SetLastBackup(DateTime.Now.Ticks);                             sb.Append("</body></html>");                             SendEMail(new SMTPRec(sb.ToString(), "dbBackup"));                             driveService.Dispose();                         }                     }                     else                     {                         throw new Exception(string.Format("EXP FAILED!  Process exit code not same as successExitCode specified.!! Process ExitCode={0} and successExitCode={1}", proc.ExitCode, successExitCode));                     }                 }             }             catch (Exception E)             {                 Utility.SendEventLogError("Fatal Exception raised in HousekeepingServer.RunDBBackupJob (not-stopping), " + E.Message);             }         }         private static void SendEMail(SMTPRec smtpInfo)         {             try             {                 string sBody = smtpInfo.rawHTML;                 MailAddress maFrom = new MailAddress(smtpInfo.from, "Housekeeping"Encoding.UTF8);                 MailAddress maTo = new MailAddress(smtpInfo.to, smtpInfo.to, Encoding.UTF8);                 MailMessage mailMessage = new MailMessage(maFrom, maTo);                 if (!smtpInfo.bcc.Equals(string.Empty))                     mailMessage.Bcc.Add(smtpInfo.bcc);                 mailMessage.Body = sBody;                 mailMessage.BodyEncoding = Encoding.UTF8;                 mailMessage.IsBodyHtml = true;                 mailMessage.Subject = smtpInfo.subject;                 mailMessage.SubjectEncoding = Encoding.UTF8;                 SmtpClient smtpClient = new SmtpClient(smtpInfo.host, smtpInfo.hostPort);                 smtpClient.DeliveryMethod = SmtpDeliveryMethod.Network;                 smtpClient.Timeout = 20000;                 if (smtpInfo.useSSL)                 {                     Utility.SendEventLogInfo("Using SSL");                     smtpClient.EnableSsl = true;                 }                 if (!string.IsNullOrEmpty(smtpInfo.hostUserName))                 {                     Utility.SendEventLogInfo("Setting credentials smtpClient, " + smtpInfo.hostUserName + " password " + smtpInfo.hostPassword);                     smtpClient.UseDefaultCredentials = false;                     smtpClient.Credentials = new NetworkCredential(smtpInfo.hostUserName, smtpInfo.hostPassword); ;                 }                 smtpClient.Send(mailMessage);             }             catch (Exception E)             {                 Utility.SendEventLogError("GPHousekeeping:SendEMail Exception Raised: "+ E.Message);             }         }     } }

Utility.cs
using System;
using System.Data;
using System.Configuration;
using System.Text.RegularExpressions;
using System.IO;
using System.IO.Ports;
using System.Net;
using System.Net.Sockets;
using Oracle.DataAccess.Client;
using System.Diagnostics;
 
 
/// <summary>
/// Summary description for Utility
/// </summary>
public static class Utility
{
    public static System.Diagnostics.EventLog myEventLog;
 
    static Utility()
    {
        if (!EventLog.SourceExists("GPHousekeepingServer"))
            EventLog.CreateEventSource("GPHousekeepingServer""Application");
        myEventLog = new EventLog("Application");
        myEventLog.Source = "GPHousekeepingServer";
    }
 
    public static void SendEventLogError(string errorMessage)
    {
        try
        {
            if (myEventLog != null)
                myEventLog.WriteEntry(errorMessage, EventLogEntryType.Error);
        }
        catch (Exception)
        {
            //nothing to do with this... :(
        }
    }
 
    public static void SendEventLogInfo(string infoMessage)
    {
        try
        {
            if (myEventLog != null)
                myEventLog.WriteEntry(infoMessage, EventLogEntryType.Information);
        }
        catch (Exception)
        {
            //nothing to do with this... :(
        }
    }
 
    public static bool isEmail(string inputEmail)
    {
        string strRegex = @"^([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}" +
              @"\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\" +
              @".)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$";
        Regex re = new Regex(strRegex);
        if (re.IsMatch(inputEmail))
            return (true);
        else
            return (false);
    }
 
 
    public static uint IPDottedToUint(string dottedIP)
    {
        uint uIP = 0;
        try
        {
            string[] sNumbers = dottedIP.Split('.');
            if (sNumbers.GetLength(0) != 4)
                throw new Exception("invalid format, " + dottedIP);
 
            uIP = (uint.Parse(sNumbers[0]) * 16777216) + (uint.Parse(sNumbers[1]) * 65536) + (uint.Parse(sNumbers[2]) * 256) + (uint.Parse(sNumbers[3]));
 
        }
        catch (Exception E)
        {
            throw new Exception("Exception raised in IPDottedToUint, " + E.Message);
        }
        return uIP;
    }
 
 
    public static long GetLastBackup()
    {
        long lResult=0;
        try
        {
            Configuration config = ConfigurationManager.OpenExeConfiguration(System.Reflection.Assembly.GetExecutingAssembly().Location);
            if (config.AppSettings.Settings["lastBackupRun"] == null)
            {
                //to force initial run, arbitrarily subtract one day
                lResult = DateTime.Now.AddDays(-1).Ticks;
            }
            else
            {
                if (!long.TryParse(config.AppSettings.Settings["lastBackupRun"].Value, out lResult))
                    throw new Exception("Trouble parsing lastBackupRun (ticks) from config, " + config.AppSettings.Settings["lastBackupRun"].Value);
            }
        }
        catch (Exception E)
        {
            throw new Exception("Exception raised in GetLastBackup, " + E.Message);
        }
        return lResult;
    }
 
    public static void SetLastBackup(long ticks)
    {
        try
        {
            Configuration config = ConfigurationManager.OpenExeConfiguration(System.Reflection.Assembly.GetExecutingAssembly().Location);
            if (config.AppSettings.Settings["lastBackupRun"] == null)
                config.AppSettings.Settings.Add("lastBackupRun", ticks.ToString());
            else
                config.AppSettings.Settings["lastBackupRun"].Value = ticks.ToString();
            config.Save(ConfigurationSaveMode.Minimal, false);
        }
        catch (Exception E)
        {
            throw new Exception("Exception raised in SetLastBackup, " + E.Message);
        }
    }
 
    public static string GetBackupLocation()
    {
        string sResult = string.Empty;
        try
        {
            Configuration config = ConfigurationManager.OpenExeConfiguration(System.Reflection.Assembly.GetExecutingAssembly().Location);
            if (config.AppSettings.Settings["backuplocation"] == null)
                throw new Exception("backuplocation is not set in App.config");
            sResult = config.AppSettings.Settings["backuplocation"].Value;
 
        }
        catch (Exception E)
        {
            throw new Exception("Exception raised in GetBackupLocation, " + E.Message);
        }
        return sResult;
    }
 
    public static string GetBackupServiceAccount()
    {
        string sResult = string.Empty;
        try
        {
            Configuration config = ConfigurationManager.OpenExeConfiguration(System.Reflection.Assembly.GetExecutingAssembly().Location);
            if (config.AppSettings.Settings["backupserviceAccount"] == null)
                throw new Exception("backupserviceAccount is not set in App.config");
            sResult = config.AppSettings.Settings["backupserviceaccount"].Value;
 
        }
        catch (Exception E)
        {
            throw new Exception("Exception raised in GetBackupServiceAccount, " + E.Message);
        }
        return sResult;
    }
 
    public static string GetBackupUserAccount()
    {
        string sResult = string.Empty;
        try
        {
            Configuration config = ConfigurationManager.OpenExeConfiguration(System.Reflection.Assembly.GetExecutingAssembly().Location);
            if (config.AppSettings.Settings["backupuseraccount"] == null)
                throw new Exception("backupuseraccount is not set in App.config");
            sResult = config.AppSettings.Settings["backupuseraccount"].Value;
 
        }
        catch (Exception E)
        {
            throw new Exception("Exception raised in GetBackupUserAccount, " + E.Message);
        }
        return sResult;
    }
 
    public static string GetBackupPrefix()
    {
        string sResult = string.Empty;
        try
        {
            Configuration config = ConfigurationManager.OpenExeConfiguration(System.Reflection.Assembly.GetExecutingAssembly().Location);
            if (config.AppSettings.Settings["backupprefix"] == null)
                throw new Exception("backupprefix is not set in App.config");
            sResult = config.AppSettings.Settings["backupprefix"].Value;
 
        }
        catch (Exception E)
        {
            throw new Exception("Exception raised in GetBackupPrefix, " + E.Message);
        }
        return sResult;
    }
 
 
    public static string GetApplicationName()
    {
        string sResult = string.Empty;
        try
        {
            Configuration config = ConfigurationManager.OpenExeConfiguration(System.Reflection.Assembly.GetExecutingAssembly().Location);
            if (config.AppSettings.Settings["backupapplicationname"] == null)
                throw new Exception("backupapplicationname is not set in App.config");
            sResult = config.AppSettings.Settings["backupapplicationname"].Value;
 
        }
        catch (Exception E)
        {
            throw new Exception("Exception raised in GetApplicationName, " + E.Message);
        }
        return sResult;
    }
 
 
 
    public static string GetBackupBatchFile()
    {
        string sResult = string.Empty;
        try
        {
            Configuration config = ConfigurationManager.OpenExeConfiguration(System.Reflection.Assembly.GetExecutingAssembly().Location);
            if (config.AppSettings.Settings["backupbatch"] == null)
                throw new Exception("backupbatch is not set in App.config");
            sResult = config.AppSettings.Settings["backupbatch"].Value;
            if (!File.Exists(sResult))
                throw new Exception("unable to locate file, " + sResult);
        }
        catch (Exception E)
        {
            throw new Exception("Exception raised in GetBackupBatchFile, " + E.Message);
        }
        return sResult;
    }
 
    public static string GetBackupP12File()
    {
        string sResult = string.Empty;
        try
        {
            //determine the code for the current provider
            Configuration config = ConfigurationManager.OpenExeConfiguration(System.Reflection.Assembly.GetExecutingAssembly().Location);
            if (config.AppSettings.Settings["backupp12"] == null)
                throw new Exception("backupp12 is not set in App.config");
            sResult = config.AppSettings.Settings["backupp12"].Value;
            if (!File.Exists(sResult))
                throw new Exception("unable to locate file, " + sResult);
        }
        catch (Exception E)
        {
            throw new Exception("Exception raised in GetBackupP12File, " + E.Message);
        }
        return sResult;
    }
 
    public static int GetBackupEvery()
    {
        int iResult = 0;
        try
        {
            //determine the code for the current provider
            Configuration config = ConfigurationManager.OpenExeConfiguration(System.Reflection.Assembly.GetExecutingAssembly().Location);
            if (config.AppSettings.Settings["backupevery"] == null)
                throw new Exception("backupevery is not set in App.config");
            if (!int.TryParse(config.AppSettings.Settings["backupevery"].Value, out iResult))
                throw new Exception("unable to convert to int, " + config.AppSettings.Settings["backupevery"].Value);
        }
        catch (Exception E)
        {
            throw new Exception("Exception raised in GetBackupEvery, " + E.Message);
        }
        return iResult;
    }
 
}



Below is the assemblyname.config file
<configuration>
  <appSettings>
    <add key="SmtpHost" value="smtp.gmail.com" />
    <add key="SmtpPort" value="587" />
    <add key="SmtpHostUserName" value="" />
    <add key="SmtpHostPassword" value="" />
    <add key="SmtpUseSSL" value="1"/>
    <add key="FromEmail" value="" />
    <add key="ToEmail" value="" />
    <add key="subject" value="DB Backup"/>
    <add key="backuplocation" value="c:\garbage\"/>
    <add key="backupbatch" value="c:\GPUtilities\cmdbackup.bat"/>
    <add key="backupevery" value="480"/> 
    <add key="backupp12"   value="c:\GPUtilities\ServerBackups.p12"/>
    <add key="backupserviceaccount" value="...@...gserviceaccount.com"/>
    <add key="backupuseraccount" value=""/>
    <add key="backupapplicationname" value=""/>
    <add key="backupprefix" value="BBB_"/>
  </appSettings>
</configuration>

Example of  batch file called in backupbatch for Oracle, this could be anything so long as it ultimately creates a single file %1 passed in from the service.
@ECHO OFF

SET filename=%1.dmp
SET logname=%1.log

EXP credentials FILE=%filename% OWNER=schema LOG=%logname% STATISTICS=NONE