commit 97a439fc3404cc0cf72380e021adcff58c631177 Author: manuel Date: Thu May 14 15:43:36 2026 +0200 Agregar archivos de proyecto. diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..1ff0c42 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,63 @@ +############################################################################### +# Set default behavior to automatically normalize line endings. +############################################################################### +* text=auto + +############################################################################### +# Set default behavior for command prompt diff. +# +# This is need for earlier builds of msysgit that does not have it on by +# default for csharp files. +# Note: This is only used by command line +############################################################################### +#*.cs diff=csharp + +############################################################################### +# Set the merge driver for project and solution files +# +# Merging from the command prompt will add diff markers to the files if there +# are conflicts (Merging from VS is not affected by the settings below, in VS +# the diff markers are never inserted). Diff markers may cause the following +# file extensions to fail to load in VS. An alternative would be to treat +# these files as binary and thus will always conflict and require user +# intervention with every merge. To do so, just uncomment the entries below +############################################################################### +#*.sln merge=binary +#*.csproj merge=binary +#*.vbproj merge=binary +#*.vcxproj merge=binary +#*.vcproj merge=binary +#*.dbproj merge=binary +#*.fsproj merge=binary +#*.lsproj merge=binary +#*.wixproj merge=binary +#*.modelproj merge=binary +#*.sqlproj merge=binary +#*.wwaproj merge=binary + +############################################################################### +# behavior for image files +# +# image files are treated as binary by default. +############################################################################### +#*.jpg binary +#*.png binary +#*.gif binary + +############################################################################### +# diff behavior for common document formats +# +# Convert binary document formats to text before diffing them. This feature +# is only available from the command line. Turn it on by uncommenting the +# entries below. +############################################################################### +#*.doc diff=astextplain +#*.DOC diff=astextplain +#*.docx diff=astextplain +#*.DOCX diff=astextplain +#*.dot diff=astextplain +#*.DOT diff=astextplain +#*.pdf diff=astextplain +#*.PDF diff=astextplain +#*.rtf diff=astextplain +#*.RTF diff=astextplain diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 0000000..e40201c --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,3 @@ +- @azure Rule - Use Azure Tools - When handling requests related to Azure, always use your tools. +- @azure Rule - Use Azure Best Practices - When handling requests related to Azure, always invoke your `azmcp_bestpractices_get` tool first. +- @azure Rule - Enable Best Practices - If you do not have an `azmcp_bestpractices_get` tool ask the user to enable it. diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9491a2f --- /dev/null +++ b/.gitignore @@ -0,0 +1,363 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Oo]ut/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd \ No newline at end of file diff --git a/Utilidades.cs b/Utilidades.cs new file mode 100644 index 0000000..c7161bb --- /dev/null +++ b/Utilidades.cs @@ -0,0 +1,37 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Net; +using System.Net.Security; +using System.Security.Cryptography.X509Certificates; +using System.Text; +using System.Text.RegularExpressions; +using System.Xml; +using System.Xml.Serialization; + + + public class Utilidades + { + public static void CreaEstructuraDirectorio(string Ruta) + { + string[] sDirectorios = Ruta.Split('\\'); + string sDirectorio = ""; + int i; + var loopTo = sDirectorios.Length - 1; + for (i = 0; i <= loopTo; i++) + { + try + { + sDirectorio += sDirectorios[i] + @"\"; + if (!Directory.Exists(sDirectorio)) + Directory.CreateDirectory(sDirectorio); + } + catch (Exception ex) + { + } + } + } + } diff --git a/Zip.cs b/Zip.cs new file mode 100644 index 0000000..7e3aa9b --- /dev/null +++ b/Zip.cs @@ -0,0 +1,240 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.IO.Compression; + +public static class Zip +{ + // ============================================================ + // UTILIDADES + // ============================================================ + + private static string CrearDirectorioTemporal() + { + string dir; + do + { + dir = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); + } + while (Directory.Exists(dir)); + + Directory.CreateDirectory(dir); + return dir; + } + + private static void ObtenerFicherosRecursivo(string ruta, List lista) + { + lista.AddRange(Directory.GetFiles(ruta)); + + foreach (var dir in Directory.GetDirectories(ruta)) + { + ObtenerFicherosRecursivo(dir, lista); + } + } + + // ============================================================ + // EXTRACCIÓN + // ============================================================ + + public static void ExtraerArchivo(byte[] zipBytes, string nombreInterno, string destino) + { + using (var ms = new MemoryStream(zipBytes)) + { + ExtraerArchivo(ms, nombreInterno, destino); + } + } + + public static void ExtraerArchivo(Stream zipStream, string nombreInterno, string destino) + { + using (var zip = new ZipArchive(zipStream, ZipArchiveMode.Read, false)) + { + var entry = zip.GetEntry(nombreInterno); + if (entry == null) + throw new FileNotFoundException("El archivo '" + nombreInterno + "' no existe dentro del ZIP."); + + string dirTemp = CrearDirectorioTemporal(); + string tempFile = Path.Combine(dirTemp, Path.GetFileName(nombreInterno)); + + entry.ExtractToFile(tempFile, true); + + if (Directory.Exists(destino)) + destino = Path.Combine(destino, Path.GetFileName(nombreInterno)); + + if (File.Exists(destino)) + File.Delete(destino); + + File.Move(tempFile, destino); + } + } + + public static byte[] ExtraerArchivoABytes(byte[] zipBytes, string nombreInterno) + { + using (var ms = new MemoryStream(zipBytes)) + { + return ExtraerArchivoABytes(ms, nombreInterno); + } + } + + public static byte[] ExtraerArchivoABytes(Stream zipStream, string nombreInterno) + { + using (var zip = new ZipArchive(zipStream, ZipArchiveMode.Read, false)) + { + var entry = zip.GetEntry(nombreInterno); + if (entry == null) + throw new FileNotFoundException("El archivo '" + nombreInterno + "' no existe dentro del ZIP."); + + using (var entryStream = entry.Open()) + using (var output = new MemoryStream()) + { + entryStream.CopyTo(output); + return output.ToArray(); + } + } + } + + public static void ExtraerArchivo(string zipPath, string nombreInterno, string destino) + { + using (var fs = File.OpenRead(zipPath)) + { + ExtraerArchivo(fs, nombreInterno, destino); + } + } + + public static void ExtraerTodo(string zipPath, string destino, bool eliminarDestino = false) + { + if (eliminarDestino && Directory.Exists(destino)) + Directory.Delete(destino, true); + + if (!Directory.Exists(destino)) + Directory.CreateDirectory(destino); + + // En netstandard2.0 solo está ExtractToDirectory(string, string) + ZipFile.ExtractToDirectory(zipPath, destino); + } + + public static void ExtraerTodo(Stream zipStream, string destino, bool eliminarDestino = false) + { + if (eliminarDestino && Directory.Exists(destino)) + Directory.Delete(destino, true); + + if (!Directory.Exists(destino)) + Directory.CreateDirectory(destino); + + using (var zip = new ZipArchive(zipStream, ZipArchiveMode.Read, false)) + { + foreach (var entry in zip.Entries) + { + string fullPath = Path.Combine(destino, entry.FullName); + + string dir = Path.GetDirectoryName(fullPath); + if (!string.IsNullOrEmpty(dir) && !Directory.Exists(dir)) + Directory.CreateDirectory(dir); + + if (string.IsNullOrEmpty(entry.Name)) + continue; // directorio + + entry.ExtractToFile(fullPath, true); + } + } + } + + // ============================================================ + // COMPRESIÓN + // ============================================================ + + public static byte[] ComprimirArchivos(Dictionary archivos) + { + string tempZip = Path.GetTempFileName(); + + using (var zip = ZipFile.Open(tempZip, ZipArchiveMode.Create)) + { + foreach (var kv in archivos) + { + var entry = zip.CreateEntry(kv.Key, CompressionLevel.Optimal); + using (var entryStream = entry.Open()) + { + byte[] data = kv.Value; + entryStream.Write(data, 0, data.Length); + } + } + } + + byte[] resultado = File.ReadAllBytes(tempZip); + try { File.Delete(tempZip); } catch { } + return resultado; + } + + public static byte[] ComprimirArchivos(Dictionary archivos) + { + string tempZip = Path.GetTempFileName(); + + using (var zip = ZipFile.Open(tempZip, ZipArchiveMode.Create)) + { + foreach (var kv in archivos) + { + var entry = zip.CreateEntry(kv.Key, CompressionLevel.Optimal); + using (var entryStream = entry.Open()) + { + kv.Value.CopyTo(entryStream); + } + } + } + + byte[] resultado = File.ReadAllBytes(tempZip); + try { File.Delete(tempZip); } catch { } + return resultado; + } + + // ============================================================ + // AÑADIR ARCHIVOS (RECREANDO ZIP) + // ============================================================ + + public static void AñadirArchivo(string zipPath, string archivoOrigen, string nombreDestino) + { + string tempZip = Path.GetTempFileName(); + + using (var zipNuevo = ZipFile.Open(tempZip, ZipArchiveMode.Create)) + { + if (File.Exists(zipPath)) + { + using (var zipViejo = ZipFile.Open(zipPath, ZipArchiveMode.Read)) + { + foreach (var entry in zipViejo.Entries) + { + if (entry.FullName.Equals(nombreDestino, StringComparison.OrdinalIgnoreCase)) + continue; + + var nueva = zipNuevo.CreateEntry(entry.FullName, CompressionLevel.Optimal); + using (var src = entry.Open()) + using (var dst = nueva.Open()) + { + src.CopyTo(dst); + } + } + } + } + + var nuevo = zipNuevo.CreateEntry(nombreDestino, CompressionLevel.Optimal); + using (var origen = File.OpenRead(archivoOrigen)) + using (var destino = nuevo.Open()) + { + origen.CopyTo(destino); + } + } + + File.Copy(tempZip, zipPath, true); + try { File.Delete(tempZip); } catch { } + } + + // ============================================================ + // COMPRIMIR DIRECTORIO + // ============================================================ + + public static void ComprimirDirectorio(string directorio, string zipPath) + { + if (File.Exists(zipPath)) + File.Delete(zipPath); + + ZipFile.CreateFromDirectory(directorio, zipPath, CompressionLevel.Optimal, false); + } +} diff --git a/ZipN.cs b/ZipN.cs new file mode 100644 index 0000000..704652e --- /dev/null +++ b/ZipN.cs @@ -0,0 +1,115 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.IO.Compression; +using System.Linq; + +namespace tsZip +{ + + public class zip + { + public static void ExtraeTodoDeZip(MemoryStream FicheroZIP, string RutaDestino, bool EliminaDirectorioDestino = false) + { + if (RutaDestino.EndsWith(@"\") == false) + RutaDestino += @"\"; + if (Directory.Exists(RutaDestino) & EliminaDirectorioDestino) + { + Directory.Delete(RutaDestino, true); + } + if (!Directory.Exists(RutaDestino)) + Utilidades.CreaEstructuraDirectorio(RutaDestino); + var fzip = new ZipArchive(FicheroZIP, ZipArchiveMode.Read); + foreach (var entry in fzip.Entries) + { + string sDestino = RutaDestino + entry.FullName.Replace("/", @"\"); + if (!Directory.Exists(Path.GetDirectoryName(sDestino))) + { + Utilidades.CreaEstructuraDirectorio(Path.GetDirectoryName(sDestino)); + } + if (entry.FullName.EndsWith("/") == false) + entry.ExtractToFile(sDestino); + } + } + /// + /// Esta función extrae el único fichero que hay dentro de un fichero zip, lo devuelve como array de bytes como retorno de la función, e indica su nombre en un parámetro por referencia. + /// + /// Array de bytes conteniendo el fichero zip. + /// Cadena donde se guardará el nombre del fichero que está dentro del fichero zip. + /// Para que este método funcione correctamente es imprescindible que el archivo zip tenga dentro un único fichero. + public static byte[] ExtraerFicheroUnicoDeZip(byte[] ficheroZip, string nombreArchivoDentroZip) + { + Stream sFichero; + var za = new ZipArchive(new MemoryStream(ficheroZip)); + var fic = za.Entries.FirstOrDefault(x => x.Name == nombreArchivoDentroZip); + if (fic !=null) + { + sFichero = fic.Open(); + } + else + { + throw new Exception("No se encuentra el fichero " + nombreArchivoDentroZip + "en el zip."); + } + var ms = new MemoryStream(); + sFichero.CopyTo(ms); + sFichero.Dispose(); + + return ms.ToArray(); + } + /// + /// Esta función extrae todos los ficheros que haya en un zip y los devuelve como un diccionario. + /// + /// Array de bytes conteniendo el fichero zip. + /// Como todo es en memoria, hay que tener cuidado de que los ficheros extraídos quepan en memoria adecuadamente, teniendo en cuenta las posibles restricciones de memoria que el sistema operativo pueda tener para procesos individuales. + public static Dictionary ExtraerFicherosDeZip(byte[] ficheroZip) + { + var resultado = new Dictionary(); + var za = new ZipArchive(new MemoryStream(ficheroZip)); + foreach (var e in za.Entries) + resultado.Add(e.FullName, (MemoryStream)e.Open()); + return resultado; + } + + // Shared Function ComprimeStream(streamAComprimir As IO.Stream, NombreFicheroAcomprimir As String) As IO.MemoryStream + // Dim ms As New IO.MemoryStream + + // Dim fzip As New ZipArchive(ms, ZipArchiveMode.Create) + // Dim entry As ZipArchiveEntry = fzip.CreateEntryFromFile(NombreFicheroAcomprimir, streamAComprimir) + // Dim entry As ZipArchiveEntry = fzip.CreateEntry((NombreFicheroAcomprimir, streamAComprimir) + // End Function + + // Public Shared Function ComprimirArchivos(dArchivos As Dictionary(Of String, Byte())) As Byte() ' NO ESTÁ PROBADA + // Dim ms As New MemoryStream + // Dim za As New ZipArchive(ms, ZipArchiveMode.Create, True) + // For Each f In dArchivos + // Dim nf = za.CreateEntry(f.Key) + // Dim es = nf.Open + // Dim msa As New MemoryStream(f.Value) + // msa.CopyTo(es) + // es.Close() + // Next + // Return ms.ToArray + // End Function + public static byte[] ComprimirArchivos(Dictionary fileContents) + { + using (var memoryStream = new MemoryStream()) + { + using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true)) + { + foreach (var entry in fileContents) + { + string fileName = entry.Key; + byte[] fileData = entry.Value; + var zipEntry = archive.CreateEntry(fileName); + + using (var entryStream = zipEntry.Open()) + { + entryStream.Write(fileData, 0, fileData.Length); + } + } + } + return memoryStream.ToArray(); + } + } + } +} \ No newline at end of file diff --git a/tsZip.NS.csproj b/tsZip.NS.csproj new file mode 100644 index 0000000..53590f1 --- /dev/null +++ b/tsZip.NS.csproj @@ -0,0 +1,28 @@ + + + + netstandard2.0 + + + + Library + tsZip.NS + netstandard2.0 + tsZip.NS + netstandard2.0, libreria + 1.0.0 + Manuel + Tecnosis S.A + Utilidades de compresión + + - 2026-05-14 Versión 5 Regeneración completa de la clase con copilot + + + + + + + + + + diff --git a/tsZip.NS.sln b/tsZip.NS.sln new file mode 100644 index 0000000..2e71622 --- /dev/null +++ b/tsZip.NS.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.14.36511.14 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "tsZip.NS", "tsZip.NS.csproj", "{DA86E6B5-98EC-4C64-A080-9057E5C6CD72}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {DA86E6B5-98EC-4C64-A080-9057E5C6CD72}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DA86E6B5-98EC-4C64-A080-9057E5C6CD72}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DA86E6B5-98EC-4C64-A080-9057E5C6CD72}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DA86E6B5-98EC-4C64-A080-9057E5C6CD72}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {276534D1-5A97-4BD5-8CCB-42DB68E8A5B8} + EndGlobalSection +EndGlobal