public virtual string generateDlineageRelation(Dlineage dlineage, columnImpactResult impactResult) { if (dlineage == null || impactResult == null) { return(null); } Document doc = null; Element dlineageRelation = null; doc = new Document(); XDeclaration declaration = new XDeclaration("1.0", "utf-8", "no"); doc.Declaration = declaration; dlineageRelation = new XElement("dlineageRelation"); doc.Add(dlineageRelation); if (doc != null) { appendTables(dlineage, dlineageRelation); appendProcedures(dlineage, dlineageRelation); appendColumnRelations(impactResult, dlineageRelation); appendProcedureRelations(dlineage, dlineageRelation); try { StringBuilder xmlBuffer = new StringBuilder(); using (StringWriter writer = new Utf8StringWriter(xmlBuffer)) { doc.Save(writer, SaveOptions.None); } string result = xmlBuffer.ToString().Trim(); return(result); } catch (IOException e) { Console.WriteLine(e.ToString()); Console.Write(e.StackTrace); } } return(null); }
public virtual IList <ColumnMetaData[]> collectDlineageRelations(Dlineage dlineage, columnImpactResult impactResult) { IList <ColumnMetaData[]> relations = new List <ColumnMetaData[]>(); if (dlineage == null || impactResult == null) { return(relations); } database[] dataMetaInfos = dlineage.DataMetaInfos; if (dataMetaInfos == null) { return(relations); } MetaScanner scanner = new MetaScanner(dlineage); targetColumn[] targetColumns = impactResult.columns; if (impactResult != null && targetColumns != null) { for (int z = 0; z < targetColumns.Length; z++) { targetColumn target = targetColumns[z]; if (target.linkTables != null && target.columns != null) { linkTable[] links = target.linkTables; for (int i = 0; i < links.Length; i++) { linkTable link = links[i]; for (int j = 0; j < target.columns.Length; j++) { sourceColumn source = target.columns[j]; if ("true".Equals(source.orphan)) { continue; } if (!string.ReferenceEquals(source.clause, null)) { if ("select".Equals(link.type, StringComparison.CurrentCultureIgnoreCase)) { if (!"select".Equals(source.clause, StringComparison.CurrentCultureIgnoreCase)) { continue; } } if ("view".Equals(link.type, StringComparison.CurrentCultureIgnoreCase)) { if (!"select".Equals(source.clause, StringComparison.CurrentCultureIgnoreCase)) { continue; } } if ("insert".Equals(link.type, StringComparison.CurrentCultureIgnoreCase)) { if (!"select".Equals(source.clause, StringComparison.CurrentCultureIgnoreCase)) { continue; } } if ("update".Equals(link.type, StringComparison.CurrentCultureIgnoreCase)) { if (!"assign".Equals(source.clause, StringComparison.CurrentCultureIgnoreCase) && !"select".Equals(source.clause, StringComparison.CurrentCultureIgnoreCase)) { continue; } } if ("merge".Equals(link.type, StringComparison.CurrentCultureIgnoreCase)) { if (!"assign".Equals(source.clause, StringComparison.CurrentCultureIgnoreCase) && !"select".Equals(source.clause, StringComparison.CurrentCultureIgnoreCase)) { continue; } } } string sourceTableName = null; if (!string.ReferenceEquals(source.tableOwner, null) && !"unknown".Equals(source.tableOwner, StringComparison.CurrentCultureIgnoreCase)) { sourceTableName = source.tableOwner + "." + source.tableName; } else { sourceTableName = source.tableName; } ColumnMetaData sourceColumn = scanner.getColumnMetaData(sourceTableName + "." + source.name); string targetTableName = null; if (!string.ReferenceEquals(link.tableOwner, null) && !"unknown".Equals(link.tableOwner, StringComparison.CurrentCultureIgnoreCase)) { targetTableName = link.tableOwner + "." + link.tableName; } else { targetTableName = link.tableName; } ColumnMetaData targetColumn = scanner.getColumnMetaData(targetTableName, link.name); if (sourceColumn != null && targetColumn != null) { relations.Add(new ColumnMetaData[] { targetColumn, sourceColumn }); } else { if (sourceColumn == null) { Console.Error.WriteLine(sourceTableName + "." + source.name + " should not be null."); } if (targetColumn == null) { Console.Error.WriteLine(targetTableName + "." + link.name + " should not be null."); } } } } } } } return(relations); }
public static void Main_dlineageRelation(string[] args) { if (args.Length < 1) { Console.WriteLine("Usage: DlineageRelation [/f <path_to_sql_file>] [/d <path_to_directory_includes_sql_files>] [/t <database type>] [/o <output file path>]"); Console.WriteLine("/f: Option, specify the sql file path to analyze dlineage relation."); Console.WriteLine("/d: Option, specify the sql directory path to analyze dlineage relation."); Console.WriteLine("/t: Option, set the database type. Support oracle, mysql, mssql, db2, netezza, teradata, informix, sybase, postgresql, hive, greenplum and redshift, the default type is oracle"); Console.WriteLine("/o: Option, write the output stream to the specified file."); return; } FileInfo sqlFiles = null; IList <string> argList = new List <string>(args); if (argList.IndexOf("/f") != -1 && argList.Count > argList.IndexOf("/f") + 1) { sqlFiles = new FileInfo(args[argList.IndexOf("/f") + 1]); if (!sqlFiles.Exists || sqlFiles.Attributes == FileAttributes.Directory) { Console.WriteLine(sqlFiles + " is not a valid file."); return; } } else if (argList.IndexOf("/d") != -1 && argList.Count > argList.IndexOf("/d") + 1) { sqlFiles = new FileInfo(args[argList.IndexOf("/d") + 1]); if (sqlFiles.Attributes != FileAttributes.Directory) { Console.WriteLine(sqlFiles + " is not a valid directory."); return; } } else { Console.WriteLine("Please specify a sql file path or directory path to analyze dlineage."); return; } EDbVendor vendor = EDbVendor.dbvoracle; int index = argList.IndexOf("/t"); if (index != -1 && args.Length > index + 1) { if (args[index + 1].Equals("mssql", StringComparison.CurrentCultureIgnoreCase)) { vendor = EDbVendor.dbvmssql; } else if (args[index + 1].Equals("db2", StringComparison.CurrentCultureIgnoreCase)) { vendor = EDbVendor.dbvdb2; } else if (args[index + 1].Equals("mysql", StringComparison.CurrentCultureIgnoreCase)) { vendor = EDbVendor.dbvmysql; } else if (args[index + 1].Equals("netezza", StringComparison.CurrentCultureIgnoreCase)) { vendor = EDbVendor.dbvnetezza; } else if (args[index + 1].Equals("teradata", StringComparison.CurrentCultureIgnoreCase)) { vendor = EDbVendor.dbvteradata; } else if (args[index + 1].Equals("oracle", StringComparison.CurrentCultureIgnoreCase)) { vendor = EDbVendor.dbvoracle; } else if (args[index + 1].Equals("informix", StringComparison.CurrentCultureIgnoreCase)) { vendor = EDbVendor.dbvinformix; } else if (args[index + 1].Equals("sybase", StringComparison.CurrentCultureIgnoreCase)) { vendor = EDbVendor.dbvsybase; } else if (args[index + 1].Equals("postgresql", StringComparison.CurrentCultureIgnoreCase)) { vendor = EDbVendor.dbvpostgresql; } else if (args[index + 1].Equals("hive", StringComparison.CurrentCultureIgnoreCase)) { vendor = EDbVendor.dbvhive; } else if (args[index + 1].Equals("greenplum", StringComparison.CurrentCultureIgnoreCase)) { vendor = EDbVendor.dbvgreenplum; } else if (args[index + 1].Equals("redshift", StringComparison.CurrentCultureIgnoreCase)) { vendor = EDbVendor.dbvredshift; } } string outputFile = null; index = argList.IndexOf("/o"); if (index != -1 && args.Length > index + 1) { outputFile = args[index + 1]; } System.IO.FileStream writer = null; StreamWriter sw = null; if (!string.ReferenceEquals(outputFile, null)) { try { writer = new System.IO.FileStream(outputFile, System.IO.FileMode.Create, System.IO.FileAccess.Write); sw = new StreamWriter(writer); Console.SetOut(sw); } catch (FileNotFoundException e) { Console.WriteLine(e.ToString()); Console.Write(e.StackTrace); } } DlineageRelation relation = new DlineageRelation(); Dlineage dlineage = new Dlineage(sqlFiles, vendor, false, false); StringBuilder errorBuffer = new StringBuilder(); columnImpactResult impactResult = relation.generateColumnImpact(dlineage, errorBuffer); string result = relation.generateDlineageRelation(dlineage, impactResult); if (!string.ReferenceEquals(result, null)) { Console.WriteLine(result); if (writer != null) { Console.Error.WriteLine(result); } } if (errorBuffer.Length > 0) { Console.Error.WriteLine("Error log:\n" + errorBuffer.ToString()); } try { if (sw != null && writer != null) { sw.Close(); writer.Close(); } } catch (IOException e) { Console.WriteLine(e.ToString()); Console.Write(e.StackTrace); } }
private void appendColumnRelations(columnImpactResult impactResult, Element dlineageRelation) { targetColumn[] targetColumns = impactResult.columns; if (impactResult != null && targetColumns != null) { for (int z = 0; z < targetColumns.Length; z++) { targetColumn target = targetColumns[z]; if (target.linkTables != null && target.columns != null) { linkTable[] links = target.linkTables; for (int i = 0; i < links.Length; i++) { linkTable link = links[i]; for (int j = 0; j < target.columns.Length; j++) { sourceColumn source = target.columns[j]; if ("true".Equals(source.orphan)) { continue; } if (!string.ReferenceEquals(source.clause, null)) { if ("select".Equals(link.type, StringComparison.CurrentCultureIgnoreCase)) { if (!"select".Equals(source.clause, StringComparison.CurrentCultureIgnoreCase)) { continue; } } if ("view".Equals(link.type, StringComparison.CurrentCultureIgnoreCase)) { if (!"select".Equals(source.clause, StringComparison.CurrentCultureIgnoreCase)) { continue; } } if ("insert".Equals(link.type, StringComparison.CurrentCultureIgnoreCase)) { if (!"select".Equals(source.clause, StringComparison.CurrentCultureIgnoreCase)) { continue; } } if ("update".Equals(link.type, StringComparison.CurrentCultureIgnoreCase)) { if (!"assign".Equals(source.clause, StringComparison.CurrentCultureIgnoreCase) && !"select".Equals(source.clause, StringComparison.CurrentCultureIgnoreCase)) { continue; } } if ("merge".Equals(link.type, StringComparison.CurrentCultureIgnoreCase)) { if (!"assign".Equals(source.clause, StringComparison.CurrentCultureIgnoreCase) && !"select".Equals(source.clause, StringComparison.CurrentCultureIgnoreCase)) { continue; } } } Element relationNode = new Element("relation"); Element sourceNode = new Element("source"); sourceNode.Add(new XAttribute("column", source.name)); sourceNode.Add(new XAttribute("coordinate", source.coordinate)); if (!string.ReferenceEquals(source.tableOwner, null) && !"unknown".Equals(source.tableOwner, StringComparison.CurrentCultureIgnoreCase)) { sourceNode.Add(new XAttribute("table", source.tableOwner + "." + source.tableName)); } else { sourceNode.Add(new XAttribute("table", source.tableName)); } Element targetNode = new Element("target"); targetNode.Add(new XAttribute("column", link.name)); if (!string.ReferenceEquals(target.aliasCoordinate, null)) { targetNode.Add(new XAttribute("coordinate", target.aliasCoordinate)); } else { targetNode.Add(new XAttribute("coordinate", link.coordinate)); } if (!string.ReferenceEquals(link.tableOwner, null) && !"unknown".Equals(link.tableOwner, StringComparison.CurrentCultureIgnoreCase)) { targetNode.Add(new XAttribute("table", link.tableOwner + "." + link.tableName)); } else { targetNode.Add(new XAttribute("table", link.tableName)); } relationNode.Add(sourceNode); relationNode.Add(targetNode); bool append = true; IEnumerator <Element> iter = dlineageRelation.Elements().GetEnumerator(); while (iter.MoveNext()) { if (iter.Current.Equals(relationNode)) { append = false; break; } } if (append) { dlineageRelation.Add(relationNode); } } } } } } }
public static void Main(string[] args) { IList <string> argList = new List <string>(args); if (args.Length < 1 || (argList.IndexOf("/d") == -1 && argList.IndexOf("/f") == -1)) { Console.WriteLine("Usage: getTableColumn [/f <path_of_sql_file>] [/d <path_to_directory_includes_sql_files>] [/o <path_to_directory_table_columns_result>] [/t <database type>]"); Console.WriteLine("/f: specify the single sql file to analyze table columns."); Console.WriteLine("/d: specify the sql directory path to analyze table columns."); Console.WriteLine("/o: Option, write the output result to the specified directory."); Console.WriteLine("/t: Option, set the database type. Support oracle, mysql, mssql, db2, netezza, teradata, informix, sybase, postgresql, hive, greenplum and redshift, the default type is oracle"); return; } FileInfo sqlFiles = null; FileInfo sqlFile = null; FileInfo outputDir = null; if (argList.IndexOf("/f") != -1 && argList.Count > argList.IndexOf("/f") + 1) { sqlFile = new FileInfo(args[argList.IndexOf("/f") + 1]); if (sqlFile.Attributes.HasFlag(FileAttributes.Directory)) { Console.WriteLine(sqlFiles + " is not a valid file."); return; } } if (argList.IndexOf("/d") != -1 && argList.Count > argList.IndexOf("/d") + 1) { sqlFiles = new FileInfo(args[argList.IndexOf("/d") + 1]); if (!sqlFiles.Attributes.HasFlag(FileAttributes.Directory)) { Console.WriteLine(sqlFiles + " is not a valid directory."); return; } } if (argList.IndexOf("/o") != -1 && argList.Count > argList.IndexOf("/o") + 1) { outputDir = new FileInfo(args[argList.IndexOf("/o") + 1]); if (!outputDir.Attributes.HasFlag(FileAttributes.Directory)) { Console.WriteLine(outputDir + " is not a valid directory."); return; } } string outputFile = null; string errorFile = null; if (sqlFiles != null) { if (outputDir != null) { outputFile = outputDir.FullName + "\\tableColumns.txt"; errorFile = outputDir.FullName + "\\error.txt"; } else { outputFile = ".\\tableColumns.txt"; errorFile = ".\\error.txt"; } } else if (sqlFile != null) { String fileName = sqlFile.FullName; int index = fileName.LastIndexOf('.'); if (index != -1) { outputFile = fileName.Substring(0, index) + ".out"; } else { outputFile += ".out"; } errorFile = outputFile; } System.IO.FileStream writer = null; StreamWriter sw = null; if (!string.ReferenceEquals(outputFile, null)) { try { writer = new System.IO.FileStream(outputFile, System.IO.FileMode.Create, System.IO.FileAccess.Write); sw = new StreamWriter(writer); Console.SetOut(sw); } catch (FileNotFoundException e) { Console.WriteLine(e.ToString()); Console.Write(e.StackTrace); } } StringBuilder errorBuffer = new StringBuilder(); List <FileInfo> files = new List <FileInfo>(); if (sqlFiles != null) { getFiles(sqlFiles, files); } else if (sqlFile != null) { files.Add(sqlFile); } bool isOver = false; StringBuilder buffer = new StringBuilder(); buffer.Append("Schama,Table,Column,File\r\n"); int count = 0; for (int i = 0; i < files.Count; i++) { if (count >= 30) { isOver = true; break; } try { StringBuilder errorMessage = new StringBuilder(); DlineageCommon dlineage = new DlineageCommon(files[i], Common.GetEDbVendor(args), false, false); columnImpactResult impactResult = dlineage.generateColumnImpact(errorMessage); getTableColumn relation = new getTableColumn(); string result = relation.getTableColumns(files[i], dlineage); if (result != null) { buffer.Append(result); } if (errorMessage.Length > 0) { errorBuffer.AppendLine(files[i].Name + ":\r\n" + errorMessage); if (errorMessage.ToString().IndexOf("syntax error") == -1) { count += 1; } } else { count += 1; } } catch (Exception e) { errorBuffer.AppendLine(files[i].Name + ":\r\n" + e.Message + "\r\n" + e.StackTrace); } } Console.Write(buffer.ToString()); try { if (sw != null && writer != null) { sw.Close(); writer.Close(); } } catch (IOException e) { Console.WriteLine(e.ToString()); Console.Write(e.StackTrace); } if (isOver) { errorBuffer.Insert(0, OverWarning + "\r\n"); } if (errorBuffer.Length > 0) { Console.Error.WriteLine("Error log:\n" + errorBuffer.ToString()); string log = errorBuffer.ToString().Replace(OverWarning, "").Trim(); if (log.Length > 0 && !string.ReferenceEquals(errorFile, null)) { try { writer = new System.IO.FileStream(errorFile, System.IO.FileMode.Create, System.IO.FileAccess.Write); sw = new StreamWriter(writer); sw.Write(log); sw.Close(); writer.Close(); } catch (FileNotFoundException e) { Console.WriteLine(e.ToString()); Console.Write(e.StackTrace); } } } }
public static void Main(string[] args) { if (args.Length < 1) { Console.WriteLine("Usage: DlineageRelation [/f <path_to_sql_file>] [/d <path_to_directory_includes_sql_files>] [/t <database type>] [/o <output file path>]"); Console.WriteLine("/f: Option, specify the sql file path to analyze dlineage relation."); Console.WriteLine("/d: Option, specify the sql directory path to analyze dlineage relation."); Console.WriteLine("/t: Option, set the database type. Support oracle, mysql, mssql, db2, netezza, teradata, informix, sybase, postgresql, hive, greenplum and redshift, the default type is oracle"); Console.WriteLine("/o: Option, write the output stream to the specified file."); Console.WriteLine("/log: Option, generate a dlineage.log file to log information."); return; } FileInfo sqlFiles = null; IList <string> argList = new List <string>(args); if (argList.IndexOf("/f") != -1 && argList.Count > argList.IndexOf("/f") + 1) { sqlFiles = new FileInfo(args[argList.IndexOf("/f") + 1]); if (!sqlFiles.Exists || sqlFiles.Attributes.HasFlag(FileAttributes.Directory)) { Console.WriteLine(sqlFiles + " is not a valid file."); return; } } else if (argList.IndexOf("/d") != -1 && argList.Count > argList.IndexOf("/d") + 1) { sqlFiles = new FileInfo(args[argList.IndexOf("/d") + 1]); if (!sqlFiles.Attributes.HasFlag(FileAttributes.Directory)) { Console.WriteLine(sqlFiles + " is not a valid directory."); return; } } string outputFile = null; int index = argList.IndexOf("/o"); if (index != -1 && args.Length > index + 1) { outputFile = args[index + 1]; } System.IO.FileStream writer = null; StreamWriter sw = null; if (!string.ReferenceEquals(outputFile, null)) { try { writer = new System.IO.FileStream(outputFile, System.IO.FileMode.Create, System.IO.FileAccess.Write); sw = new StreamWriter(writer); Console.SetOut(sw); } catch (FileNotFoundException e) { Console.WriteLine(e.ToString()); Console.Write(e.StackTrace); } } DlineageCommon dlineage; if (sqlFiles != null) { dlineage = new DlineageCommon(sqlFiles, Common.GetEDbVendor(args), false, false); } else { string sqltext = @"SELECT e.last_name AS name, e.commission_pct comm, e.salary * 12 ""Annual Salary"" FROM scott.employees AS e WHERE e.salary > 1000 or 1=1 ORDER BY e.first_name, e.last_name;"; dlineage = new DlineageCommon(sqltext, Common.GetEDbVendor(args), false, false); } StringBuilder errorBuffer = new StringBuilder(); columnImpactResult impactResult = dlineage.generateColumnImpact(errorBuffer); DlineageRelation relation = new DlineageRelation(); string result = relation.generateDlineageRelation(dlineage, impactResult); bool log = argList.IndexOf("/log") != -1; TextWriter pw = null; StringBuilder errsw = null; TextWriter systemSteam = Console.Error; try { errsw = new StringBuilder(); pw = new StringWriter(errsw); Console.SetError(pw); } catch (Exception e) { Console.WriteLine(e.ToString()); Console.Write(e.StackTrace); } if (!string.ReferenceEquals(result, null)) { Console.WriteLine(result); if (writer != null) { Console.Error.WriteLine(result); } } if (errorBuffer.Length > 0) { Console.Error.WriteLine("Error log:\n" + errorBuffer.ToString()); } try { if (sw != null && writer != null) { sw.Close(); writer.Close(); } } catch (IOException e) { Console.WriteLine(e.ToString()); Console.Write(e.StackTrace); } if (pw != null) { pw.Close(); } if (errsw != null) { string errorMessage = errsw.ToString().Trim(); if (errorMessage.Length > 0) { if (log) { try { pw = new StreamWriter(new FileInfo("./dlineageRelation.log").FullName); pw.WriteLine(errorMessage); pw.Close(); } catch (FileNotFoundException e) { Console.WriteLine(e.ToString()); Console.Write(e.StackTrace); } } Console.SetError(systemSteam); Console.Error.WriteLine(errorMessage); } } }
public static void Main(string[] args) { if (args.Length < 1) { Console.WriteLine("Usage: Dlineage [/f <path_to_sql_file>] [/d <path_to_directory_includes_sql_files>] [/t <database type>] [/fo <table column>] [/b <view column>] [/ddl] [/s] [/log]"); Console.WriteLine("/f: Option, specify the sql file path to analyze dlineage."); Console.WriteLine("/d: Option, specify the sql directory path to analyze dlineage."); Console.WriteLine("/d: Option, forward analyze the specified table column."); Console.WriteLine("/t: Option, set the database type. Support oracle, mysql, mssql, db2, netezza, teradata, informix, sybase, postgresql, hive, greenplum and redshift, the default type is oracle"); Console.WriteLine("/fo: Option, forward analyze the specified table column."); Console.WriteLine("/b: Option, backward analyze the specified view column."); Console.WriteLine("/ddl: Option, output the database DDL schema."); Console.WriteLine("/s: Option, set the strict match mode. It will match the catalog name and schema name."); Console.WriteLine("/log: Option, generate a dlineage.log file to log information."); return; } FileInfo sqlFiles = null; IList <string> argList = new List <string>(args); if (argList.IndexOf("/f") != -1 && argList.Count > argList.IndexOf("/f") + 1) { sqlFiles = new FileInfo(args[argList.IndexOf("/f") + 1]); if (!sqlFiles.Exists || sqlFiles.Attributes == FileAttributes.Directory) { Console.WriteLine(sqlFiles + " is not a valid file."); return; } } else if (argList.IndexOf("/d") != -1 && argList.Count > argList.IndexOf("/d") + 1) { sqlFiles = new FileInfo(args[argList.IndexOf("/d") + 1]); if (sqlFiles.Attributes != FileAttributes.Directory) { Console.WriteLine(sqlFiles + " is not a valid directory."); return; } } bool strict = argList.IndexOf("/s") != -1; bool log = argList.IndexOf("/log") != -1; TextWriter pw = null; StringBuilder sw = null; TextWriter systemSteam = Console.Error; try { sw = new StringBuilder(); pw = new StringWriter(sw); Console.SetError(pw); } catch (Exception e) { Console.WriteLine(e.ToString()); Console.Write(e.StackTrace); } DlineageCommon dlineage; if (sqlFiles != null) { dlineage = new DlineageCommon(sqlFiles, Common.GetEDbVendor(args), strict, false); } else { string sqltext = @"SELECT e.last_name AS name, e.commission_pct comm, e.salary * 12 ""Annual Salary"" FROM scott.employees AS e WHERE e.salary > 1000 or 1=1 ORDER BY e.first_name, e.last_name;"; dlineage = new DlineageCommon(sqltext, Common.GetEDbVendor(args), strict, false); } bool forwardAnalyze = argList.IndexOf("/fo") != -1; bool backwardAnalyze = argList.IndexOf("/b") != -1; bool outputDDL = argList.IndexOf("/ddl") != -1; if (!forwardAnalyze && !backwardAnalyze && !outputDDL) { dlineage.columnImpact(); } else if (outputDDL) { dlineage.outputDDLSchema(); } else { columnImpactResult impactResult = dlineage.generateColumnImpact(null); IList <ColumnMetaData[]> relations = dlineage.collectDlineageRelations(impactResult); if (forwardAnalyze && argList.Count > argList.IndexOf("/fo") + 1) { string tableColumn = argList[argList.IndexOf("/fo") + 1]; dlineage.forwardAnalyze(tableColumn, relations); } if (backwardAnalyze && argList.Count > argList.IndexOf("/b") + 1) { string viewColumn = argList[argList.IndexOf("/b") + 1]; dlineage.backwardAnalyze(viewColumn, relations); } } if (pw != null) { pw.Close(); } if (sw != null) { string errorMessage = sw.ToString().Trim(); if (errorMessage.Length > 0) { if (log) { try { pw = new StreamWriter(new FileInfo("./dlineage.log").FullName); pw.WriteLine(errorMessage); pw.Close(); } catch (FileNotFoundException e) { Console.WriteLine(e.ToString()); Console.Write(e.StackTrace); } } Console.SetError(systemSteam); Console.Error.WriteLine(errorMessage); } } }