3

I have a solution with 1 web application project. I'm trying to add three c# class library projects to it and then add project references of these three projects to the existing web application project. I'm doing this using powershell. I'm able to add the three projects to the solution, but I can't figure out how to add the project references to the existing project. I understand I have to use VSLangProj.VSProject in order to get access to the references, but I Keep getting a conversion error.

Here is the error:

Cannot convert the "System._ComObject" value of type "System._ComObject#{b1042570-25c6-424a-b58b-56fa83aa828a}" to type "VSLangProj.VSProject".

Here is the relevant code I have so far.

[void][System.Reflection.Assembly]::LoadWithPartialName("envdte.dll")
[void][System.Reflection.Assembly]::LoadWithPartialName("envdte80.dll")
[void][System.Reflection.Assembly]::LoadWithPartialName("VSLangProj.dll")
[void][System.Reflection.Assembly]::LoadWithPartialName("VSLangProj80.dll")

$envdte = [System.Runtime.InteropServices.Marshal]::GetActiveObject("VisualStudio.DTE.12.0")


    $envdte.Solution.Open($FullPathtoSolution)

    $envdte.Solution.AddFromFile($FUllPathtoNewProject1)
$envdte.Solution.AddFromFile($FUllPathtoNewProject2)
$envdte.Solution.AddFromFile($FUllPathtoNewProject3) 

    $envdte.Solution.SaveAs($FullPathtoSolution)

    foreach ($proj in $envdte.Solution.Projects)
               {
                    $proj.Kind #Prints {FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
        $proj.Name #Prints the name of my web application project like it should
        $vsproj = [VSLangProj.VSProject]$proj.Object #this line causes the error
        $vsproj.References.AddProject($NewProject1Name)
                    $vsproj.References.AddProject($NewProject2Name)
                    $vsproj.References.AddProject($NewProject3Name)
                }



$envdte.Solution.SaveAs($FullPathtoSolution)
Chris
  • 49
  • 4

3 Answers3

1

Try changing from VSLangProj.VSProject to VSLangProj80.VSProject2. So:

$vsproj = [VSLangProj.VSProject]$proj.Object

becomes:

$vsproj = [VSLangProj80.VSProject2]$proj.Object

See the VSProject2 Interface docs on MSDN (specifically the GuidAttribute).

areyling
  • 2,181
  • 2
  • 20
  • 25
  • In my limited but hard earned experience with `VSLangProj80.VSProject2`, if something can be successfully casted to it, it can also be casted to `VSLangProj.VSProject` just as well. – V-R Sep 21 '16 at 21:02
  • That would make sense because VSProject2 is derived from VSProject, but I'm not sure if COM handles casting. The Guid listed in the error message is for VSProject2. – areyling Sep 22 '16 at 13:34
0

According to the docs for VSProject Interface, EnvDte.Project.Object is VSProject only for Visual Basic or Visual C# projects. You can try the following (example in C#):

if (project.Kind == VSLangProj.PrjKind.prjKindCSharpProject)
{
    var vsproj = (VSLangProj.VSProject)project.Object;
    vsproj.References.Add(...);
}
Sergii Volchkov
  • 1,169
  • 17
  • 23
0

I just ran into this same issue. As discussed in PowerShell: how to convert a COM object to an .NET interop type?, it's not possible to cast the PowerShell System._ComObject wrapper to the interface type, although you can check if it implements the COM interface using -is. In most cases PowerShell will forward to the correct interface automatically without casting:

foreach ($proj in $envdte.Solution.Projects) {
    if ($proj.Object -is [VSLangProj.VSProject]) {
        $vsproj = $proj.Object
        $vsproj.References.AddProject($NewProject1Name)
        $vsproj.References.AddProject($NewProject2Name)
        $vsproj.References.AddProject($NewProject3Name)
    }
}
Kevinoid
  • 4,180
  • 40
  • 25