Zine.net online

Witaj na Zine.net online Zaloguj się | Rejestracja | Pomoc
w Szukaj

arkadiusz.wasniewski

Pobranie projektów rozwiązania czyli Regex w akcji

Asumpt do poniższego rozwiązania dostarczył skrypt PowerShell, który kompiluje projekty pewnego mojego rozwiązania, i gdzie zapałałem chęcią automatycznego uaktualnienia numeru wersji we wszystkich plikach AssemblyInfo.cs. Ale gdzież są te wszystkie pliki? No w projektach…

Najprostszy sposób dotarcia do projektów to odczytanie pliku .sln. Hm… ale to oznacza analizowanie zawartości. Z pomocą przyszły wyrażenia regularne oraz świadomość istnienia jasno określonej struktury pliku .sln.

Project\("\{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC\}"\) = "(?<projectName>[^"]+)", "(?<projectFolder>[^"]+)", "(?<projectGuid>[^"]+)"\nEndProject

Oczywiście kilka słów wyjaśnienia. Po pierwsze wszystkie projekty rozwiązania jak i również foldery (Solution Folders) są umieszczane w sekcji zaczynającej się od słów Project a kończącej się na EndProject. Elementy będące projektami są oznaczone odpowiednim identyfikatorem Guid (konkretnie {FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}). Następnie w cudzysłowach danej sekcji mamy kolejno nazwę projektu, ścieżkę względną do projektu oraz unikalny identyfikator Guid przypisany do danego projektu. Dla ułatwienia pobierania informacji zastosowałem grupy nazwane. Czas na prosty przykład użycia:

$pattern =
    "Project\(`"\{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC\}`"\) = " +
    "`"(?<projectName>[^`"]+)`", " +
    "`"(?<projectFolder>[^`"]+)`", " +
    "`"(?<projectGuid>[^`"]+)`"\r\nEndProject"
$regex = [regex] $pattern
$solution = [System.IO.File]::ReadAllText('d:\Solution\MySolution.sln')
$regex.Matches($solution) | ForEach-Object {
    Write-Host $_.Groups['projectName']
    Write-Host $_.Groups['projectFolder']
    Write-Host $_.Groups['projectGuid']
    Write-Host
}

Ze względu na składnię PowerShell wzorzec wyrażenia regularnego został nieco zmodyfikowany.

PS. Oczywiście można również zastosować prostsze wyrażenie regularne:

\{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC\}"\) = "(?<projectName>[^"]+)", "(?<projectFolder>[^"]+)", "(?<projectGuid>[^"]+)

lub też bardziej odporne na potencjalne błędy (czy aby na pewno takie będą?):

\{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC\}"\)\s*=\s*"(?<projectName>[^"]+)",\s*"(?<projectFolder>[^"]+)",\s*"(?<projectGuid>[^"]+)

Ale to już sztuka dla sztuki.

Opublikowane 8 października 2009 00:17 przez arkadiusz.wasniewski

Komentarze:

 

merdacz said:

Jeśli chodzi o numer wersji to o ile ma być on wspólny dla wszystkich projektów danego rozwiązania (a to wynika chyba z automatycznego sposobu aktualizacji) to wydaje mi się łatwiej stworzyć oddzielne "ProductAssemblyInfo" zawierające wspólne sekcje dla wszystkich projektów (w tym numer wersji) umieszczone np. w głównym katalogu solution i tam dokonywac stosownych zmian. Co o tym sądzisz?

BTW. Możesz napisać coś więcej o samej inkrementacji wersji? Czy korzystasz do tego może z MSBuildTasks?

października 8, 2009 07:40
 

arkadiusz.wasniewski said:

Jedno wspólne AssemblyInfo.cs tak, ale pod warunkiem, iż możesz vel chcesz mieć identyczne wartości dla atrybutów AssemblyTitle oraz AssemblyDescription. Wtedy faktycznie wystarczy zrobić łącze z każdego projektu do tego pliku. Innym utrudnieniem przy zastosowaniu jednego pliku AssemblyInfo.cs jest stosowanie class wewnętrznych (internal). Aby móc je testować umieszczam w niektórych projektach dodatkowo atrybut InternalsVisibleTo.

Jeśli chodzi o zwiększanie numeru to wykorzystuję bieżący numer z repozytorium Subversion.

Nie korzystam z NAnt ani z MSBuild (przynajmniej bezpośrednio). Cały skrypt zbudowany mam w PowerShell.

października 8, 2009 09:33
 

Wojciech Gebczyk said:

Ja uzywam takiego rozwiazania:

AssemblyInfoBase.cs (linkowane w kazdym projekcie):

-----

using System.Reflection;

using System.Runtime.InteropServices;

#if DEBUG

[assembly: AssemblyConfiguration("Debug")]

#else

[assembly: AssemblyConfiguration("Release")]

#endif

[assembly: AssemblyCompany("...")]

[assembly: AssemblyCopyright("Copyright © ...")]

[assembly: AssemblyVersion("1.1.1.*")]

[assembly: AssemblyFileVersion("1.1.1.3")]

[assembly: ComVisible(false)]

-----

oraz kazdy z proj ma osobny AssemblyInfo.cs w styul:

-----

using System.Reflection;

[assembly: AssemblyTitle("...")]

[assembly: AssemblyDescription("...")]

[assembly: AssemblyProduct("...")]

-----

bardzo wygodne.

Jesli robie projekt i chce miesc 2 niezalezne wersjonowania DLL, to robie 2 "AssemblyInfoBase.cs" itd...

października 8, 2009 09:52
 

arkadiusz.wasniewski said:

O a to rozwiązuje od razu kilka problemów i mój skrypt można wywalić do kosza ;-)

października 8, 2009 10:01
 

dotnetomaniak.pl said:

Dziękujemy za publikację - Trackback z dotnetomaniak.pl

października 8, 2009 18:43
Komentarze anonimowe wyłączone
W oparciu o Community Server (Personal Edition), Telligent Systems