I created a package for internal use which has an App.xaml file in content. Naturally I would like to find it in target project with BuildAction set to “ApplicationDefinition”, but Visual Studio treats it as “Page”, because it is the xaml extension default.
I found a hopeful solution here promising a fast track. My first version of install.ps1 was this:
param($installPath, $toolsPath, $package, $project) $item = $project.ProjectItems.Item("App.xaml") $item.Properties.Item("BuildAction").Value = ???
The problem raised when I didnt found the “ApplicationDefinition” value in prjBuildAction enumeration on MSDN…
I found some similar examples on the net. Some of them have comment with a question: what to do if someone wants to set a value not in the enumeration? Neither of those comments has an answer which distressed me a bit.
Here I found a clue so I tried to enumerate those undefined prjBuildAction values with this code:
param($installPath, $toolsPath, $package, $project) Add-Type -AssemblyName 'Microsoft.Build.Engine' $msbuildproject = new-object Microsoft.Build.BuildEngine.Project $msbuildproject.Load($project.FullName) [System.Collections.ArrayList]$buildActions = "None", "Compile", "Content","EmbeddedResource" $msbuildproject.ItemGroups | Where-Object { $_.Name -eq "AvailableItemName" } | Select-Object -Property "Include" | ForEach-Object { $act = $_ $buildActions.Add($act) } $item = $project.ProjectItems.Item("App.xaml") $item.Properties.Item("BuildAction").Value = [int]$buildActions.IndexOf("ApplicationDefinition")
Dont know why but the enumeration of the ItemGroups didnt worked. When I did a
Write-Host ($msbuildproject.ItemGroups | Format-List | Out-String)
it showed me a nice list of BuildItems, but when I run with a Where-Object against it I found nothing. The problem should be in PS syntax or the object instances. I dont maintain my PS knowledge which is based on my .Net and Linux scripting practice combined with looking for snippets from code examples around. I simply dont want to go more deeply into it because I feel PS is something “created” and not “born” if You understand what I mean.
I rewrite the script to get the available BuildAction values as follows:
... $msbuildproject.ItemGroups | ForEach-Object { $ig = $_ @($ig.GetEnumerator()) | ForEach-Object { $i = $_ if ($i.Name -eq "AvailableItemName") { $buildActions.Add($i.Include); } } ...
And voilá, I got a nice list of values in $buildActions:
None Compile Content EmbeddedResource CodeAnalysisDictionary ApplicationDefinition Page Resource SplashScreen DesignData DesignDataWithDesignTimeCreatableTypes EntityDeploy XamlAppDef
My $idx becomes: 5, I checked value in Solution Explorer… and found “CodeAnalysisDictionary” there. No problem, it should be some 0/1 based indexing problem, lets set $idx+1, run, check, value okay! Lets try something other just for to be sure… again bad value! Unfortunately it seems the order of values collected with this algorithm isnt good as the link I mentioned above imply. Back to the start line.
While looking for solutions I somewhere found something else about ProjectItem’s “ItemType” property, so I tried to play with it. And suddently the Sun raised, the sky becomes blue, etc.:
param($installPath, $toolsPath, $package, $project) $item = $project.ProjectItems.Item("App.xaml") $item.Properties.Item("ItemType").Value = "ApplicationDefinition"
So simple and it works!