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-ID: 318542

Url: https://administrator.de/forum/csproj-mit-powershell-aendern-318542.html

Ausgedruckt am: 22.12.2024 um 09:12 Uhr

131223
131223 20.10.2016 um 14:39:55 Uhr
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.
Sirius91
Sirius91 20.10.2016 um 14:49:06 Uhr
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
131223
131223 20.10.2016 um 14:55:25 Uhr
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.
colinardo
Lösung colinardo 20.10.2016 aktualisiert um 15:03:59 Uhr
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
Sirius91
Sirius91 20.10.2016 um 15:12:47 Uhr
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!
colinardo
colinardo 20.10.2016 aktualisiert um 15:23:12 Uhr
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
Sirius91
Sirius91 21.10.2016 um 10:48:16 Uhr
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!
colinardo
colinardo 21.10.2016 aktualisiert um 10:57:18 Uhr
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