Accessing TwinCAT configuration
This chapter describes how to create and access a TwinCAT XAE configuration project via Automation interface. The objective of this creation process is to get access to a TwinCAT XAE project (formerly known as a TwinCAT System Manager configuration). The new TwinCAT XAE project is more sophisticated than the TwinCAT System Manager configuration known from TwinCAT2, which implies a slight concept change of project / configuration handling. TwinCAT 3 supports an extra hierarchical level combining several configurations into a Visual Studio solution container. This can for example be used to organize the configurations of distributed resources into a solution or for packaging HMI projects together with the system configuration. The solution is able to bind together all types of Visual Studio and/or TwinCAT XAE projects. When using the TwinCAT XAE Automation inferface, this means an extra level of possiblities.
Basic information
TwinCAT 3 has been fully integrated into Visual Studio to provide users with a standardized and most flexible editor to create and manage TwinCAT projects. To create and/or access a TwinCAT configuration, the combined use of Visual Studio and TwinCAT Automation Interface is possible. For example: If you want to create a new TwinCAT configuration via Automation Interface, you first need to call methods of the Visual Studio API to create a Visual Studio solution container and then add a TwinCAT project by using methods of the TwinCAT Automation Interface. This scenario will be covered in some code snippets below.
In addition, the Visual Studio API (so-called Visual Studio DTE ) provide developers with many more features, e.g. accessing the error output window. For more information about Visual Studio DTE please see the Microsoft MSDN website.
Please note:
- When creating a new TwinCAT project within a Visual Studio solution, you need to specify a path to the TwinCAT project template. Please adapt this path in the code snippets below according to your environment.
- The following code snippets use dynamic linking for the Visual Studio DTE objects, which means that the actual type of the object will be determined during the application runtime. In case you do not want to use dynamic linking but instead specify the data type in advance, you need to include the namespace EnvDTE.DTE to your project.
Creating TwinCAT Projects via templates
Please note that you need to add a reference to the COM object TcatSysManagerLib and EnvDTE.DTE (Microsoft Developement) in order to be able to use the TwinCAT Automation Interface and the Visual Studio API. The ProgID that is used in the GetTypeFromProdID() method depends on the Visual Studio version that should be used. Please have a look at this documentation article for more information about the different ProgIDs.
Code Snippet (C#):
Type t = System.Type.GetTypeFromProgID("VisualStudio.DTE.10.0");
EnvDTE.DTE dte = System.Activator.CreateInstance(t);
dte.SuppressUI = false;
dte.MainWindow.Visible = true;
if (Directory.Exists(@"C:\Temp\SolutionFolder"))
Directory.Delete(@"C:\Temp\SolutionFolder", true);
Directory.CreateDirectory(@"C:\Temp\SolutionFolder");
Directory.CreateDirectory(@"C:\Temp\SolutionFolder\MySolution1");
dynamic solution = dte.Solution;
solution.Create(@"C:\Temp\SolutionFolder", "MySolution1");
solution.SaveAs(@"C:\Temp\SolutionFolder\MySolution1\MySolution1.sln");
string template = @"C:\TwinCAT\3.1\Components\Base\PrjTemplate\TwinCAT Project.tsproj"; //path to project template
dynamic project = solution.AddFromTemplate(template, @"C:\Temp\SolutionFolder\MySolution1", "MyProject");
ITcSysManager sysManager = project.Object;
sysManager.ActivateConfiguration();
sysManager.StartRestartTwinCAT();
project.Save();
solution.SaveAs(@"C:\Temp\SolutionFolder\MySolution1\MySolution1.sln");
Code Snippet (Powershell):
You can copy and paste the following code snippet into a textfile and save it as "someName.ps1". After that you can execute it directly via Windows PowerShell.
$targetDir = "C:\tmp\TestSolution"
$targetName = "TestSolution.tsp"
$template = "C:\TwinCAT\3.1\Components\Base\PrjTemplate\TwinCAT Project.tsproj"
$dte = new-object -com VisualStudio.DTE.10.0
$dte.SuppressUI = $false
$dte.MainWindow.Visible = $true
if(test-path $targetDir -pathtype container)
{
Remove-Item $targetDir -Recurse -Force
}
New-Item $targetDir –type directory
$sln = $dte.Solution
$project = $sln.AddFromTemplate($template,$targetDir,$targetName)
$systemManager = $project.Object
$targetNetId = $systemManager.GetTargetNetId()
write-host $targetNetId
$systemManager.ActivateConfiguration()
$systemManager.StartRestartTwinCAT()
$project.Save()
$solutionPath = $targetDir + "\" + $targetName
$sln.SaveAs($solutionPath)
Code Snippet (C++):
Within appropriate Header file (e.g the stdafx.h):
//the following #import imports EnvDTE based on its LIBID.
#import"libid:80cc9f66-e7d8-4ddd-85b6-d9e6cd0e93e2" version("10.0") lcid("0") raw_interfaces_only named_guids
// Imports die "Beckhoff TCatSysManager 1.1 Type Library"
#import"libid:3C49D6C3-93DC-11D0-B162-00A0248C244B" version("1.1") lcid("0")
Because a known issue within VisualStudio 2010 (SP1), the generated proxy code will not be included into the C++ project. Please use the workaround described in #import Known Issue import Known Issue.
#include
using namespace std
using namespace TCatSysManagerLib;
using namespace EnvDTE;
int _tmain(int argc, _TCHAR* argv[])
{
CoInitialize(NULL); // COM initialisieren
cout << "Creating VisualSTudio.DTE.10.0 ...";
// creating a new instance of Visual Studio
CComPtr<_DTE> m_pDTE;
HRESULT hr = m_pDTE.CoCreateInstance(L"VisualStudio.DTE.10.0", 0, CLSCTX_ALL);
if (FAILED(hr)) { cout << " FAILED"; return 1; }
cout << " created." << endl;
// retrieves the EnvDTE.Solution-Objekt
CComPtr<_Solution> pSolution;
m_pDTE->get_Solution(&pSolution);
CComBSTR strSolutionFolder(_T("C:\\SolutionFolder")); // Solution-main directory (has to exist)
CComBSTR strSolutionName(_T("MySolution1"));
CComBSTR strTemplatePath(_T("C:\\TwinCAT\\3.1\\Components\\Base\\PrjTemplate\\TwinCAT Project.tsproj"));
CComBSTR strSolutionPath; // Solution-Pfad (doesn’t exist!)
strSolutionPath=strSolutionFolder;
strSolutionPath.Append(_T("\\"));
strSolutionPath.Append(strSolutionName);
strSolutionPath.Append(_T(".sln"));
// create the solution
hr = pSolution->Create(strSolutionFolder,strSolutionName);
CComBSTR strProjectPath(strSolutionFolder); // project path
strProjectPath.Append(_T("\\"));
strProjectPath.Append(strSolutionName);
CComBSTR strProjectName = "MyProject"; // project name // create projekt from a template
CComPtr pProject;
hr = pSolution->AddFromTemplate(strTemplatePath,strProjectPath,strProjectName,VARIANT_FALSE,&pProject);
// Wenn z.B. Projekt bereits besteht >> error
if (FAILED(hr)) { cout << " Project creation FAILED"; return 1; }
cout << "Project created" << endl;
// define project automation class (here the Coclass TcSysManager)
CComPtr pDispatch;
hr = pProject->get_Object(&pDispatch);
// retrieve ITcSysManager interface
CComPtr pSystemManager;
hr = pDispatch.QueryInterface(&pSystemManager);
// operate with SystemManager interface
CComBSTR netId;
netId = (pSystemManager->GetTargetNetId()).GetBSTR();
cout << "TargetNetId: " << netId << endl;
hr = pSystemManager->ActivateConfiguration();
hr = pSystemManager->StartRestartTwinCAT();
// save project and solution
hr = pProject->Save(CComBSTR());
hr = pSolution->SaveAs(strSolutionPath);
cout << "Succeeded";
return 0;
}
import Known Issue:
CComPtr<_DTE> m_pDTE;
CLSID clsid;
CLSIDFromProgID(L"VisualStudio.DTE.10.0",&clsid);
CComPtr punk;
HRESULT hr = GetActiveObject(clsid,NULL,&punk); // retrieve actual instance of Visual Studio .NET
m_pDTE = punk;
Please note:
ITcSysManager::NewConfiguration, ITcSysManager::OpenConfiguraiton and ITcSysManager::SaveConfiguration will create error messages in this case, because the project handling is delegated to the Visual Studio IDE (the Solution and Project instances realized by the DTE object).