sirius91
Goto Top

Csproj mit powershell ändern

Hallo liebes Forum,

ich versuche gerade ein PowerShell Script zu schreiben, welches eine VisualStudio ".csproj" verändert.
Die csproj Datei ist wie eine XML Datei aufgebaut.
Ich habe schon etliche Versuche gestartet aber leider kann ich keines der Elemente verändern, obwohl ich mir eigentlich sicher bin, dass es so funktionieren sollte.

Wenn ich die Datei manuell ändere lässt sich die Datei bearbeiten. Also am Schreibschutz sollte es nicht liegen!

Die csProj ist wie folgt aufgebaut:

Stark gekürzte csproj Datei:
<Project>
  <PropertyGroup>
    <ApplicationRevision>30000</ApplicationRevision>
    <ApplicationVersion>2.2.7200.%2a</ApplicationVersion>
  </PropertyGroup>
</Project>
[...]

TestScript zu updaten der Revision und Version Nummer:
[string] $Version = "2.3.16294.07"  
[string] $file = 'D:\GUI.csproj'  

	[string]$ApplicationRevisionFormat = "([0-9]+)$"  
	[string]$ApplicatonVersionFormat = "(\d+\.\d+\.\d+\.)"  

	$Version -match $ApplicationRevisionFormat 
	[string]$ApplicationRevision = $matches
	Write "Revision: $ApplicationRevision"  

	$Version -match $ApplicatonVersionFormat
	[string]$ApplicatonVersion = $matches + "%2a"   
	Write "Version: $ApplicatonVersion"  

		[xml]$xmlDoc = Get-Content $file 
		if($xmlDoc -ne $null)
		{
			[string]$xmlApplicatonRevisionExists = $xmlDoc.Project.PropertyGroup.ApplicationRevision
			[string]$xmlApplicatonVersionExists = $xmlDoc.Project.PropertyGroup.ApplicationVersion 
            

			if($xmlApplicatonVersionExists -ne $null -and $xmlApplicatonRevisionExists -ne $null)
			{
**                $xmlDoc.Project.PropertyGroup.ApplicationRevision.SetValue("$ApplicationRevision", 0)  
                $xmlDoc.Project.PropertyGroup.ApplicationVersion.SetValue("$ApplicatonVersion", 0)**  
				$xmlDoc.Save($file)
			}
        }

    
        [xml]$xmlDocUpdated = Get-Content $file
        write $xmlDocUpdated.Project.PropertyGroup.ApplicationRevision
        write $xmlDocUpdated.Project.PropertyGroup.ApplicationVersion

Vielen Dank für die Hilfe

Content-Key: 318542

Url: https://administrator.de/contentid/318542

Printed on: April 28, 2024 at 01:04 o'clock

Mitglied: 131223
131223 Oct 20, 2016 at 12:39:55 (UTC)
Goto Top
Ganz einfach dein $xmlDoc.Project.PropertyGroup ist ein Array. Da musst du entweder das erste Element von nehmen oder besser gleich mit XPath den richtigen Knoten selektieren.
Member: Sirius91
Sirius91 Oct 20, 2016 at 12:49:06 (UTC)
Goto Top
So sicher wäre ich mir da nicht. Ich werde es mal ausprobieren.

Aber mit meinem Code kann ich ja darauf zugreifen... also selektiere ich ja den Knoten ?!

Hier mal das Output Fenster:
PS C:\Users\xyz> [string] $Version = "2.3.16294.07"  
[string] $file = 'D:\GUI.csproj'  

	[string]$ApplicationRevisionFormat = "([0-9]+)$"  
	[string]$ApplicatonVersionFormat = "(\d+\.\d+\.\d+\.)"  

	$Version -match $ApplicationRevisionFormat 
	[string]$ApplicationRevision = $matches
	Write "Revision: $ApplicationRevision"  

	$Version -match $ApplicatonVersionFormat
	[string]$ApplicatonVersion = $matches + "%2a"   
	Write "Version: $ApplicatonVersion"  

		[xml]$xmlDoc = Get-Content $file 
		if($xmlDoc -ne $null)
		{
			[string]$xmlApplicatonRevisionExists = $xmlDoc.Project.PropertyGroup.ApplicationRevision
			[string]$xmlApplicatonVersionExists = $xmlDoc.Project.PropertyGroup.ApplicationVersion 
            

			if($xmlApplicatonVersionExists -ne $null -and $xmlApplicatonRevisionExists -ne $null)
			{
                $xmlDoc.Project.PropertyGroup.ApplicationRevision.SetValue("$ApplicationRevision", 0)  
                $xmlDoc.Project.PropertyGroup.ApplicationVersion.SetValue("$ApplicatonVersion", 0)  
				$xmlDoc.Save($file)
			}
        }

    
        [xml]$xmlDocUpdated = Get-Content $file
        write $xmlDocUpdated.Project.PropertyGroup.ApplicationRevision
        write $xmlDocUpdated.Project.PropertyGroup.ApplicationVersion
True
Revision: 07
True
Version: 2.3.16294.%2a
30000
2.2.7200.%2a
Mitglied: 131223
131223 Oct 20, 2016 at 12:55:25 (UTC)
Goto Top
So sicher wäre ich mir da nicht.
Doch das ist ein Array. es gibt mehrere PropertyGroup Knoten in der XML-Datei, du kannst keine Eigenschaft einem Array zuweisen, sondern nur einem Knoten aus dem Array.
Member: colinardo
Solution colinardo Oct 20, 2016 updated at 13:03:59 (UTC)
Goto Top
Servus,
Sacknase hat recht, in einer CSProj XML-Datei existieren mehrere dieser PropertyGroup-Knoten, deswegen musst du den gewünschten mit seinem Index selektieren.
$xmlDoc.Project.PropertyGroup ist ein Array
$xmlDoc.Project.PropertyGroup ist ein Knoten aus diesem Array

Oder du machst es sichere mit meinem Vorschlag per XPath Selection:
[string] $Version = '2.3.16294.07'  
[string] $file = 'D:\Testprojekt.csproj'  

$xml = [xml](gc $file)
# NamespaceManager erstellen
[System.Xml.XmlNamespaceManager]$ns = new-Object System.Xml.XmlNamespaceManager $xml.NameTable
# Extract all used Namespaces in XML document and them to NamespaceManager
$xml.SelectNodes('//*') | ?{$_.NamespaceURI -ne ''} | select @{n='Prefix';e={$_.GetPrefixOfNamespace($_.NamespaceURI)}},NamespaceURI | select Prefix,NamespaceURI -unique | %{if($_.Prefix -eq ''){$_.Prefix = 'default'};$ns.AddNamespace($_.Prefix,$_.NamespaceURI)}  
# Abfrage des richtigen Knotens
$group = $xml.SelectSingleNode('//default:PropertyGroup[default:ApplicationVersion]',$ns)  
if($group){
    $parts = [regex]::Match($version,'^(\d+\.\d+\.\d+\.)(\d+)$')  
    $group.ApplicationVersion = "$($parts.Groups[1].Value)%2a"  
    $group.ApplicationRevision = $parts.Groups[2].Value
}
$xml.Save($file)
Grüße Uwe
Member: Sirius91
Sirius91 Oct 20, 2016 at 13:12:47 (UTC)
Goto Top
Besten Dank!
Der Code ist zwar etwas verwirrend für mich. Ich muss zugeben das dies mein erste PowerShell Script ist.

Aber deine Lösung funktioniert.
Wenn es dir nichts ausmacht und du Lust hast, könntest du mir erklären was genau was macht? face-big-smile


Bitte ändere $file = D:\GUI.csproj - damit der Namespace nicht zugeordnet werden kann, hab ich leider vergessen. Danke!
Member: colinardo
colinardo Oct 20, 2016 updated at 13:23:12 (UTC)
Goto Top
Zitat von @Sirius91:
Aber deine Lösung funktioniert.
Wenn es dir nichts ausmacht und du Lust hast, könntest du mir erklären was genau was macht? face-big-smile
Mache ich gerne:
# NamespaceManager erstellen
[System.Xml.XmlNamespaceManager]$ns = new-Object System.Xml.XmlNamespaceManager $xml.NameTable
# Extract all used Namespaces in XML document and them to NamespaceManager
$xml.SelectNodes('//*') | ?{$_.NamespaceURI -ne ''} | select @{n='Prefix';e={$_.GetPrefixOfNamespace($_.NamespaceURI)}},NamespaceURI | select Prefix,NamespaceURI -unique | %{if($_.Prefix -eq ''){$_.Prefix = 'default'};$ns.AddNamespace($_.Prefix,$_.NamespaceURI)}  
Die zwei Zeilen für den Namespacemanager sind hier nötig da das XML-File einen Namespace hat > xmlns="http://schemas.microsoft.com/developer/msbuild/2003", und ich ohne diese keine Selection per XPath durchführen kann.
Die Zeile für das Hinzufügen der Namespaces habe ich mir mal gebaut um alle Namespaces automatisch hinzufügen zu können ohne diese manuell hinzufügen zu müssen.
$group = $xml.SelectSingleNode('//default:PropertyGroup[default:ApplicationVersion]',$ns)   
Diese Zeile selektiert den passenden Knoten per XPath. Hier ein Knoten mit dem Namen PropertyGroup mit Namespace default und einem Unterknoten mit dem Namen ApplicationVersion.

Der Rest sollte bekannt sein.

Es gibt viele Wege nach Rom, das ist einer davon. Du kannst das natürlich auch anders machen und die Knoten ausfiltern per where-object die keinen ApplicationVersion Knoten haben.

Bitte ändere $file = D:\GUI.csproj - damit der Namespace nicht zugeordnet werden kann, hab ich leider vergessen.
Geändert.

Grüße Uwe
Member: Sirius91
Sirius91 Oct 21, 2016 at 08:48:16 (UTC)
Goto Top
Alles klar. Danke. Ungefähr kann ich erahnen was du meinst. Als Namespace kann man also auch die "Elemente" bezeichnen face-smile
Auf jeden Fall coole Lösung!
Member: colinardo
colinardo Oct 21, 2016 updated at 08:57:18 (UTC)
Goto Top
Zitat von @Sirius91:
Als Namespace kann man also auch die "Elemente" bezeichnen face-smile
Nein, der Namespace ist ein Attribut eines Knotens. Lautet das dieser xmlns ist das der Standard-Namespace für diesen und alle untergeordneten Knoten, außer in einem Kind-Knoten wird ein anderer Namespace definiert.
Dann gibt es noch Namespace-Prefixes xmlns:abcd welche einen benutzerdefinierten Prefix für Knoten definiert. Diese sehen dann bspw. so aus
<abcd:Knoten> ......</abcd:Knoten>
und gehören dann automatisch dem vorher definierten Namespace an.

Details stehen hier
http://www.w3schools.com/xml/xml_namespaces.asp

Grüße Uwe