Error handling in DTS Package execution using .NET - c#

I am executing a SQL Server 2000 DTS package using C# by following the code from this article http://support.microsoft.com/kb/319985. once the package is executed I am looping through each step to find out if any step has failed and get info about error if it has failed. I also use this information to find out if the package has succeeded or not (package failed if anyone step has failed).
the issue I am facing here is that sometimes the package fails (jumps to catch block) with a generic error message that "Execution was canceled by user" and doesn't give any more information than that. If I run the package manually using the DTSRUNUI then I found that the package was expecting a text file as an input and the file didn't exist in the specified location. in that case the error message from .NET code should say that clearly. do I need to make any changes to the code from the article, to get more details about the errors. I added the following extra to get error information, but didn't help much. there are two properties called "FailonError" on package and "ExecuteInMainThread" on step objects. I tried setting them as well, but that also didn't help. not sure if they are required.
bool success = true;
if (package != null)
{
foreach (Step step in package.Steps)
{
if (step.ExecutionStatus == DTSStepExecStatus.DTSStepExecStat_Completed
&& step.ExecutionResult == DTSStepExecResult.DTSStepExecResult_Failure)
{
int errorCode, helpContext;
string errorSource, errorDescription, helpFile, iDofInterfaceWithError;
step.GetExecutionErrorInfo(out errorCode, out errorSource, out errorDescription, out helpFile,
out helpContext, out iDofInterfaceWithError);
LogToTextFile(
string.Format(
"step name: {0} error Code : {1}, error Source : {2}, error Description: {3}", step.Name,
errorCode, errorSource, errorDescription));
success = false;
}
}
}

I am using DTSRun.EXE to execute the DTS package (by launching the process from C#) and redirecting its console output to the file and that output is normally sufficient in case of any errors.

Related

"Runtime error Exception has been thrown by the target of an invocation" from Script task

I have a SSIS package with a script task, I get the following error when i try to run it in my local system. It works fine for my collegues as well as in production. However, I am not able to run it locally, to test. I keep a debug point in the main method, but it is never reached, I get the error before it goes to main method.
I am using VS 2010, .Net framework 4.5.
The script task does compile. I get the following messages SSIS package "..\Test.dtsx" starting. Error: 0x1 at Test: Exception has been thrown by the target of an invocation. Task failed: Test SSIS package "..\Test.dtsx" finished: Success. The program '[2552] DtsDebugHost.exe: DTS' has exited with code 0 (0x0).
The following is the code:
public void Main()
{
try
{
LogMessages("Update Bug package execution started at :: " + DateTime.Now.ToLongTimeString());
LogMessages("Loading package configuration values to local variables.");
strDBConn = Dts.Variables["User::DBConnection"] != null ? Dts.Variables["User::DBConnection"].Value.ToString() : string.Empty;
strTPCUrl = Dts.Variables["User::TPCUrl"] != null ? Dts.Variables["User::TPCUrl"].Value.ToString() : string.Empty;
TfsTeamProjectCollection objTPC = new TfsTeamProjectCollection(new Uri(strTPCUrl));
WorkItemStore objWIS = new WorkItemStore(objTPC);
WorkItemCollection objWIC = objWIS.Query("SELECT...");
foreach (WorkItem wi in objWIC)
{
}
}
catch(Exception ex)
{
}
When I commented the code from TfsTeamProjectCollection objTPC = new TfsTeamProjectCollection(new Uri(strTPCUrl)); The script executes successfully. However, if i keep TfsTeamProjectCollection objTPC = new TfsTeamProjectCollection(new Uri(strTPCUrl)); and comment the rest, i get the exception.
I do have access to the URL.
I am using Microsoft.TeamFoundation.Client.dll and Microsoft.TeamFoundation.WorkItemTracking.Client.dll, in my script task. However the dll version in the package is 10.0, and the version of the dll in my GAC is 12.0. Would that cause a problem?
I had the same Problem (i.e. the same error code Error: 0x1 ...).
The issue was with some of the libraries referenced from a missing folder.
Removing the references and adding them back from the correct path fixed the issue.
The Microsoft Reference (https://msdn.microsoft.com/en-us/library/ms345164.aspx) related to the Error code is very generic and doesn't help you much.
However, reading other articles it is quite likely it indicates an unknown failure reason to run the Script Task.
Hexadecimal code: 0x1
Decimal Code: 1
Symbolic Name: DTS_MSG_CATEGORY_SERVICE_CONTROL
Description: Incorrect function.
I got this error message when I referred to a passed ssis variable in Dts.Variables["User::xxxx].Value(); where xxxx did not exist and was not passed from the calling program. It was a simple Console.Writeline referring to a passed variable that didn't exist.
I fixed this error by changing the TargetServerVersion of the SSIS Project.
Integration Services Project Property Pages
This is just a different situation and not intended to be the end all be all solution for everyone.
When I was installing my DLLs into the GAC I forgot to run my script as Administrator and the script ran silently without error as though it was working.
I felt really dumb when I realized that's what I did wrong. Hopefully this can help prevent other people from wasting time on something so silly.
For reference this is what I use for installing my DLLs into the GAC and I modified it to tell me when I am not running it as Administrator now:
#https://superuser.com/questions/749243/detect-if-powershell-is-running-as-administrator
$isAdmin = ([Security.Principal.WindowsPrincipal] `
[Security.Principal.WindowsIdentity]::GetCurrent() `
).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
if($isAdmin -eq $false)
{
Write-Host "You have to run this script as Administrator or it just won't work!" -ForegroundColor Red
return;
}
$strDllPath = "C:\PathToYourDllsHere\"
#Note that you should be running PowerShell as an Administrator
[System.Reflection.Assembly]::Load("System.EnterpriseServices, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")
$publish = New-Object System.EnterpriseServices.Internal.Publish
$arr = #(
"YourDLL01.dll",
"YourDLL02.dll",
"YourDLL03.dll"
)
get-date
foreach($d in $arr)
{
$p = ($strDllPath + $d);
$p
$publish.GacInstall($p);
}
#If installing into the GAC on a server hosting web applications in IIS, you need to restart IIS for the applications to pick up the change.
#Uncomment the next line if necessary...
#iisreset
Credit for how to determine if your PowerShell script is running in Admin mode or not:
https://superuser.com/questions/749243/detect-if-powershell-is-running-as-administrator
In my case it was missing DLLs or not having the correct version installed on the server.
Locally all tests were fine but on the server the error message Runtime error Exception has been thrown by the target of an invocation kept popping up.
No exception handler would be able to catch that error - the code in the script task would not even be executed, as soon as a DLL would be needed, that is not in the assembly cache on the server (it could happen on a local machine as well, with the same error).
The difficulty here is finding out what is missing and then either update the references to the correct version or install the missing DLL in the assembly cache with gacutil. The way I approached the debugging was to remove parts of the code in the script task until that error wouldn't appear, then analyze the missing part for references.
After not having any luck with the other answers here, I finally found that in my package, the problem was that I had created a new variable but not carried its name across into my new copy of the C# script. The variables were the ones to be used as connection string expressions. So it was ultimately a matter of changing:
Dts.Variables["Exists"].Value = File.Exists(Dts.Variables["OldSSISPackageVariableName"].Value.ToString());
to:
Dts.Variables["Exists"].Value = File.Exists(Dts.Variables["NewSSISPackageVariableName"].Value.ToString());
Once I kept them in sync, it worked fine.
Its fixed, when added reference to dll version 12.0.0 and changed Target Framework to .Net Framework 4.5
My problem was that I, in the script task, tried to fetch data like this:
public void Main()
{
using (var connection = Dts.Connections["localhost.Test"].AcquireConnection(Dts.Transaction) as SqlConnection)
{
connection.Open();
var command = new SqlCommand("select * from Table;", connection);
var reader = command.ExecuteReader();
while (reader.Read())
{
MessageBox.Show($"{reader[0]} {reader[1]} {reader[2]}");
}
}
Dts.TaskResult = (int)ScriptResults.Success;
}
However, my connection is of the type OLE DB, and therefore I needed to connect to it like this instead:
public void Main()
{
var connectionString = Dts.Connections["localhost.Test"].ConnectionString;
using (var connection = new OleDbConnection(connectionString))
{
connection.Open();
var command = new OleDbCommand("select * Table;", connection);
var reader = command.ExecuteReader();
while (reader.Read())
{
MessageBox.Show($"{reader[0]} {reader[1]} {reader[2]}");
}
}
Dts.TaskResult = (int)ScriptResults.Success;
}
Notice that I'm using OleDbConnection here.
For me what fixed the issue was updating the string parameter I passed to the script. it was missing "" at the end of the path (i.e. "e:\arcive" - needed to add "" at the end)

NullPointerException with MR2 in windows

I have installed Hadoop 2.3.0 in windows and able to execute MR jobs successfully. But while trying with streaming sample in C# [with HadoopSDK's .Net assemblies] the app ends with the following exception
14/05/16 18:21:06 INFO mapreduce.Job: Task Id : attempt_1400239892040_0003_r_000000_0, Status : FAILED
Error: java.lang.NullPointerException
at org.apache.hadoop.mapred.Task.getFsStatistics(Task.java:347)
at org.apache.hadoop.mapred.ReduceTask$OldTrackingRecordWriter.<init>(ReduceTask.java:478)
at org.apache.hadoop.mapred.ReduceTask.runOldReducer(ReduceTask.java:414)
at org.apache.hadoop.mapred.ReduceTask.run(ReduceTask.java:392)
at org.apache.hadoop.mapred.YarnChild$2.run(YarnChild.java:168)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.Subject.doAs(Subject.java:415)
at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1548)
at org.apache.hadoop.mapred.YarnChild.main(YarnChild.java:163)
Update:
I was able to drill down the problem and found that the exception raised in the following line
matchedStats = getFsStatistics(FileOutputFormat.getOutputPath(job), job);
at org.apache.hadoop.mapred.ReduceTask$OldTrackingRecordWriter.<init>(ReduceTask.java:478)
In the above, the result of 'FileOutputFormat.getOutputPath(job)' returns null, which throws the null pointer exception. Below are the codes for the getOutputPath() function.
public static final String OUTDIR = "mapreduce.output.fileoutputformat.outputdir";
public static Path getOutputPath(JobConf conf) {
String name = conf.get(org.apache.hadoop.mapreduce.lib.output.
FileOutputFormat.OUTDIR);
return name == null ? null: new Path(name);
}
So Is it needed to set value for property "mapreduce.output.fileoutputformat.outputdir" anywhere in the configuration files to get this issue resolved?
Thanks
The problem is that the hadoop services have been started from a different user [SYSTEM in my case] and the mapreduce sample was submitted from my local user. So this makes the issue by returning the FileSystem statistics [for the local user] as Null.
Once i started Hadoop from my local user, the above issue gets resolved.

Calling PowerShell cmdlet from C# throws CommandNotFoundException

I'm trying to call the Add-AppxPackage cmdlet from C#. I found the MSDN article on running PowerShell from C# code. I have referenced the System.Management.Automation assembly and have tried the following code snippets, all of which result in the same exception when trying to call powerShell.Invoke():
System.Management.Automation.CommandNotFoundException was unhandled
The term 'Add-AppxPackage' is not recognized as the name of a cmdlet,
function, script file, or operable program. Check the spelling of the
name, or if a path was included, verify that the path is correct and
try again.
Snippet 1:
var powerShell = PowerShell.Create();
powerShell.AddCommand(string.Format("Add-AppxPackage '{0}'", appxFilePath));
foreach (PSObject result in powerShell.Invoke())
{
Console.WriteLine(result);
}
I understand why this doesn't work, since I shouldn't be providing parameters in the AddCommand() function.
Snippet 2:
var powerShell = PowerShell.Create();
powerShell.AddCommand("Add-AppxPackage");
powerShell.AddParameter("Path", appxFilePath);
foreach (PSObject result in powerShell.Invoke())
{
Console.WriteLine(result);
}
Snippet 3:
var powerShell = PowerShell.Create();
powerShell.AddCommand("Add-AppxPackage");
powerShell.AddArgument(appxFilePath);
foreach (PSObject result in powerShell.Invoke())
{
Console.WriteLine(result);
}
My C# project targets .Net 4.5, and if I do powerShell.AddCommand("Get-Host") it works and the Version it returns back is 4.0. Add-AppxPackage was added in v3.0 of PowerShell, so the command should definitely exist, and it works fine if I manually run this command from the Windows PowerShell command prompt.
Any ideas what I am doing wrong here? Any suggestions are appreciated.
-- Update --
I found this post and this one, and realized there is a AddScript() function, so I tried this:
Snippet 4:
var powerShell = PowerShell.Create();
powerShell.AddScript(string.Format("Add-AppxPackage '{0}'", appxFilePath));
var results = powerShell.Invoke();
foreach (PSObject result in results)
{
Console.WriteLine(result);
}
And it does not throw an exception, but it also doesn't install the metro app, and the "results" returned from powerShell.Invoke() are empty, so I'm still at a loss...
-- Update 2 --
So I decided that I would try just creating a new PowerShell process to run my command, so I tried this:
Process.Start(new ProcessStartInfo("PowerShell", string.Format("-Command Add-AppxPackage '{0}'; $key = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyUp')", appxFilePath)));
but it still throws the same error that Add-AppxPackage is not a recognized cmdlet.
ANSWER
If you follow the long comment thread on robert.westerlund's answer, you will see that for some reason when running/launched from Visual Studio, PowerShell was not including all of the PSModulePaths that it does when running straight from a PowerShell command prompt, so many modules are not present. The solution was to find the absolute path of the module that I needed (the appx module in my case) using:
(Get-Module appx -ListAvailable).Path
And then import that module before trying to call one of its cmdlets. So this is the C# code that worked for me:
var powerShell = PowerShell.Create();
powerShell.AddScript(string.Format(#"Import-Module 'C:\WINDOWS\system32\WindowsPowerShell\v1.0\Modules\Appx\Appx.psd1'; Add-AppxPackage '{0}'", appxFilePath));
var results = powerShell.Invoke();
UPDATED ANSWER
You can see from this other post I opened, that the problem was with a bug in a Visual Studio extension (in my case StudioShell) causing not all of the PSModulePaths to be loaded. After uninstalling that extension all of the modules were loaded correctly and I no longer needed to manually import the module.
In PowerShell there is a difference between terminating errors (which stops the execution) and non-terminating errors (which are just written to the error stream).
If you want to create a non-terminating error in a function of your own, just use the Write-Error cmdlet. If you want to create a terminating error, use the Throw keyword. You can read more about these concepts if you run Get-Help Write-Error, Get-Help about_Throw and Get-Help about_Try_Catch_Finally.
Using the Add-AppxPackage with a non existing package is a non terminating error and will thus be written to the error stream, but no execution halting exception will be thrown. The following code tries to add a non existing package and then writes the error to the console.
var powerShell = PowerShell.Create();
powerShell.AddScript("Add-AppxPackage NonExistingPackageName");
// Terminating errors will be thrown as exceptions when calling the Invoke method.
// If we want to handle terminating errors, we should place the Invoke call inside a try-catch block.
var results = powerShell.Invoke();
// To check if a non terminating error has occurred, test the HadErrors property
if (powerShell.HadErrors)
{
// The documentation for the Error property states that "The command invoked by the PowerShell
// object writes information to this stream whenever a nonterminating error occurs."
foreach (var error in powerShell.Streams.Error)
{
Console.WriteLine("Error: " + error);
}
}
else
{
foreach(var package in results)
{
Console.WriteLine(package);
}
}

Microsoft Diagnostics Runtime crash.dmp analysis (C#)

I'm trying to read in a crash.dmp using the functionality in Microsoft.Diagnostics.Runtime .NET componenet (also known as ClrMD).
I have a crash.dmp in a known location (in a string called pathToFile) so that's not the issue. The rest of the code looks like this.
DataTarget dataTarget = DataTarget.LoadCrashDump(pathToFile);
ClrInfo clrInfo = dataTarget.ClrVersions[0];
string dacLocation = clrInfo.TryGetDacLocation();
When testing this code, I get the following error in the command window:
Error processing directory: System.ArgumentOutOfRangeException. Index was out of range. Must be non-negative and less than the size of the collection. Parameter name: index.
I'm assuming it's something to do with the ClrVersions[0] bit but can't for the life of me pin it down.
Any help would be appreciated.
Current Status
When running the following command (which fails)
ClrRuntime rt = dataTarget.CreateRuntime("path\to\mscordawks.dll");
I receive the following error in cmd
mismatched architecture between this process and the dac
Cheers
Anyone?
If the TryGetDacLocation succeeded then you should be able to do
ClrRuntime rt = dataTarget.CreateRuntime(dacLocation);
so you get the correct dacLocation.
Was the dump you are analysing generated on same machine where you are analysing it?
Also what are the bitnesses of the process the dump was generated from, the process in which the CLRMD code is running and the debugger utility used to generate the dump?
Generally you want to be matching the bitnesses all round (x86/x64).
Doug
I was having the same issue reading a dump file generated on the same computer. There were two problems, first bitness (should have been 64, was running in 32) and the second harder problem that the proper DLL could not be located. To fix the second problem I created a method that tries all of the properly named DLLs it can find:
private static ClrRuntime GetRuntime(DataTarget target)
{
ClrInfo version = target.ClrVersions[0];
string dacLocation = version.TryGetDacLocation();
// If we don't have the dac installed, we will use the long-name dac in the same folder.
if (!string.IsNullOrEmpty(dacLocation))
dacLocation = version.DacInfo.FileName;
try // try the one it should be
{
return target.CreateRuntime(dacLocation);
}
catch (Exception e)
{
}
// can't find the one it should be, try'em all
string fileName = "mscordacwks.dll";
string[] searchLocations = new[]
{
#"C:\Windows\Microsoft.NET\",
#"C:\Windows\winsxs\"
};
foreach (string searchLocation in searchLocations)
{
foreach (string file in Directory.GetFiles(searchLocation, fileName, SearchOption.AllDirectories))
{
try
{
return target.CreateRuntime(file);
}
catch (Exception e)
{
}
}
}
throw new Exception("No found valid runtimes");
}
I followed this artificial to get the mscordacwks.dll when dealing with platform differences between where the dmp file was taken and the machine doing the analysis.
http://chentiangemalc.wordpress.com/2014/04/16/obtaining-correct-mscordacwks-dll-for-net-windbging/#comment-3380
and followed the steps including renaming the file to include the architecture and version information.
After that I just http://chentiangemalc.wordpress.com/2014/04/16/obtaining-correct-mscordacwks-dll-for-net-windbging/#comment-3380ut the full path of the file as dacLocation in the script.
After that it worked!
I suspect that putting it on the path could be made to work.

OAuth 2.0 inconsistent errors when using BigQuery commandline tool

I'm using BigQuery's command-line tool to load data into BigQuery.
I'm running the bq tool through a C# program using the following method:
private void RunShellCmd(string cmd, string args)
{
ProcessStartInfo start = new ProcessStartInfo
{
FileName = cmd,
Arguments = args,
UseShellExecute = false,
RedirectStandardOutput = true
};
using (Process process = Process.Start(start))
{
using (StreamReader reader = process.StandardOutput)
{
string result = reader.ReadToEnd();
if (OnMessage != null)
{
OnMessage(result);
}
}
}
}
Where cmd is the path for the bq script tool and args are:
load --nosync --credential_file=_CRED_PATH_ --source_format=NEWLINE_DELIMITED_JSON --project_id=_PROJECT_ID_ _TABLE_URI_ _DATA_FILE_
When performing the exact command from shell, it works perfectly.
However, through the C# program, I'm getting the following output:
Welcome to BigQuery! This script will walk you through the process of initializing your .bigqueryrc configuration file.
First, we need to set up your credentials if they do not already exist.
******************************************************************
** No OAuth2 credentials found, beginning authorization process **
******************************************************************
Go to the following link in your browser:
https://accounts.google.com/o/oauth2/auth?scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fbigquery&redirect_uri=...
Enter verification code: You have encountered a bug in the BigQuery CLI. Google engineers monitor and answer questions on Stack Overflow, with the tag google-bigquery: http://stackoverflow.com/questions/ask?tags=google-bigquery Please include a brief description of the steps that led to this issue, as well as the following information:
========================================
== Platform == CPython:2.7.5:Windows-2008ServerR2-6.1.7601-SP1
== bq version == v2.0.16
== Command line == ['C:\\Python27\\Scripts\\bq-script.py', 'load', '--nosync', '--credential_file=C:\\Users\\Administrator\\.bigquery.v2.token', '--source_format=NEWLINE_DELIMITED_JSON', '--project_id=_PROJECT_ID_',
>'_TABLE_URI_', '_DATA_FILE_PATH_']
== UTC timestamp == 2013-10-20 05:52:59
== Error trace == File "build\bdist.win32\egg\bq.py", line 783, in RunSafely
return_value = self.RunWithArgs(*args, **kwds) File "build\bdist.win32\egg\bq.py", line 2082, in RunWithArgs
client = Client.Get() File "build\bdist.win32\egg\bq.py", line 604, in Get
cls.client = Client.Create() File "build\bdist.win32\egg\bq.py", line 584, in Create
credentials = _GetCredentialsFromFlags() File "build\bdist.win32\egg\bq.py", line 390, in _GetCredentialsFromFlags
credentials = credentials_getter(storage) File "build\bdist.win32\egg\bq.py", line 330, in
_GetCredentialsFromOAuthFlow
credentials = oauth2client.tools.run(flow, storage) File "build\bdist.win32\egg\oauth2client\util.py", line 132, in positional_wrapper
return wrapped(*args, **kwargs) File "build\bdist.win32\egg\oauth2client\old_run.py", line 149, in run
code = raw_input('Enter verification code: ').strip()
========================================
Unexpected exception in init operation: EOF when reading a line
Successfully started load _TABLE_URI_
The odd thing is that the command actually works and loads the data correctly (As also proven by the final output line).
But for some reason, it is preceded by an OAUTH 2.0 error.
Has anyone encountered something like this before?
Any idea what might cause it?
Thanks!
Why are you calling the bq.py tool from c# rather than using the C# client?
The c# client is available here:
https://developers.google.com/api-client-library/dotnet/apis/#BigQuery_API
and the ndocs are here:
https://developers.google.com/resources/api-libraries/documentation/bigquery/v2/csharp/latest/annotated.html
If you don't want to / can't use the C# client, my guess as to what is happening is that bq is having trouble writing out a credential file (or reading a credential file). Possibly this is due to a windows path issue ('/' vs '\') or possibly the path it tries to write to or read-from is inaccessible. (or possibly the path it writes to doesn't match the path it tries to read from the next time).

Categories