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);
Related
I'm using visual studio to do my first full release of an application, which is a simple WPF GUI to configure a locally saved JSON object, and a console application to run in the background, using data from that object to monitor a website. I published each project to a test folder (we'll say Publish/), where each application manifest now resides, along with an 'Application Files' folder containing another sub-folder for each project.
I got the applications to run just fine - the problem is the configuration file saves to one folder a few more levels into C:\Users\username\AppData\Local\Apps\2.0\ and the console application is attempting to read from a completely separate folder. Both projects write and read using GetCurrentDirectory() for the file path. Is there a way I'm missing to remedy this?
Code for retrieving JSON object
try
{
//Confirms file exists
if (File.Exists(Directory.GetCurrentDirectory().ToString() + filePath))
{
//Initialize json variable to a string, then deserialize it into an instance of RCDetails
var json = File.ReadAllText(Directory.GetCurrentDirectory().ToString() + filePath);
RCDetails parsedDetails = JsonConvert.DeserializeObject<RCDetails>(json);
//Return deserialized JSON
return parsedDetails;
}
else return null;
And code for writing json object
public void WriteToFile(RCDetails rcd)
{
//Serialize input instance of RCDetails class
string JSONresult = JsonConvert.SerializeObject(rcd, Formatting.Indented);
//Remove old JSON object
if (File.Exists(Directory.GetCurrentDirectory().ToString() + jsonFilePath))
File.Delete(Directory.GetCurrentDirectory().ToString() + jsonFilePath);
//Create new JSON object with updated details
File.WriteAllText(Directory.GetCurrentDirectory().ToString() + jsonFilePath, JSONresult);
}
Exact steps for publishing project:
With console app selected, click Build > Publish (console app name)
Browse to C:\Users\username\Downloads\Publish\
For installation, choose "From a CD-ROM or DVD-ROM"
Select "the application will not check for updates
Select finish, and repeat all steps with same file path for config WPF
Solution I wound up finding (feel free to let me know if this is a bad plan). I just plopped this into both apps.
string s = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "\\IntendedFolder";
if (!Directory.Exists(s))
Directory.CreateDirectory(s);
Directory.SetCurrentDirectory(s);
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.
We have the following code in wizard to add existing project to a new solution:
//generating files
if (dte.Solution.Projects.Count < 1) // Solution is empty or doesn't exist
{
dte.Solution.Create(oneFolderHigher(Params.OutputDir, solutionName),
solutionFileName(solutionName));
}
// adding created project to solution
dte.Solution.AddFromFile(Path.Combine(Params.ProjectRootFolder,
Params.ProjectName + ".csproj"));
It works just fine under MS Visual Studio 2010, but fails under 2012 (I experimented with second parameter):
System.Runtime.InteropServices.COMException (0x80004004): Operation aborted (Exception from HRESULT: 0x80004004 (E_ABORT))
at EnvDTE.SolutionClass.AddFromFile(String FileName, Boolean Exclusive)
at Wizard.Generator.NewProjectGenerator.Generate(Action`1 logMessage)
at Wizard.Forms.WizardForm.Finish()
After this error I'm adding the new project to the solution manually and everything works OK. But we can not just say, "Sorry, we can not add newly generated project for you so please add it by yourself."
MSDN proposes:
You can use the LaunchWizard method rather than AddFromFile to execute a wizard if you want to suppress its UI during execution. LaunchWizard has a parameter that allows you to disable the UI.
But this method requires some wizard file, so it can not be a solution.
Could someone help?
Wizard is running from "New -> Project" menu.
Here the workaround for the issue (proposed by my boss):
Before adding the project to solution, project file should be converted to
VS2012 format.
But code is little ugly:
using (StreamReader sr = new StreamReader(newFile))
using (StreamWriter sw = new StreamWriter(projectFile, false, Encoding.UTF8))
{
while (sr.Peek() >= 0)
{
string s = sr.ReadLine();
if (s.Contains("<Project ToolsVersion=\"4.0\""))
{
s = s + Environment.NewLine + importProject;
}
... and so on
Maybe someone knows the way to do it awesome? I mean converting. I'll let the question to be unanswered some time. Waiting for your comments.
I am creating an installer for a custom SSIS component that we have written. I would like to add the custom component automatically, rather than asking the user to manually add it.
I'm trying to do this with this code:
public void AddToolboxItem(string toolboxTabName, string toolBoxItemName, string toolBoxItemPath) {
Type dteReference;
EnvDTE.ToolBox toolBox;
EnvDTE80.ToolBoxItem2 addedToolBoxItem;
// Get a reference to the visual studio development environment.
dteReference = Type.GetTypeFromProgID("VisualStudio.DTE.9.0");
if(dteReference != null) {
// Get a reference to the toolbox of the development environment.
EnvDTE80.DTE2 dte = (EnvDTE80.DTE2)Activator.CreateInstance(dteReference);
toolBox = (EnvDTE.ToolBox)dte.Windows.Item("{B1E99781-AB81-11D0-B683-00AA00A3EE26}").Object;
// Loop through all tab pages to find the toolbox tab page that was specified
// in the toolboxTabName parameter.
foreach (EnvDTE80.ToolBoxTab2 toolBoxTab in toolBox.ToolBoxTabs) {
// Is this the right toolbox?
if(string.Compare(toolBoxTab.Name, toolboxTabName, true) == 0) {
// First check if the component is not already in the toolbox:
bool found = false;
foreach(EnvDTE80.ToolBoxItem2 toolBoxItem in toolBoxTab.ToolBoxItems) {
if (string.Compare(toolBoxItem.Name, toolBoxItemName, true) == 0) {
found = true;
break;
}
}
// The toolbox item is not in the toolbox tab, add it:
if (!found) {
addedToolBoxItem = (EnvDTE80.ToolBoxItem2)toolBoxTab.ToolBoxItems.Add(
toolBoxItemName,
toolBoxItemPath,
EnvDTE.vsToolBoxItemFormat.vsToolBoxItemFormatDotNETComponent);
}
break;
}
}
}
}
I can get a reference to the "Data Flow Transformations" ToolBox Tab, but adding an item fails without an exception or error.
I call this function with the parameters:
toolboxTabName = "Data Flow Transformations"
toolBoxItemName = "Special Test Component"
toolBoxItemPath = "c:\Program Files\Microsoft SQL Server\100\DTS\PipelineComponents\mdTest.dll"
As a sanity check, I tried using the vsToolBoxItemFormatDotNETComponent enumeration as Add()'s third parameter. This causes Add to return a valid object (ie, success), but the new item does not appear on the tool box. I suspect there is some sort of 'save' operation that may be necessary (even if I get the Add() to work properly).
Is there any way to programmatically add a SSIS component to the
toolbox?
Same question can also be found in the MSDN forums and it has been answered there by an MVP, Moderator. I am pasting the link to the answer provided in MSDN forums so that others stumbling on this question can know what the answer is.
Programmatically Add an SSIS Component to the Toolbox (social.msdn.microsoft.com)
I'm currently writing a Winamp plugin framework for C# (basically, a C# implementation of the Winamp API/SDK, as well as a barebones plugin template). Because C# libraries can't export DLL entry points, I'm using a C++/CLI wrapper which basically just loads the C# library. I'd like to create a Visual Studio template for this, which creates both the barebones C# plugin library, and the C++ wrapper. However, if I click File → Export Template, only the C# project is listed.
Is it possible to create a multi-project template containing both a C# project and a C++/CLI project? If so, how?
I found the answer myself a while ago, and forgot to properly update this. A .vstemplate file can be used to create a C++ template by setting the language to CSharp like in C# templates (it will still work correctly).
Here is an example I've used: .vstemplate file and all other files
WiX also uses this method
'export template' does not work for C++ projects. If you want templates for them, you need to create it yourself: see my answer here. It involves some work, but if you use this kind of projects a lot, the work is well-spent time.
edit
I looked up my code, something like this should get you started; the onFinish method in default.js gets called after clicking 'Ok' in the default wizards. Note that I did not test this!
function onFinish( selProj, selObj )
{
var strProjectPath = wizard.FindSymbol('PROJECT_PATH');
var prjCpp;
var prjCs;
CreateProjects( strProjectPath, prjCpp, prjCs );
//project config here
prjCpp.Object.Save();
prjCs.Object.Save();
selProj = prjCpp;
}
function CreateProjects( path, prjCpp, prjCs )
{
var strProjTemplatePath = wizard.FindSymbol('ABSOLUTE_PATH'); //get template from our template dir
var strProjTemplateCpp = strProjTemplatePath + '\\default.vcproj';
var strProjTemplateCs = strProjTemplatePath + '\\default.csproj';
var Solution = dte.Solution;
if( wizard.FindSymbol( "CLOSE_SOLUTION" ) )
{
Solution.Close();
strSolutionName = wizard.FindSymbol( "VS_SOLUTION_NAME" );
if( strSolutionName.length )
{
var strSolutionPath = strProjectPath.substr( 0, strProjectPath.length - strProjectName.length );
Solution.Create(strSolutionPath, strSolutionName);
}
}
var oTarget = wizard.FindSymbol( "TARGET" );
prjCpp = oTarget.AddFromTemplate( strProjTemplateCpp, strProjectPath, strProjectName + '.vcproj' );
prjCs = oTarget.AddFromTemplate( strProjTemplateCs, strProjectPath, strProjectName + '.csproj' );
Solution.Projects.Add( prjCpp );
Solution.Projects.Add( prjCs );
}