.NET10 Migration (#946)

Runtime and build
- Move all projects to .NET 10 with SDK-style project files and a shared
  Directory.Build.props (WIN/LINUX, x86/x64 defines)
- Load managed and unmanaged dependencies from libs/managed and
  libs/unmanaged through assembly and native library resolvers
- Compile party modes with Roslyn instead of CodeDom
- Update AppVeyor to the .NET 10 SDK and dotnet test
- Download the FFmpeg and gstreamer runtimes from the dependencies
  repository during the build
- Remove the VC++ 2015-2022 runtime check, no dependency needs it anymore

Graphics and windowing
- Replace the Direct3D 9 renderer with Direct3D 11 (Vortice)
- Pace Direct3D 11 frames with a frame latency waitable swap chain
- Move window, input and message boxes to SDL3
- Replace System.Drawing with SkiaSharp and WinForms with SDL3 and a
  software renderer

Video and audio
- Replace Acinerella with FFmpeg 8.1.3 (FFmpeg.AutoGen)
- Add hardware accelerated video decoding (D3D11VA, DXVA2, VideoToolbox,
  VAAPI, VDPAU) with software fallback
- Convert YUV video frames to RGB on the GPU in Direct3D 11 and OpenGL
- Add the video options HardwareDecoding, GpuColorConversion,
  DecoderThreads and VideoDownscaleResolution
- Update OpenAL to OpenTK 4 and NAudio recording to WasapiRecorder

Fixes
- Fix the song preview start and shorten the reporter buttons
- Fix a crash when opening the highscore without a selected song
- Use the options slide highlight in the party mode screens to avoid
  brightness flicker on VRR displays
- Disable GameInput in the x86 build, SDL3 crashes in GameInputCreate
  on 32-bit systems with the GameInput runtime installed
- Fix a truncation warning in PitchTracker
This commit is contained in:
McSchneidar authored and GitHub committed 2026-11-02 08:11:20 +01:00
1 parent 5767914372
commit cf2fa796e2
176 files changed
+5218 -8042

No files matched your search

+13 -4
View File
@@ -15,28 +15,37 @@
// along with Vocaluxe. If not, see <http://www.gnu.org/licenses/>.
#endregion
using System;
using System.Globalization;
using System.Text;
namespace VocaluxeLib
{
static class CEncoding
public static class CEncoding
{
static CEncoding()
{
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
}
public static Encoding Locale => OperatingSystem.IsWindows() ? Encoding.GetEncoding(CultureInfo.CurrentCulture.TextInfo.ANSICodePage) : Encoding.UTF8;
public static Encoding GetEncoding(this string encodingName)
{
switch (encodingName)
{
case "AUTO":
return Encoding.Default;
return Locale;
case "CP1250":
return Encoding.GetEncoding(1250);
case "CP1252":
return Encoding.GetEncoding(1252);
case "LOCALE":
return Encoding.Default;
return Locale;
case "UTF8":
return Encoding.UTF8;
default:
return Encoding.Default;
return Locale;
}
}
+9 -3
View File
@@ -22,6 +22,7 @@ using System.Globalization;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using SkiaSharp;
using VocaluxeLib.Log;
namespace VocaluxeLib
@@ -351,7 +352,7 @@ namespace VocaluxeLib
/// </summary>
/// <param name="filePath">Full path to image file</param>
/// <returns>Bitmap or null on error</returns>
public static Bitmap LoadBitmap(string filePath)
public static SKBitmap LoadBitmap(string filePath)
{
if (!File.Exists(filePath))
{
@@ -359,12 +360,17 @@ namespace VocaluxeLib
return null;
}
Bitmap bmp;
SKBitmap bmp;
try
{
bmp = new Bitmap(filePath);
bmp = SKBitmap.Decode(filePath);
}
catch (Exception)
{
bmp = null;
}
if (bmp == null)
{
CLog.Error("Error loading bitmap: " + filePath);
return null;
+11
View File
@@ -182,6 +182,17 @@ namespace VocaluxeLib
GstreamerSharp
}
public enum EVideoDownscaleResolution
{
TR_CONFIG_SCALING_360p = 360,
TR_CONFIG_SCALING_480p = 480,
TR_CONFIG_SCALING_720p = 720,
TR_CONFIG_SCALING_1080p = 1080,
TR_CONFIG_SCALING_1440p = 1440,
TR_CONFIG_SCALING_2160p = 2160,
TR_CONFIG_SCALING_DISABLED = -1
}
public enum EWebcamLib
{
AForgeNet
+34 -12
View File
@@ -19,10 +19,10 @@ using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Globalization;
using System.Linq;
using System.Text.RegularExpressions;
using SkiaSharp;
namespace VocaluxeLib
{
@@ -217,14 +217,14 @@ namespace VocaluxeLib
return list;
}
public static Size GetSize(this Bitmap bmp)
public static Size GetSize(this SKBitmap bmp)
{
return new Size(bmp.Width, bmp.Height);
}
public static Rectangle GetRect(this Bitmap bmp)
public static Rectangle GetRect(this SKBitmap bmp)
{
return Rectangle.Round(new Rectangle(0, 0, bmp.Width, bmp.Height));
return new Rectangle(0, 0, bmp.Width, bmp.Height);
}
/// <summary>
@@ -233,19 +233,19 @@ namespace VocaluxeLib
/// <param name="bmp"></param>
/// <param name="newSize"></param>
/// <returns>Resized bitmap or null on error</returns>
public static Bitmap Resize(this Bitmap bmp, Size newSize)
public static SKBitmap Resize(this SKBitmap bmp, Size newSize)
{
Bitmap result = null;
SKBitmap result = null;
try
{
//Create a new Bitmap with the new sizes
result = new Bitmap(newSize.Width, newSize.Height);
result = new SKBitmap(newSize.Width, newSize.Height, SKColorType.Bgra8888, SKAlphaType.Premul);
//Scale the texture
using (var g = Graphics.FromImage(result))
using (var canvas = new SKCanvas(result))
using (var image = SKImage.FromBitmap(bmp))
{
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.SmoothingMode = SmoothingMode.HighQuality;
g.DrawImage(bmp, result.GetRect());
canvas.Clear(SKColors.Transparent);
canvas.DrawImage(image, new SKRect(0, 0, newSize.Width, newSize.Height), new SKSamplingOptions(SKCubicResampler.Mitchell));
}
}
catch (Exception)
@@ -259,5 +259,27 @@ namespace VocaluxeLib
return result;
}
public static SKBitmap ToBgra(this SKBitmap bmp)
{
if (bmp.ColorType == SKColorType.Bgra8888 && bmp.AlphaType != SKAlphaType.Premul && bmp.RowBytes == bmp.Width * 4)
{
return bmp;
}
var result = new SKBitmap(new SKImageInfo(bmp.Width, bmp.Height, SKColorType.Bgra8888, SKAlphaType.Unpremul));
bmp.CopyPixelsTo(result);
return result;
}
public static void CopyPixelsTo(this SKBitmap bmp, SKBitmap target)
{
using (var pixmap = bmp.PeekPixels())
{
pixmap.ReadPixels(target.Info.WithSize(bmp.Width, bmp.Height), target.GetPixels(), target.RowBytes, 0, 0);
}
target.NotifyPixelsChanged();
}
}
}
}
+161
View File
@@ -0,0 +1,161 @@
#region license
// This file is part of Vocaluxe.
//
// Vocaluxe is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Vocaluxe is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Vocaluxe. If not, see <http://www.gnu.org/licenses/>.
#endregion
using System;
namespace VocaluxeLib
{
[Flags]
public enum Keys
{
None = 0,
Back = 8,
Tab = 9,
Clear = 12,
Enter = 13,
Return = 13,
ShiftKey = 16,
ControlKey = 17,
Menu = 18,
Pause = 19,
CapsLock = 20,
Escape = 27,
Space = 32,
PageUp = 33,
PageDown = 34,
End = 35,
Home = 36,
Left = 37,
Up = 38,
Right = 39,
Down = 40,
PrintScreen = 44,
Insert = 45,
Delete = 46,
D0 = 48,
D1 = 49,
D2 = 50,
D3 = 51,
D4 = 52,
D5 = 53,
D6 = 54,
D7 = 55,
D8 = 56,
D9 = 57,
A = 65,
B = 66,
C = 67,
D = 68,
E = 69,
F = 70,
G = 71,
H = 72,
I = 73,
J = 74,
K = 75,
L = 76,
M = 77,
N = 78,
O = 79,
P = 80,
Q = 81,
R = 82,
S = 83,
T = 84,
U = 85,
V = 86,
W = 87,
X = 88,
Y = 89,
Z = 90,
LWin = 91,
RWin = 92,
Apps = 93,
NumPad0 = 96,
NumPad1 = 97,
NumPad2 = 98,
NumPad3 = 99,
NumPad4 = 100,
NumPad5 = 101,
NumPad6 = 102,
NumPad7 = 103,
NumPad8 = 104,
NumPad9 = 105,
Multiply = 106,
Add = 107,
Separator = 108,
Subtract = 109,
Decimal = 110,
Divide = 111,
F1 = 112,
F2 = 113,
F3 = 114,
F4 = 115,
F5 = 116,
F6 = 117,
F7 = 118,
F8 = 119,
F9 = 120,
F10 = 121,
F11 = 122,
F12 = 123,
F13 = 124,
F14 = 125,
F15 = 126,
F16 = 127,
F17 = 128,
F18 = 129,
F19 = 130,
F20 = 131,
F21 = 132,
F22 = 133,
F23 = 134,
F24 = 135,
NumLock = 144,
Scroll = 145,
LShiftKey = 160,
RShiftKey = 161,
LControlKey = 162,
RControlKey = 163,
LMenu = 164,
RMenu = 165,
VolumeMute = 173,
VolumeDown = 174,
VolumeUp = 175,
MediaNextTrack = 176,
MediaPreviousTrack = 177,
MediaStop = 178,
MediaPlayPause = 179,
OemSemicolon = 186,
Oemplus = 187,
Oemcomma = 188,
OemMinus = 189,
OemPeriod = 190,
OemQuestion = 191,
Oemtilde = 192,
OemOpenBrackets = 219,
OemPipe = 220,
OemCloseBrackets = 221,
OemQuotes = 222,
OemBackslash = 226,
KeyCode = 0x0000FFFF,
Shift = 0x00010000,
Control = 0x00020000,
Alt = 0x00040000,
Modifiers = unchecked((int)0xFFFF0000)
}
}
-1
View File
@@ -19,7 +19,6 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Windows.Forms;
using System.Xml.Serialization;
using VocaluxeLib.Draw;
using VocaluxeLib.Log;
@@ -17,7 +17,6 @@
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using VocaluxeLib.Profile;
namespace VocaluxeLib.Menu
@@ -17,7 +17,6 @@
using System;
using System.Collections.Generic;
using System.Windows.Forms;
namespace VocaluxeLib.Menu
{
-1
View File
@@ -18,7 +18,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using System.Xml.Serialization;
using VocaluxeLib.Draw;
-1
View File
@@ -19,7 +19,6 @@ using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Windows.Forms;
using VocaluxeLib.Menu.SingNotes;
using VocaluxeLib.Menu.SongMenu;
-1
View File
@@ -17,7 +17,6 @@
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Xml.Serialization;
using VocaluxeLib.Songs;
@@ -19,7 +19,6 @@ using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Windows.Forms;
using VocaluxeLib.Draw;
using VocaluxeLib.PartyModes;
using VocaluxeLib.Songs;
@@ -18,7 +18,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using VocaluxeLib.Draw;
using VocaluxeLib.PartyModes;
using VocaluxeLib.Songs;
-1
View File
@@ -21,7 +21,6 @@ using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.Contracts;
using System.Drawing;
using System.Windows.Forms;
using System.Xml.Serialization;
using VocaluxeLib.Songs;
using VocaluxeLib.Xml;
+8 -192
View File
@@ -1,211 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">DebugWin</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{D2B6DDEF-E0E1-4DDF-A73A-E6ACEF5C95EC}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>VocaluxeLib</RootNamespace>
<AssemblyName>VocaluxeLib</AssemblyName>
<TargetFrameworkVersion>v4.8.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(OS)' == 'Windows_NT' ">
<TargetFrameworkProfile>
</TargetFrameworkProfile>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'DebugWin|AnyCPU'">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>..\Output\libs\managed</OutputPath>
<DefineConstants>TRACE;DEBUG;WIN</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
<CodeAnalysisRuleSet>..\CheckingRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>false</Prefer32Bit>
<LangVersion>9.0</LangVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'ReleaseWin|AnyCPU'">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>..\Output\libs\managed</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<UseVSHostingProcess>false</UseVSHostingProcess>
<DefineConstants>WIN</DefineConstants>
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
<Prefer32Bit>false</Prefer32Bit>
<DebugSymbols>true</DebugSymbols>
<LangVersion>9.0</LangVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'DebugLinux|AnyCPU'">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>..\Output\libs\managed</OutputPath>
<DefineConstants>TRACE;DEBUG;LINUX</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
<Prefer32Bit>false</Prefer32Bit>
<LangVersion>9.0</LangVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'ReleaseLinux|AnyCPU'">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>..\Output\libs\managed</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<UseVSHostingProcess>false</UseVSHostingProcess>
<DefineConstants>LINUX</DefineConstants>
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
<Prefer32Bit>false</Prefer32Bit>
<DebugSymbols>true</DebugSymbols>
<LangVersion>9.0</LangVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'InstallerWin|AnyCPU'">
<OutputPath>..\Output\libs\managed</OutputPath>
<DefineConstants>WIN</DefineConstants>
<Optimize>true</Optimize>
<PlatformTarget>AnyCPU</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>ManagedMinimumRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>false</Prefer32Bit>
<DebugType>pdbonly</DebugType>
<DebugSymbols>true</DebugSymbols>
<LangVersion>9.0</LangVersion>
<OutputPath>..\Output\libs\managed\</OutputPath>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.CSharp" />
<Reference Include="System" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.XML" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Serilog" Version="4.3.1" />
<PackageReference Include="Serilog" Version="4.4.0" />
<PackageReference Include="Serilog.Enrichers.Thread" Version="4.0.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="6.1.1" />
<PackageReference Include="Serilog.Sinks.File" Version="7.0.0" />
<PackageReference Include="Serilog.Sinks.TextWriter" Version="3.0.0" />
<PackageReference Include="SkiaSharp" Version="4.154.0" />
</ItemGroup>
<ItemGroup>
<Compile Include="CEncoding.cs" />
<Compile Include="CFading.cs" />
<Compile Include="CFont.cs" />
<Compile Include="Log\ELogLevel.cs" />
<Compile Include="Log\ShowReporterDelegate.cs" />
<Compile Include="Log\CLog.cs" />
<Compile Include="CVideoStream.cs" />
<Compile Include="Extensions.cs" />
<Compile Include="GlobalSuppressions.cs" />
<Compile Include="IBasic.cs" />
<Compile Include="Log\Enricher\CTimeStampFromStartEnricher.cs" />
<Compile Include="Log\Rolling\CLogFileRoller.cs" />
<Compile Include="Log\Serilog\CSilentLogger.cs" />
<Compile Include="Log\CLogFunctions.cs">
<Compile Update="Log\CLogFunctions.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>CLogFunctions.tt</DependentUpon>
</Compile>
<Compile Include="Log\CBenchmark.cs" />
<Compile Include="Menu\CBackground.cs" />
<Compile Include="CBasic.cs" />
<Compile Include="Menu\CButton.cs" />
<Compile Include="Menu\CEqualizer.cs" />
<Compile Include="CHelper.cs" />
<Compile Include="Menu\CInteraction.cs" />
<Compile Include="Menu\CLyric.cs" />
<Compile Include="Menu\CMenu.cs" />
<Compile Include="Menu\CMenuElementBase.cs" />
<Compile Include="Menu\CMenuParty.cs" />
<Compile Include="Menu\CMenuPartyNameSelection.cs" />
<Compile Include="Menu\CMenuPartySongSelection.cs" />
<Compile Include="Menu\CNameSelection.cs" />
<Compile Include="Menu\CObjectInteractions.cs" />
<Compile Include="Menu\COrderedDictionaryLite.cs" />
<Compile Include="Menu\CParticle.cs" />
<Compile Include="Menu\CParticleEffect.cs" />
<Compile Include="Menu\CPlaylist.cs" />
<Compile Include="Game\CPoints.cs" />
<Compile Include="Menu\CRatingPopup.cs" />
<Compile Include="Menu\CScreenSetting.cs" />
<Compile Include="Menu\CSelectSlide.cs" />
<Compile Include="Menu\CProgressBar.cs" />
<Compile Include="Menu\CStatic.cs" />
<Compile Include="Menu\CText.cs" />
<Compile Include="Draw\CTextureRef.cs" />
<Compile Include="Menu\IThemeable.cs" />
<Compile Include="Menu\SingNotes\CNoteBars.cs" />
<Compile Include="Utils\Combinatorics\CCombinations.cs" />
<Compile Include="Utils\ObjectPool.cs" />
<Compile Include="XmlStructs.cs" />
<Compile Include="Xml\CTypeExtensions.cs" />
<Compile Include="Xml\CXmlDeserializer.cs" />
<Compile Include="Xml\CXmlSerializer.cs" />
<Compile Include="Enums.cs" />
<Compile Include="Menu\IMenu.cs" />
<Compile Include="Menu\IMenuElement.cs" />
<Compile Include="Menu\SongMenu\CSongMenuList.cs" />
<Compile Include="Profile\CAvatar.cs" />
<Compile Include="Profile\CProfile.cs" />
<Compile Include="Songs\CLineBase.cs" />
<Compile Include="Songs\CBaseNote.cs" />
<Compile Include="Songs\CSongLine.cs" />
<Compile Include="Songs\CSongNote.cs" />
<Compile Include="Songs\CNotes.cs" />
<Compile Include="Menu\SingNotes\CSingNotes.cs" />
<Compile Include="Songs\CCategory.cs" />
<Compile Include="Songs\CSong.cs" />
<Compile Include="Menu\SongMenu\CSongMenuFactory.cs" />
<Compile Include="Menu\SongMenu\CSongMenuFramework.cs" />
<Compile Include="Menu\SongMenu\CSongMenuTileBoard.cs" />
<Compile Include="Menu\SongMenu\ISongMenu.cs" />
<Compile Include="Songs\CSongWriter.cs" />
<Compile Include="Songs\CSungLine.cs" />
<Compile Include="Songs\CSungNote.cs" />
<Compile Include="Songs\CVoice.cs" />
<Compile Include="Songs\CSongLoader.cs" />
<Compile Include="Structs.cs" />
<Compile Include="PartyModes\CPartyMode.cs" />
<Compile Include="PartyModes\CPartyModeNormal.cs" />
<Compile Include="PartyModes\IPartyMode.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Utils\CWavFile.cs" />
<Compile Include="Utils\Player\CSongPlayer.cs" />
<Compile Include="Utils\Player\CSoundPlayer.cs" />
<Compile Include="Xml\SFieldInfo.cs" />
</ItemGroup>
<ItemGroup>
<Content Include="Log\CLogFunctions.tt">
<None Update="Log\CLogFunctions.tt">
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>CLogFunctions.cs</LastGenOutput>
</Content>
</None>
</ItemGroup>
<ItemGroup>
<Service Include="{508349B6-6B84-4DF5-91F0-309BEEBAD82D}" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
<PostBuildEvent>
</PostBuildEvent>
</PropertyGroup>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
</Project>