4

I am trying to convert the following C# code to PowerShell (I have left out the parts of the code that I do not think are relevant):

C#

System.Type t = System.Type.GetTypeFromProgID("VisualStudio.DTE.10.0", true);
object obj = System.Activator.CreateInstance(t, true);
EnvDTE80.DTE2 dte = (EnvDTE80.DTE2)obj;

dte.MainWindow.Activate();

dynamic solution = dte.Solution;
solution.Create(solution_folder_path, solution_name);
solution.SaveAs(solution_file_path);

dynamic project = solution.AddFromTemplate(template_path, project_folder_path, project_name);

TCatSysManagerLib.ITcSysManager system_manager = project.Object;

PowerShell

[System.Reflection.Assembly]::LoadFrom("C:\Windows\assembly\GAC_MSIL\TCatSysManagerLib\2.1.0.0__180016cd49e5e8c3\TCatSysManagerLib.dll");

$dte = New-Object -ComObject VisualStudio.DTE.10.0

$dte.SuppressUI = $false
$dte.MainWindow | %{$_.GetType().InvokeMember("Visible", "SetProperty", $null, $_, $true)}

$solution = $dte.Solution

$project = $solution.AddFromTemplate($template_path, $project_folder_path, $project_name)

[TCatSysManagerLib.ITcSysManager] $system_manager = [TCatSysManagerLib.ITcSysManager] $project.Object

The problem that I run into is that the last line in PowerShell returns an error of the form:

Cannot convert the "System.__ComObject" value of type "System.__ComObject#{3b56a5ce-0c02-440b-8ced-f1f3e83f66ed}" to type "TCatSysManagerLib.ITcSysManager".

Added details:

I could just leave out the [TCatSysManagerLib.ITcSysManager] type in the PowerShell code. I run into the same problem however in converting this C# code later on:

TCatSysManagerLib.ITcSmTreeItem gvl = system_manager.LookupTreeItem("TIPC^PLC1^PLC1 Project^GVLs^GVL");
TCatSysManagerLib.ITcPlcDeclaration gvl_declaration = (TCatSysManagerLib.ITcPlcDeclaration)gvl;
string gvl_declaration_text = System.IO.File.ReadAllText(gvl_declaration_text_file_path);
gvl_declaration.DeclarationText = gvl_declaration_text;

In this case I have to make the cast to the TCatSysManagerLib.ITcPlcDeclaration type in order to gain access to the DeclarationText property of gvl_declaration.

The C# code is modified from: http://infosys.beckhoff.com/english.php?content=../content/1033/tc3_automationinterface/108086391299624331.html&id=

I am new to both C# and PowerShell and have modified these from examples. Any advice would be appreciated.

Patrick
  • 147
  • 1
  • 15
  • Possible duplicate of [PowerShell: how to convert a COM object to an .NET interop type?](https://stackoverflow.com/questions/9036551/powershell-how-to-convert-a-com-object-to-an-net-interop-type) – weir May 01 '18 at 16:46

1 Answers1

1

Here's a couple of ideas.

  1. When making use of COM classes using the Primary Interop assembly (PIA) is recommend, if one is available. There is one for VS. I found it by looking in the registry for VisualStudio.DTE, then finding the typelib GUID, and going to the TypeLib key to see that EnvDTE is listed as the PIA. In retrospect a google search would've found it as well. Load the PIA with [reflection.assembly]::loadwithpartialname("EnvDTE"). Unfortunately I can't any way to instantiate an object via the PIA. You can get access to the $DTA variable in the VS powershell console, though.
  2. Probably not necessary if you use #1, but you can get MethodInfos for COM coclass by doing GetMethod on the Interface, rather than the class. You can then use .Invoke() against a MethodInfo.
  3. Check out the documentation for EnvDTE and related.
  4. Also you might want to check out "StudioShell".
Χpẘ
  • 3,403
  • 1
  • 13
  • 22
  • Thank you for your response. Unfortunately I am not familiar with a lot of these terms. I think I am going to have to do some background reading. – Patrick Dec 03 '15 at 19:03
  • If you want to simplify somewhat, I suggest: 1) decide if your solution can run within VS. If it can then you can use the $DTA variable and hopefully your existing code wirjs without too many mods. You may want to do this anyway, even if your solution has to be external to VS, just to prove out your PS script. 2) decide if you can use a tool like StudioShell. BTW, from what I can tell, typecasting in PS doesn't work the same as in C#, so I'm not sure I'd hold hope for the cast working like you want. `MethodInfo` is the .NET type: System.Reflection.MethodInfo. GetMethod is a System.Type method – Χpẘ Dec 03 '15 at 22:34