Executing SSIS package programmatically - c#

Below is the code I will be referring to. A few questions:
Am I able to reference two different .DTSX files within one "String pkgLocation =" statement? (I did it below), if I am unable to do so, and have over 10 different packages to execute programmatically, is there a quick and painless way to go about this?
Does the code below represent Entity Framework at all?
Its been a while since I played with SSIS and I am wondering how to specifically execute it? simply pressing "Run" shows me nothing within the Test Explorer (probably because its not a test) and when I attempt to Execute it I receive a message stating "project with an output type of class library cannot be started directly" What does that even mean?
Am I on the right track? (with regards to executing these packages programmatically)
public class UnitTest1
{
private void Execute_Package()
{
string pkgLocation = #"C:\tfs\z Reports\BI Projects\Customer Service Data Warehouse\Customer Service Data Warehouse" +
#"C:\tfs\z Reports\BI Projects\Customer Service Data Warehouse\SRS DataMart SSIS\SRSDimCategorizationLoad.dtsx";
Package pkg;
Application app;
DTSExecResult pkgResults;
Variables vars;
app = new Application();
pkg = app.LoadPackage(pkgLocation, null);
vars = pkg.Variables;
vars["A_Variable"].Value = "Some value";
pkgResults = pkg.Execute();
}
}
Here is the old code that I made into the code above:
private static void LoadTicketLifeCycleSnapShotFact()
{
ExceutePackage(#"C:\tfs\z Reports\BI Projects\Customer Service Data Warehouse\Customer Service Data Warehouse\SAPBPDataToStage.dtsx");
ExceutePackage(#"C:\tfs\z Reports\BI Projects\Customer Service Data Warehouse\SRS DataMart SSIS\SRSDimCategorizationLoad.dtsx");

I would create an array of the package locations and then enumerate through them calling the Execute method for each of them.
private void Execute_Package()
{
string [] pkgLocations = new string[]{
#"C:\tfs\z Reports\BI Projects\Customer Service Data Warehouse\Customer Service Data Warehouse",
#"C:\tfs\z Reports\BI Projects\Customer Service Data Warehouse\SRS DataMart SSIS\SRSDimCategorizationLoad.dtsx"};
Package pkg;
Application app;
DTSExecResult pkgResults;
Variables vars;
app = new Application();
foreach(string currentFile in pkgLocations)
{
pkg = app.LoadPackage(currentFile, null);
// Assumes this variable exists in all of the packages
vars = pkg.Variables;
vars["A_Variable"].Value = "Some value";
pkgResults = pkg.Execute();
}
}
To answer the specific questions you raised:
No, you cannot reference them as you specified. The above is how you would execute the packages in sequence.
I have no clue whether this is "EF". I assume not
You've created a test library. A library isn't a runnable thing. Something else needs to make it go (something with a Main method). For testing, this will be your test harness (nUnit). Alternatively, I'd create a Console app that uses the testing project to ensure you've built your test cases correctly (and then you create a test project to test your test...)
Yes, your code above instantiates a package, assigns a value to an SSIS variable and then runs the package with that new variable.

Related

C# SSIS pkg.Execute(null,null,dtsEvents,null,null) returns "Failed" with no events

I'm just dummy in using SSIS&*.dtsx files from C#. Now I have WindowsForms project and OnClick handler with this code:
.....
string pkgLocation;
Package pkg;
Microsoft.SqlServer.Dts.Runtime.Application app;
DTSExecResult pkgResults;
DTSEvents dtsEvents=new DTSEvents();
pkgLocation = System.Windows.Forms.Application.StartupPath+ #"\" + #"3StreamsImport.dtsx";
app = new Microsoft.SqlServer.Dts.Runtime.Application();
app.PackagePassword = "abudfv";
app.EnableDump = true;
app.DumpOnAnyError = true;
pkg = app.LoadPackage(pkgLocation, dtsEvents,true);
try {
pkgResults = pkg.Execute(null,null,dtsEvents,null,null);
}catch(System.Runtime.InteropServices.COMException ex) {
Console.WriteLine(ex.StackTrace);
}
.......
"3Streamsimport.dtsx" file was created with SqlServer management studio for SqlServer 2016 and is working fine from standard Еxecute Package Utility. Loading package in my code passes fine too. But executing fails allways! dtsEvents is instanceof object that implements all from IDTSEvents interface.
Dear ALL, who can help with definitions of ways to solve the problem?
It's been a while since I tried, so I don't know if later versions have improved anything, but I was never able to get an SSIS package to execute from C# the way you are trying to do.
What I eventually did was create a job that executed the package, and used C# to start the job. It worked fine.
Solved! All C# code is fine. As addition I'm implemented IDTSLogging. After changing "exectute" call to
pkgResults = pkg.Execute(null,null,dtsEvents,new DTSLogging(),null);
all events are firing smoothly. I don'nt know/ why, but it is working.
Now about DTSX- file: It was my mistake in project and the proper copy was simply in other place! :-(
Sorry :-(

Unable to communicate between actors in Akka.Cluster

I am having some problems in communicating between actors in Cluster.
My test project has this structure below.
TestJob [C# Console Project]
TestJobService.cs
TestJobActor
MainProject [C# Console Project] //Note: I configured this service as a seed node. I didn't use lighthouse.
MainService
JobManagerActor
Note: I don't want to put actors in Shared project or Main project. The actors that are supposed to do a test job should be under "TestJob" project.
I already followed this article http://getakka.net/docs/clustering/cluster-overview and video. I did enable Akka.Cluster based on the article. I am able to run both console projects but when I tried to "tell" from JobManagerActor to TestJobActor, it doesn't work. No error but doesn't work.
I have this config in MainProject.
actor {
provider = "Akka.Cluster.ClusterActorRefProvider, Akka.Cluster"
deployment {
/TestJobAActor {
router = consistent-hashing-group
routees.paths = ["/user/TestJobAActor"]
virtual-nodes-factor = 8
cluster {
enabled = on
max-nr-of-instances-per-node = 2
allow-local-routees = off
use-role = backend
}
}
}
}
Here is the code that I use for sending the message.
var backendRouter = Context.ActorOf(Props.Empty.WithRouter(new ClusterRouterGroup(new ConsistentHashingGroup("/user/TestJobAActor"),new ClusterRouterGroupSettings(10, false, "backend", ImmutableHashSet.Create("/user/TestJobAActor")))));
backendRouter.Tell("Yo yo!");
What am I missing? Thanks in advance.
Note: My test project with similar structure can be found here https://github.com/michaelsync/APMDemo . (VS2015 project)
One more question: Can we still use the actor selection when using cluster?
var actorSelection = Context.ActorSelection("akka.tcp://MyBackendProcessingSystem#127.0.0.1:2553/user/BackEndJobAActor"); //This can come from Model
actorSelection.Tell("Yo yo!");
No worries!
I managed to fix it myself. You can see the fixes in my temp repo https://github.com/michaelsync/APMDemo/tree/allinoneproject.
The problem was that I didn't know I need to use IConsistentHashable for sending message in consistent-route. I keep on sending the string and didn't work.
local route was off.

Set Package User Variable Value in Integration Services and Run Package C# LoadFromSqlServer

I have packages that I imported to Integration Services. I have them all set up and I have mapped them to run. My issue is that I am trying to programmatically pass a value to my User Variables in the package.
I have a Start Date and an End Date that I have to populate, but I have not been able to find anything regarding what I am doing. Can anyone help?
I am new to using LoadFromSqlServer and am not really sure if there is anymore information that you may need to help, but if you ask I will be more than happy to edit my question and add what is needed.
Any help would be much appreciated. Thanks!
---EDIT---
Here is the error i am getting by using this bit of code:
Application app = new Application();
Package package = new Package();
Variables variables = package.Variables;
package = app.LoadFromSqlServer("\\File\\Path\\" + paramName, ".", "UserName"
, "Password", null);
variables["User::START_DATETIME"].Value = startDate;
variables["User::END_DATETIME"].Value = endDate;
DTSExecResult result = package.Execute();
Here is the error:
Additional information: The variable cannot be found. This occurs when an attempt
is made to retrieve a variable from the Variables collection on a container during
execution of the package, and the variable is not there. The variable name may have
changed or the variable is not being created.
I actually was able to find the issue with my question. It is rather silly but still a solution.
In my code I was using
Variables variables = package.Variables;
Before I was actually attaching a package to my package variable.
Switching my code around to call the variables after the package was being attached to my variable worked. The new code looks like this:
Application app = new Application();
Package package = new Package();
package = app.LoadFromSqlServer("\\File\\Path\\" + paramName, ".", "UserName"
, "Password", null);
Variables variables = package.Variables;
variables["START_DATETIME"].Value = startDate;
variables["END_DATETIME"].Value = endDate;
DTSExecResult result = package.Execute();
you can pass the varibles into SSIS Package by:
Package package = null;
//Load the SSIS Package which will be executed
package.Variables["User::StartDate"].Value = '2014-01-01';
package.Variables["User::EndDate"].Value = '2014-01-10';
EDIT
1. Check if there is no typo:
if (package .Variables.Contains["StartDate"])
{
...
}
Ensure that the SSIS service is running
Also you can try to use Dispenser class:
package.VariableDispenser.LockOneForWrite("StartDate", variables)
package.Variables["User::StartDate"].Value = '2014-01-01';
variables.Unlock()

Use Addin project in another application

I have created a addin application with which i'm creating a solution with some files programtically. I have to integrate this in another winforms application. So once the user clicks the button a new project is created with some inputs dynamically.
In the addin project the form contains a method(OnConnection) which gets called automatically. This creates the project at run-time. The application works fine.
public void OnConnection(object application, ext_ConnectMode connectMode, object addInInst, ref Array custom)
{
_applicationObject = (DTE2)application;
_addInInstance = (AddIn)addInInst;
createProjectsFromTemplates(_applicationObject);
}
public void createProjectsFromTemplates(DTE2 dte)
{
try
{
// Create a solution with two projects in it, based on project
// templates.
Solution2 soln = (Solution2)dte.Solution;
string csTemplatePath;
//string vbTemplatePath;
string csPrjPath = "\\\\#####.com\\###\\My Documents\\TestCreateProject";
//string vbPrjPath = "C:\\UserFiles\\user1\\addins\\MyVBProject";
// Get the project template path for a C# console project.
// Console Application is the template name that appears in
// the right pane. "CSharp" is the Language(vstemplate) as seen
// in the registry.
csTemplatePath = soln.GetProjectTemplate("WpfApplication.zip", "CSharp");
System.Windows.Forms.MessageBox.Show("C# template path: " + csTemplatePath);
// Get the project template path for a Visual Basic console
// project.
// "vbproj: is the DefaultProjectExtension as seen in the
// registry.
//vbTemplatePath = soln.GetProjectTemplate("ConsoleApplication.zip", "vbproj");
//System.Windows.Forms.MessageBox.Show("Visual Basic template path: " + vbTemplatePath);
// Create a new C# console project using the template obtained
// above.
soln.AddFromTemplate(csTemplatePath, csPrjPath, "NewWCFCSharpAutoGeneratorProject", false);
// Create a new Visual Basic console project using the template
// obtained above.
//soln.AddFromTemplate(vbTemplatePath, vbPrjPath, "New VB Console Project", false);
Project prj;
ProjectItem prjItem;
String itemPath;
// Point to the first project (the Visual Basic project).
prj = soln.Projects.Item(1);
prjItem = prj.ProjectItems.AddFromFileCopy("\\\\####.com\\###\\My Documents\\SampelCSharp.cs");
// Retrieve the path to the class template.
//itemPath = soln.GetProjectItemTemplate("MyClass.zip", "CSharp");
//Create a new project item based on the template, in this
// case, a Class.
//prjItem = prj.ProjectItems.AddFromTemplate(itemPath, "MyNewClass.cs");
}
catch (System.Exception ex)
{
System.Windows.Forms.MessageBox.Show("ERROR: " + ex.Message);
}
}
Now i have to use the add in project from another application(Winforms) in order to create the project at run-time. I have build the addin project and imported the .dll file to that application. I have created an instance for the class and got the "OnConnection" method.But i'm not sure about what to be passed as the parameters. Because when debugging the method it shows the "application" parameter carries some "COM" objects within it.
Also if the application runs once, the new project is created when executed again it says file already exists in the path. I have to overwrite the older one.
What is the solution for this?
Note: Using Visual studio 2012 and Framework 3.5
Try this:
EnvDTE80.DTE2 dte2;
dte2 = (EnvDTE80.DTE2)System.Runtime.InteropServices.Marshal.GetActiveObject("VisualStudio.DTE.11.0");
Connect objConnect = new Connect();
Array objArray = null;
objConnect.OnConnection(dte2, ext_ConnectMode.ext_cm_UISetup, null, ref objArray);

C# Waiting for other services to start

I'm writing a Windows service that relies on other services, how should I wait for the other services to start?
Thanks
In addition to what other answers have alredy pointed out, if one of those services is SQL Server you will need to ensure that the specific database is available as well as the SQL Server service itself.
I use a function similar to the following:
public class DbStatus
{
public static bool DbOnline()
{
const int MaxRetries = 10;
int count = 0;
while (count < MaxRetries)
{
try
{
// Just access the database. any cheap query is ok since we don't care about the result.
return true;
}
catch (Exception ex)
{
Thread.Sleep(30000);
count++;
}
}
return false;
}
}
I think you shoud this line
installer.ServicesDependedOn = new string [] { "DependenceService" };
like this:
using (ServiceProcessInstaller processInstaller = new ServiceProcessInstaller())
{
processInstaller.Account = ServiceAccount.LocalSystem;
processInstaller.Username = null;
processInstaller.Password = null;
using (ServiceInstaller installer = new ServiceInstaller())
{
installer.DisplayName = "yourservice.";
installer.StartType = ServiceStartMode.Automatic;
installer.ServiceName = "YourService";
installer.ServicesDependedOn = new string [] { "DependenceService" };
this.Installers.Add(processInstaller);
this.Installers.Add(installer);
}
}
good luck
You need to specify the dependencies. You can do this in your Installer class.
Further clarification
You should be using an Installer class as a Custom Action in your setup project to install your service. If you aren't, post a comment and I'll update this answer with steps on how to do that.
Inside the designer for your Installer class you should see two components: a serviceInstaller and a serviceProcessInstaller. I don't remember which off of the top of my head, but one of these has a property that allows you to specify a multiline string that lists the service names of your service's dependencies.
As others here said, you should use the ServiceInstaller Class, but you don't need a full blowned setup project.
You can do a quick instalation using InstallUtil.exe, a command-line utility that comes with the .NET Framework.
Do you have control over the other services?
If yes have them start you, if not I guess you have to start anyway and monitor yourself what is going on.
It is possible to register yourself with WMI to get notifyied when other processes are started - there is a question about it.
In your service project, add a project installer as described here. One of the properties of your ProjectInstaller will be ServicesDependedOn. When you add services to that array of strings (you can do that through the IDE), they will be required to be started before your service will start. If they are not started the SCM will try and start them.

Categories

Resources