Purpose: SSIS Package Main Script Executable with DB Connectivity Verification and Error logging
using System.Collections.Generic;
using Microsoft.SqlServer.Dts.Runtime;
using Microsoft.VisualBasic.FileIO;
using System.Diagnostics;
namespace CP_AutoTerminations
/// ScriptMain entry point class.
[Microsoft.SqlServer.Dts.Tasks.ScriptTask.SSISScriptTaskEntryPointAttribute]
public partial class ScriptMain : Microsoft.SqlServer.Dts.Tasks.ScriptTask.VSTARTScriptObjectModelBase
private DataTable _dErrorsTable;
private string _messageData;
private string _fileNameOut;
//private ConnectionManager _connectMgr;
public DataTable ErrorsTable
if (_dErrorsTable == null) _dErrorsTable = new DataTable();
if (_dErrorsTable.Columns.Count == 0) _dErrorsTable.Columns.Add(new DataColumn("Errors"));
set => _dErrorsTable = value;
public string MessageData
get { return _messageData ?? "" ; }
set => _messageData = value;
public string FileNameOut
get { return _fileNameOut; }
set => _fileNameOut = value;
/// This method is called when this script task executes in the control flow.
/// and sets the value of Dts.TaskResult to indicate success or failure.
DataTable csvData = new DataTable();
StringBuilder sb = new StringBuilder();
//string fileNameOut = this.FileNameOut;
this.MessageData = string.Empty;
string fileNameIn = (string)ReadVariable("User::InputDirPath").ToString();
//string fileNameEx = (string)ReadVariable("User::OutputExPath").ToString();
csvData = GetDataTableFromCsvFile(fileNameIn);
if (csvData == null || Dts.TaskResult == 1 || ErrorsTable.Rows?.Count > 0)
//if error occurred, InputDirPath has changed, reset it here, before the return;
if (ErrorsTable.Rows.Count > 0)
foreach (DataRow row in ErrorsTable.Rows)
this.MessageData += " - " + row.ItemArray[0].ToString();
WriteVariable("User::OutputData", this.MessageData);
return; // EXIT EXIT EXIT
//using (StreamWriter w = File.AppendText(this.FileNameOut))
// var msg = $"Acquiring Db Connection: " + Dts.Connections["DatabaseConnection"].ConnectionString;
cm = Dts.Connections["DatabaseConnection"];
sqlConn = (OleDbConnection)cm.AcquireConnection(Dts.Transaction);
//sqlConn.ConnectionTimeout = 0;
//string fileXmlOut = fileNameOut;
// using (StreamWriter w = File.AppendText(this.FileNameOut))
// var msg = "Acquired Db Connection.";
//Read from Datatable and process each row by Execute sproc
foreach (DataRow cvrRow in csvData.Rows)
//this.FileNameOut = fileNameOut;
if ((string) cvrRow.ItemArray[0].ToString().ToLower() == "shortname") continue;
sQuerySuffix = "@name='[0]', @Acc='[1]', @NPI='[2]', @TermAll=0";
sQuerySuffix = sQuerySuffix.Replace("[0]", (string) cvrRow.ItemArray[0]);
sQuerySuffix = sQuerySuffix.Replace("[1]", (string) cvrRow.ItemArray[1]);
sQuerySuffix = sQuerySuffix.Replace("[2]", (string) cvrRow.ItemArray[2]);
//sQuerySuffix = sQuerySuffix.Replace("[3]", cvrRow.ItemArray[3].ToString().Trim());
sQuerySuffix = sQuerySuffix.Replace("'NULL'", "NULL");
// example [Invoice_Process].dbo.[spInvManualRunTerm] @name=N'UAMS1',@Acc=NULL,@NPI=NULL, @TermAll=0;
sQuery = string.Concat(@"EXECUTE [InvoiceDB].dbo.[spInvManualRunTerm] ", sQuerySuffix, ";");
//MessageBox.Show(query);
//using (StreamWriter w = File.AppendText(this.FileNameOut))
var dResultTable = (new DataSet("AutoTermsResult")).Tables.Add("Logging");
sWriter = new StringWriter();
using (var cmd = new OleDbCommand(sQuery, sqlConn))
using (var da = new OleDbDataAdapter(cmd))
dResultTable.WriteXml(sWriter);
if (dResultTable?.Rows?.Count > 0)
sb = new StringBuilder();
sb.AppendLine(string.Join(",", cvrRow.ItemArray));
this.MessageData = string.Concat(@"Term Results for:" , sb.ToString(), Environment.NewLine , sWriter.ToString(), Environment.NewLine);
if (this.MessageData.Contains("Exception") || this.MessageData.Contains("Errors"))
this.ErrorsTable.Rows.Add(new object[] { this.MessageData });
else // write good xml output
using (StreamWriter w = File.AppendText(this.FileNameOut))
LogEntry(this.MessageData, w);
this.ErrorsTable.Rows.Add(new object[] { ex.Message });
this.LogResults(ex.Message, true);
//<< CHANGES THE LOGFILE DIRECTORY to /EXCEPTION
WriteVariable("User::OutputData", this.MessageData);
Dts.ExecutionValue = rsNumber;
Dts.TaskResult = (int)ScriptResults.Success;
//catch possible null EX, it has happened.
if (ex.Equals(null)) ex = new Exception("InvManualTerm Package.Main. Unknown exception in script task main function.");
WriteVariable("User::OutputData", ex.Message);
ThrowAndFail(ex.Message);
if (Dts.TaskResult == 1 || ErrorsTable.Rows?.Count > 0)
if (ErrorsTable.Rows?.Count > 0)
this.MessageData = "Parameters: ";
if (csvData?.Rows.Count > 0)
foreach (DataRow dr in csvData.Rows)
sb.AppendLine(string.Join(",", dr.ItemArray));
foreach (DataRow dr in ErrorsTable?.Rows)
sb.AppendLine(dr.ItemArray[0].ToString());
this.MessageData += sb.ToString();
WriteVariable("User::OutputData", this.MessageData);
this.LogResults(this.MessageData, true);
//<< CHANGES THE LOGFILE DIRECTORY to /EXCEPTION
SetParmsDestination(true);
//Dts.TaskResult = (int) ScriptResults.Failure;
SetParmsDestination(false);
//Dts.TaskResult = (int) ScriptResults.Success;
Dts.TaskResult = (int) ScriptResults.Success;
//let it succeed either way and send email notification
public void SetLogFile(bool isError)
this.FileNameOut = ReadVariable("User::OutputDirPath").ToString();
if (string.IsNullOrEmpty(this.FileNameOut))
this.FileNameOut = string.Concat(@"\\server01\Backup\Terms\InvTermsParameters_", DateTime.Now.ToString("yyyyMMddHHmm"), ".log");
sDir = FileNameOut.Substring(0,FileNameOut.LastIndexOf('\\'));
//sDir = Path.GetDirectoryName(this.FileNameOut); //this.FileNameOut.Substring(0,this.FileNameOut.LastIndexOf(@"\"))
if (!string.IsNullOrEmpty(sDir) && !Directory.Exists(sDir))
Directory.CreateDirectory(sDir);
this.MessageData += Environment.NewLine + ex.ToString();
if (!this.FileNameOut.Contains(DateTime.Now.ToString("yyyy")))
this.FileNameOut = this.FileNameOut.Replace(".log", string.Concat("_", DateTime.Now.ToString("yyyyMMddHHmm"), ".log"));
// fileNameOut format ex: \\Server01\Backup\Terms\InvTermsOutput_2020042901.log
if (isError.Equals(true))
sDir = this.FileNameOut.Replace(@"\BACKUP\", @"\EXCEPTIONS\");
sDir = sDir.Substring(0,sDir.LastIndexOf('\\'));
if (!string.IsNullOrEmpty(sDir) && !Directory.Exists(sDir))
Directory.CreateDirectory(sDir);
this.MessageData += Environment.NewLine + ex.ToString();
if (!string.IsNullOrEmpty(sDir) && Directory.Exists(sDir))
this.FileNameOut = this.FileNameOut.Replace(@"\BACKUP\", @"\EXCEPTIONS\");
} //else don't change it, logs will dump in the BACKUP folder
WriteVariable("User::OutputExPath", this.FileNameOut);
//this.FileNameOut = ReadVariable("User::OutputExPath").ToString();
// fileNameOut format ex: \\Server01\Incoming\Terms\InvTermsOutput_2020042901.log
// EX. UNC: \\Server01\EXCEPTIONS\Terms\InvTermsOutput_2020042901.log
using (StreamWriter w = File.AppendText(this.FileNameOut))
LogEntry("SetLogFile.isError=True", w);
if (bFixedName.Equals(true))
WriteVariable("User::OutputDirPath", this.FileNameOut);
//Example: object myVarValue = "Abcd"; WriteVariable("User::MyVar", myVarValue);
private void SetParmsDestination(bool IsError)
if (string.IsNullOrEmpty(this.FileNameOut))
// get base input file variable, and move it, if previous attempt has failed
string fileParmsIncoming = (string)ReadVariable("$Package::InputFilePath").ToString();
if (File.Exists(fileParmsIncoming)) //then move it
string fileDestination = this.FileNameOut.Replace(".log", ".csv");
if (IsError.Equals(true))
fileDestination = fileDestination.Replace(@"\BACKUP\", @"\EXCEPTIONS\");
if (File.Exists(fileDestination)) //then rename it
fileDestination = fileDestination.Replace(".csv", string.Concat("_", DateTime.Now.ToString("yyyyMMddHHmm"), ".csv"));
File.Move(fileParmsIncoming, fileDestination);
private void WriteVariable(string varName, object varValue)
Dts.VariableDispenser.LockForWrite(varName);
Dts.VariableDispenser.GetVariables(ref vars);
vars[varName].Value = varValue;
//Example: object myVarValue = ReadVariable("User::MyVar");
private object ReadVariable(string varName)
var result = new object();
Dts.VariableDispenser.LockForRead(varName);
Dts.VariableDispenser.GetVariables(ref vars);
result = vars[varName].Value;
private DataTable GetDataTableFromCsvFile(string csvFilePath)
DataTable csvData = (new DataSet("AutoTermsResult")).Tables.Add("Logging");
using (TextFieldParser csvReader = new TextFieldParser(csvFilePath))
csvReader.SetDelimiters(new string[] {","});
csvReader.HasFieldsEnclosedInQuotes = false;
string[] colFields = csvReader.ReadFields();
foreach (var column in colFields)
DataColumn dc = new DataColumn(column);
while (!csvReader.EndOfData)
string[] fieldData = csvReader.ReadFields();
if (fieldData == null) continue;
//Making empty value as null
for (i = 0; i < fieldData.Length; i++)
var s = fieldData[i].Trim();
if (string.IsNullOrEmpty(s))
csvData.Rows.Add(fieldData);
// VALIDATION: NO VALUES, ALL NULL VALUES, MISSING FIELDS
if (i==0 || j > 0 || fieldData.Length < 3)
sError = "CSV input file failure. DATA VALUES VALIDATION. Data values are required for name,Acc,NPI,TermAll.";
// COLUMN COUNT VALIDATION
if (csvData.Columns?.Count < 4)
sError = "CSV input file failure. COLUMN COUNT VALIDATION. Header columns required:
if (csvData.Columns[0].ColumnName != "name")
sError = "CSV input file failure. COLUMN 1 VALIDATION. Column1 is Name.";
if (csvData.Columns[1].ColumnName != "Acc")
sError = "CSV input file failure. COLUMN 2 VALIDATION. Column2 is Acc.";
if (csvData.Columns[2].ColumnName != "NPI")
sError = "CSV input file failure. COLUMN 3 VALIDATION. Column3 is NPI.";
if (csvData.Columns[3].ColumnName != "TermAll")
sError = "CSV input file failure. COLUMN 4 VALIDATION. Column4 is TermAll.";
if (csvData.Rows.Equals(null) || csvData.Rows.Count < 1)
sError = "CSV input file failure. ROW COUNT VALIDATION. Column Header row and at least 1 data row are required.";
//StringWriter sWriter = new StringWriter();
//csvData.WriteXml(sWriter);
//using (StreamWriter w = File.AppendText(this.FileNameOut))
// LogEntry(sWriter.ToString(), w);
WriteVariable("User::OutputData", ex.Message);
ThrowAndFail(ex.Message);
//Dts.TaskResult = (int)ScriptResults.Failure;
private void ThrowAndFail(string message)
this.ErrorsTable.Rows.Add(new object[] { message });
Dts.Events.FireError(0, "InvManualRunTerm Package.Error", message + Environment.NewLine, string.Empty, 0);
//Dts.TaskResult = (int)ScriptResults.Failure;
#region ScriptResults declaration
/// This enum provides shorthand class for setting the result of the script.
private enum ScriptResults
Success = DTSExecResult.Success,
Failure = DTSExecResult.Failure
public void LogResults(string fileData, bool isError)
//<?xml version = "1.0" encoding = "UTF-8"?>
bool errorOccurred = false; //in event all logging methods fail
if (String.IsNullOrEmpty(fileData) || fileData.ToLower().Contains("system.object"))
fileData = "OutputData value is empty. Nothing to log.";
WriteVariable("User::OutputData", fileData);
using (StreamWriter w = File.AppendText(this.FileNameOut))
//using (StreamReader r = File.OpenText(this.FileNameOut))
errorOccurred = true; // possible network logging issue. try to save to event log.
ThrowAndFail(ex.Message);
WriteVariable("User::OutputData", ex.Message);
using (EventLog eventLog = new EventLog("Application"))
eventLog.Source = "Application";
eventLog.WriteEntry(string.Concat("InvManualTerm Package.Error. ", Environment.NewLine, ex.Message.ToString()), EventLogEntryType.Error, 101, 1);
//Dts.TaskResult = (int)ScriptResults.Failure;
if (errorOccurred) // fire event to store in SQL DTS log
Dts.Events.FireError(18, "InvManualTerm Package.Error", "An Exception was caught during logging write and output data flush. Check server event application log for details.", "", 0);
//Dts.TaskResult = (int)ScriptResults.Failure;
public static void LogEntry(string logMessage, TextWriter w)
w.Write(Environment.NewLine + "ScriptTaskMain: " + $"{DateTime.Now:yyyyMMdd} : {DateTime.Now.ToLongTimeString()}");
w.WriteLine($" :{logMessage}");
public static void DumpLogToConsole(StreamReader r)
while ((line = r.ReadLine()) != null)
public partial class CheckConnection
private ConnectionManager connectionManager;
//"OLEDB", "ADO.NET:SQL", "ADO.NET:OLEDB"
public void CreateOLEConnection(Package p, string csType)
connectionManager = p.Connections.Add(csType);
//Provider=SQLNCLI11.1;Integrated Security=SSPI;Persist Security Info=False;User ID="";Initial Catalog=myDatabase;Data Source=Server01
{ //Server=MYSERVER;Provider=SQLOLEDB.1;Pwd= xxxxxxx;User ID= xxxxx;Initial Catalog=mySource;OLE DB Services=-2"
connectionManager.ConnectionString = @"Provider=SQLOLEDB.1;Integrated Security=SSPI;Initial Catalog=myDatabase;Data Source=Server01;";
connectionManager.ConnectionString = @"Provider=SQLNCLI11.1;Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=myDatabase;Data Source=Server01;Auto Translate=False;";
connectionManager.Name = "SSIS Connection Manager";
connectionManager.Description = "DB connection";