diff --git a/src/FillInTheTextBot.DialogflowImporter/FillInTheTextBot.DialogflowImporter.csproj b/src/FillInTheTextBot.DialogflowImporter/FillInTheTextBot.DialogflowImporter.csproj new file mode 100644 index 00000000..e9c3107a --- /dev/null +++ b/src/FillInTheTextBot.DialogflowImporter/FillInTheTextBot.DialogflowImporter.csproj @@ -0,0 +1,27 @@ + + + + Exe + net6.0 + enable + enable + FillInTheTextBot.DialogflowImporter + FillInTheTextBot.DialogflowImporter + + + + + + + + + + + + + + PreserveNewest + + + + diff --git a/src/FillInTheTextBot.DialogflowImporter/ImporterSettings.cs b/src/FillInTheTextBot.DialogflowImporter/ImporterSettings.cs new file mode 100644 index 00000000..e807abaf --- /dev/null +++ b/src/FillInTheTextBot.DialogflowImporter/ImporterSettings.cs @@ -0,0 +1,17 @@ +namespace FillInTheTextBot.DialogflowImporter; + +public class ImporterSettings +{ + public string? ZipPath { get; set; } + public string Mode { get; set; } = "Restore"; + public bool Train { get; set; } = true; + public string? JsonPath { get; set; } + public List Targets { get; set; } = new(); +} + +public class TargetAgent +{ + public string? ProjectId { get; set; } + public string? Region { get; set; } + public string? JsonPath { get; set; } +} diff --git a/src/FillInTheTextBot.DialogflowImporter/Program.cs b/src/FillInTheTextBot.DialogflowImporter/Program.cs new file mode 100644 index 00000000..317cca9c --- /dev/null +++ b/src/FillInTheTextBot.DialogflowImporter/Program.cs @@ -0,0 +1,106 @@ +using FillInTheTextBot.DialogflowImporter; +using Google.Apis.Auth.OAuth2; +using Google.Cloud.Dialogflow.V2; +using Google.Protobuf; +using Grpc.Auth; +using Microsoft.Extensions.Configuration; + +var config = new ConfigurationBuilder() + .SetBasePath(AppContext.BaseDirectory) + .AddJsonFile("appsettings.json", optional: true) + .AddEnvironmentVariables(prefix: "DFIMPORT_") + .AddCommandLine(args) + .Build(); + +var settings = config.Get() ?? new ImporterSettings(); + +if (string.IsNullOrWhiteSpace(settings.ZipPath) || !File.Exists(settings.ZipPath)) +{ + Console.Error.WriteLine($"Zip not found: '{settings.ZipPath}'. Pass --ZipPath=path/to/agent.zip or set it in appsettings.json."); + return 1; +} + +if (settings.Targets is null || settings.Targets.Count == 0) +{ + Console.Error.WriteLine("No targets configured. Add entries to 'Targets' in appsettings.json."); + return 1; +} + +var zipBytes = await File.ReadAllBytesAsync(settings.ZipPath); +var content = ByteString.CopyFrom(zipBytes); +Console.WriteLine($"Loaded {zipBytes.Length} bytes from {settings.ZipPath}"); +Console.WriteLine($"Mode: {settings.Mode}, Train: {settings.Train}, Targets: {settings.Targets.Count}"); + +var failures = 0; +foreach (var target in settings.Targets) +{ + if (string.IsNullOrWhiteSpace(target.ProjectId)) + { + Console.Error.WriteLine("Skipping target with empty ProjectId."); + failures++; + continue; + } + + var region = string.IsNullOrWhiteSpace(target.Region) ? "global" : target.Region!; + var endpoint = region == "global" ? "dialogflow.googleapis.com:443" : $"{region}-dialogflow.googleapis.com:443"; + var agentName = region == "global" + ? $"projects/{target.ProjectId}/agent" + : $"projects/{target.ProjectId}/locations/{region}/agent"; + + Console.WriteLine(); + Console.WriteLine($"=== {target.ProjectId} ({region}) ==="); + + try + { + var jsonPath = !string.IsNullOrWhiteSpace(target.JsonPath) ? target.JsonPath : settings.JsonPath; + var builder = new AgentsClientBuilder { Endpoint = endpoint }; + if (!string.IsNullOrWhiteSpace(jsonPath)) + { + var credential = GoogleCredential.FromFile(jsonPath).CreateScoped(AgentsClient.DefaultScopes); + builder.ChannelCredentials = credential.ToChannelCredentials(); + } + var client = await builder.BuildAsync(); + + if (string.Equals(settings.Mode, "Import", StringComparison.OrdinalIgnoreCase)) + { + Console.WriteLine("Importing (merge)..."); + var op = await client.ImportAgentAsync(new ImportAgentRequest + { + Parent = agentName[..agentName.LastIndexOf("/agent", StringComparison.Ordinal)], + AgentContent = content + }); + await op.PollUntilCompletedAsync(); + } + else + { + Console.WriteLine("Restoring (replace)..."); + var op = await client.RestoreAgentAsync(new RestoreAgentRequest + { + Parent = agentName[..agentName.LastIndexOf("/agent", StringComparison.Ordinal)], + AgentContent = content + }); + await op.PollUntilCompletedAsync(); + } + Console.WriteLine("Upload complete."); + + if (settings.Train) + { + Console.WriteLine("Training..."); + var trainOp = await client.TrainAgentAsync(new TrainAgentRequest + { + Parent = agentName[..agentName.LastIndexOf("/agent", StringComparison.Ordinal)] + }); + await trainOp.PollUntilCompletedAsync(); + Console.WriteLine("Training complete."); + } + } + catch (Exception ex) + { + failures++; + Console.Error.WriteLine($"FAILED for {target.ProjectId}: {ex.Message}"); + } +} + +Console.WriteLine(); +Console.WriteLine(failures == 0 ? "All targets processed successfully." : $"Done with {failures} failure(s)."); +return failures == 0 ? 0 : 2; diff --git a/src/FillInTheTextBot.DialogflowImporter/appsettings.json b/src/FillInTheTextBot.DialogflowImporter/appsettings.json new file mode 100644 index 00000000..efb39165 --- /dev/null +++ b/src/FillInTheTextBot.DialogflowImporter/appsettings.json @@ -0,0 +1,17 @@ +{ + "ZipPath": "Dialogflow/FillInTheTextBot-eu.zip", + "Mode": "Restore", + "Train": true, + "JsonPath": "secrets/dialogflow-admin.json", + "Targets": [ + { + "ProjectId": "your-project-id-global", + "Region": "global" + }, + { + "ProjectId": "your-project-id-eu", + "Region": "europe-west1", + "JsonPath": "secrets/dialogflow-eu.json" + } + ] +} diff --git a/src/FillInTheTextBot.sln b/src/FillInTheTextBot.sln index 12cc9c99..368954fb 100644 --- a/src/FillInTheTextBot.sln +++ b/src/FillInTheTextBot.sln @@ -27,52 +27,150 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FillInTheTextBot.Messengers EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FillInTheTextBot.Messengers.Marusia", "FillInTheTextBot.Messengers.Marusia\FillInTheTextBot.Messengers.Marusia.csproj", "{D555A356-6BBF-426F-B7ED-A55CAC505753}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FillInTheTextBot.DialogflowImporter", "FillInTheTextBot.DialogflowImporter\FillInTheTextBot.DialogflowImporter.csproj", "{21CD75E5-1155-45E2-97C8-ACA00C60AAA2}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {57253AE6-A026-4050-A04B-4B3A5969BE01}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {57253AE6-A026-4050-A04B-4B3A5969BE01}.Debug|Any CPU.Build.0 = Debug|Any CPU + {57253AE6-A026-4050-A04B-4B3A5969BE01}.Debug|x64.ActiveCfg = Debug|Any CPU + {57253AE6-A026-4050-A04B-4B3A5969BE01}.Debug|x64.Build.0 = Debug|Any CPU + {57253AE6-A026-4050-A04B-4B3A5969BE01}.Debug|x86.ActiveCfg = Debug|Any CPU + {57253AE6-A026-4050-A04B-4B3A5969BE01}.Debug|x86.Build.0 = Debug|Any CPU {57253AE6-A026-4050-A04B-4B3A5969BE01}.Release|Any CPU.ActiveCfg = Release|Any CPU {57253AE6-A026-4050-A04B-4B3A5969BE01}.Release|Any CPU.Build.0 = Release|Any CPU + {57253AE6-A026-4050-A04B-4B3A5969BE01}.Release|x64.ActiveCfg = Release|Any CPU + {57253AE6-A026-4050-A04B-4B3A5969BE01}.Release|x64.Build.0 = Release|Any CPU + {57253AE6-A026-4050-A04B-4B3A5969BE01}.Release|x86.ActiveCfg = Release|Any CPU + {57253AE6-A026-4050-A04B-4B3A5969BE01}.Release|x86.Build.0 = Release|Any CPU {2A901FDB-238B-4510-BB1D-6D169361FA60}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {2A901FDB-238B-4510-BB1D-6D169361FA60}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2A901FDB-238B-4510-BB1D-6D169361FA60}.Debug|x64.ActiveCfg = Debug|Any CPU + {2A901FDB-238B-4510-BB1D-6D169361FA60}.Debug|x64.Build.0 = Debug|Any CPU + {2A901FDB-238B-4510-BB1D-6D169361FA60}.Debug|x86.ActiveCfg = Debug|Any CPU + {2A901FDB-238B-4510-BB1D-6D169361FA60}.Debug|x86.Build.0 = Debug|Any CPU {2A901FDB-238B-4510-BB1D-6D169361FA60}.Release|Any CPU.ActiveCfg = Release|Any CPU {2A901FDB-238B-4510-BB1D-6D169361FA60}.Release|Any CPU.Build.0 = Release|Any CPU + {2A901FDB-238B-4510-BB1D-6D169361FA60}.Release|x64.ActiveCfg = Release|Any CPU + {2A901FDB-238B-4510-BB1D-6D169361FA60}.Release|x64.Build.0 = Release|Any CPU + {2A901FDB-238B-4510-BB1D-6D169361FA60}.Release|x86.ActiveCfg = Release|Any CPU + {2A901FDB-238B-4510-BB1D-6D169361FA60}.Release|x86.Build.0 = Release|Any CPU {795BC172-BD86-4A15-BBDD-A9696F7DEE27}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {795BC172-BD86-4A15-BBDD-A9696F7DEE27}.Debug|Any CPU.Build.0 = Debug|Any CPU + {795BC172-BD86-4A15-BBDD-A9696F7DEE27}.Debug|x64.ActiveCfg = Debug|Any CPU + {795BC172-BD86-4A15-BBDD-A9696F7DEE27}.Debug|x64.Build.0 = Debug|Any CPU + {795BC172-BD86-4A15-BBDD-A9696F7DEE27}.Debug|x86.ActiveCfg = Debug|Any CPU + {795BC172-BD86-4A15-BBDD-A9696F7DEE27}.Debug|x86.Build.0 = Debug|Any CPU {795BC172-BD86-4A15-BBDD-A9696F7DEE27}.Release|Any CPU.ActiveCfg = Release|Any CPU {795BC172-BD86-4A15-BBDD-A9696F7DEE27}.Release|Any CPU.Build.0 = Release|Any CPU + {795BC172-BD86-4A15-BBDD-A9696F7DEE27}.Release|x64.ActiveCfg = Release|Any CPU + {795BC172-BD86-4A15-BBDD-A9696F7DEE27}.Release|x64.Build.0 = Release|Any CPU + {795BC172-BD86-4A15-BBDD-A9696F7DEE27}.Release|x86.ActiveCfg = Release|Any CPU + {795BC172-BD86-4A15-BBDD-A9696F7DEE27}.Release|x86.Build.0 = Release|Any CPU {0460EC82-4E93-4C91-8372-BF1CEFA51D91}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {0460EC82-4E93-4C91-8372-BF1CEFA51D91}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0460EC82-4E93-4C91-8372-BF1CEFA51D91}.Debug|x64.ActiveCfg = Debug|Any CPU + {0460EC82-4E93-4C91-8372-BF1CEFA51D91}.Debug|x64.Build.0 = Debug|Any CPU + {0460EC82-4E93-4C91-8372-BF1CEFA51D91}.Debug|x86.ActiveCfg = Debug|Any CPU + {0460EC82-4E93-4C91-8372-BF1CEFA51D91}.Debug|x86.Build.0 = Debug|Any CPU {0460EC82-4E93-4C91-8372-BF1CEFA51D91}.Release|Any CPU.ActiveCfg = Release|Any CPU {0460EC82-4E93-4C91-8372-BF1CEFA51D91}.Release|Any CPU.Build.0 = Release|Any CPU + {0460EC82-4E93-4C91-8372-BF1CEFA51D91}.Release|x64.ActiveCfg = Release|Any CPU + {0460EC82-4E93-4C91-8372-BF1CEFA51D91}.Release|x64.Build.0 = Release|Any CPU + {0460EC82-4E93-4C91-8372-BF1CEFA51D91}.Release|x86.ActiveCfg = Release|Any CPU + {0460EC82-4E93-4C91-8372-BF1CEFA51D91}.Release|x86.Build.0 = Release|Any CPU {ED5525FF-28D9-48B7-8D0C-4125F63E12BD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {ED5525FF-28D9-48B7-8D0C-4125F63E12BD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {ED5525FF-28D9-48B7-8D0C-4125F63E12BD}.Debug|x64.ActiveCfg = Debug|Any CPU + {ED5525FF-28D9-48B7-8D0C-4125F63E12BD}.Debug|x64.Build.0 = Debug|Any CPU + {ED5525FF-28D9-48B7-8D0C-4125F63E12BD}.Debug|x86.ActiveCfg = Debug|Any CPU + {ED5525FF-28D9-48B7-8D0C-4125F63E12BD}.Debug|x86.Build.0 = Debug|Any CPU {ED5525FF-28D9-48B7-8D0C-4125F63E12BD}.Release|Any CPU.ActiveCfg = Release|Any CPU {ED5525FF-28D9-48B7-8D0C-4125F63E12BD}.Release|Any CPU.Build.0 = Release|Any CPU + {ED5525FF-28D9-48B7-8D0C-4125F63E12BD}.Release|x64.ActiveCfg = Release|Any CPU + {ED5525FF-28D9-48B7-8D0C-4125F63E12BD}.Release|x64.Build.0 = Release|Any CPU + {ED5525FF-28D9-48B7-8D0C-4125F63E12BD}.Release|x86.ActiveCfg = Release|Any CPU + {ED5525FF-28D9-48B7-8D0C-4125F63E12BD}.Release|x86.Build.0 = Release|Any CPU {F3415D07-3FF7-45FC-AB9E-278BC2EC6157}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {F3415D07-3FF7-45FC-AB9E-278BC2EC6157}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F3415D07-3FF7-45FC-AB9E-278BC2EC6157}.Debug|x64.ActiveCfg = Debug|Any CPU + {F3415D07-3FF7-45FC-AB9E-278BC2EC6157}.Debug|x64.Build.0 = Debug|Any CPU + {F3415D07-3FF7-45FC-AB9E-278BC2EC6157}.Debug|x86.ActiveCfg = Debug|Any CPU + {F3415D07-3FF7-45FC-AB9E-278BC2EC6157}.Debug|x86.Build.0 = Debug|Any CPU {F3415D07-3FF7-45FC-AB9E-278BC2EC6157}.Release|Any CPU.ActiveCfg = Release|Any CPU {F3415D07-3FF7-45FC-AB9E-278BC2EC6157}.Release|Any CPU.Build.0 = Release|Any CPU + {F3415D07-3FF7-45FC-AB9E-278BC2EC6157}.Release|x64.ActiveCfg = Release|Any CPU + {F3415D07-3FF7-45FC-AB9E-278BC2EC6157}.Release|x64.Build.0 = Release|Any CPU + {F3415D07-3FF7-45FC-AB9E-278BC2EC6157}.Release|x86.ActiveCfg = Release|Any CPU + {F3415D07-3FF7-45FC-AB9E-278BC2EC6157}.Release|x86.Build.0 = Release|Any CPU {83C2D5D6-F6B4-4D19-B72E-B1804D95CFAD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {83C2D5D6-F6B4-4D19-B72E-B1804D95CFAD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {83C2D5D6-F6B4-4D19-B72E-B1804D95CFAD}.Debug|x64.ActiveCfg = Debug|Any CPU + {83C2D5D6-F6B4-4D19-B72E-B1804D95CFAD}.Debug|x64.Build.0 = Debug|Any CPU + {83C2D5D6-F6B4-4D19-B72E-B1804D95CFAD}.Debug|x86.ActiveCfg = Debug|Any CPU + {83C2D5D6-F6B4-4D19-B72E-B1804D95CFAD}.Debug|x86.Build.0 = Debug|Any CPU {83C2D5D6-F6B4-4D19-B72E-B1804D95CFAD}.Release|Any CPU.ActiveCfg = Release|Any CPU {83C2D5D6-F6B4-4D19-B72E-B1804D95CFAD}.Release|Any CPU.Build.0 = Release|Any CPU + {83C2D5D6-F6B4-4D19-B72E-B1804D95CFAD}.Release|x64.ActiveCfg = Release|Any CPU + {83C2D5D6-F6B4-4D19-B72E-B1804D95CFAD}.Release|x64.Build.0 = Release|Any CPU + {83C2D5D6-F6B4-4D19-B72E-B1804D95CFAD}.Release|x86.ActiveCfg = Release|Any CPU + {83C2D5D6-F6B4-4D19-B72E-B1804D95CFAD}.Release|x86.Build.0 = Release|Any CPU {1A4C9866-AE25-4BDA-A27B-230FD5F12222}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {1A4C9866-AE25-4BDA-A27B-230FD5F12222}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1A4C9866-AE25-4BDA-A27B-230FD5F12222}.Debug|x64.ActiveCfg = Debug|Any CPU + {1A4C9866-AE25-4BDA-A27B-230FD5F12222}.Debug|x64.Build.0 = Debug|Any CPU + {1A4C9866-AE25-4BDA-A27B-230FD5F12222}.Debug|x86.ActiveCfg = Debug|Any CPU + {1A4C9866-AE25-4BDA-A27B-230FD5F12222}.Debug|x86.Build.0 = Debug|Any CPU {1A4C9866-AE25-4BDA-A27B-230FD5F12222}.Release|Any CPU.ActiveCfg = Release|Any CPU {1A4C9866-AE25-4BDA-A27B-230FD5F12222}.Release|Any CPU.Build.0 = Release|Any CPU + {1A4C9866-AE25-4BDA-A27B-230FD5F12222}.Release|x64.ActiveCfg = Release|Any CPU + {1A4C9866-AE25-4BDA-A27B-230FD5F12222}.Release|x64.Build.0 = Release|Any CPU + {1A4C9866-AE25-4BDA-A27B-230FD5F12222}.Release|x86.ActiveCfg = Release|Any CPU + {1A4C9866-AE25-4BDA-A27B-230FD5F12222}.Release|x86.Build.0 = Release|Any CPU {928C09CB-BF31-4126-987A-E4D7112E0A9D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {928C09CB-BF31-4126-987A-E4D7112E0A9D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {928C09CB-BF31-4126-987A-E4D7112E0A9D}.Debug|x64.ActiveCfg = Debug|Any CPU + {928C09CB-BF31-4126-987A-E4D7112E0A9D}.Debug|x64.Build.0 = Debug|Any CPU + {928C09CB-BF31-4126-987A-E4D7112E0A9D}.Debug|x86.ActiveCfg = Debug|Any CPU + {928C09CB-BF31-4126-987A-E4D7112E0A9D}.Debug|x86.Build.0 = Debug|Any CPU {928C09CB-BF31-4126-987A-E4D7112E0A9D}.Release|Any CPU.ActiveCfg = Release|Any CPU {928C09CB-BF31-4126-987A-E4D7112E0A9D}.Release|Any CPU.Build.0 = Release|Any CPU + {928C09CB-BF31-4126-987A-E4D7112E0A9D}.Release|x64.ActiveCfg = Release|Any CPU + {928C09CB-BF31-4126-987A-E4D7112E0A9D}.Release|x64.Build.0 = Release|Any CPU + {928C09CB-BF31-4126-987A-E4D7112E0A9D}.Release|x86.ActiveCfg = Release|Any CPU + {928C09CB-BF31-4126-987A-E4D7112E0A9D}.Release|x86.Build.0 = Release|Any CPU {D555A356-6BBF-426F-B7ED-A55CAC505753}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {D555A356-6BBF-426F-B7ED-A55CAC505753}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D555A356-6BBF-426F-B7ED-A55CAC505753}.Debug|x64.ActiveCfg = Debug|Any CPU + {D555A356-6BBF-426F-B7ED-A55CAC505753}.Debug|x64.Build.0 = Debug|Any CPU + {D555A356-6BBF-426F-B7ED-A55CAC505753}.Debug|x86.ActiveCfg = Debug|Any CPU + {D555A356-6BBF-426F-B7ED-A55CAC505753}.Debug|x86.Build.0 = Debug|Any CPU {D555A356-6BBF-426F-B7ED-A55CAC505753}.Release|Any CPU.ActiveCfg = Release|Any CPU {D555A356-6BBF-426F-B7ED-A55CAC505753}.Release|Any CPU.Build.0 = Release|Any CPU + {D555A356-6BBF-426F-B7ED-A55CAC505753}.Release|x64.ActiveCfg = Release|Any CPU + {D555A356-6BBF-426F-B7ED-A55CAC505753}.Release|x64.Build.0 = Release|Any CPU + {D555A356-6BBF-426F-B7ED-A55CAC505753}.Release|x86.ActiveCfg = Release|Any CPU + {D555A356-6BBF-426F-B7ED-A55CAC505753}.Release|x86.Build.0 = Release|Any CPU + {21CD75E5-1155-45E2-97C8-ACA00C60AAA2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {21CD75E5-1155-45E2-97C8-ACA00C60AAA2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {21CD75E5-1155-45E2-97C8-ACA00C60AAA2}.Debug|x64.ActiveCfg = Debug|Any CPU + {21CD75E5-1155-45E2-97C8-ACA00C60AAA2}.Debug|x64.Build.0 = Debug|Any CPU + {21CD75E5-1155-45E2-97C8-ACA00C60AAA2}.Debug|x86.ActiveCfg = Debug|Any CPU + {21CD75E5-1155-45E2-97C8-ACA00C60AAA2}.Debug|x86.Build.0 = Debug|Any CPU + {21CD75E5-1155-45E2-97C8-ACA00C60AAA2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {21CD75E5-1155-45E2-97C8-ACA00C60AAA2}.Release|Any CPU.Build.0 = Release|Any CPU + {21CD75E5-1155-45E2-97C8-ACA00C60AAA2}.Release|x64.ActiveCfg = Release|Any CPU + {21CD75E5-1155-45E2-97C8-ACA00C60AAA2}.Release|x64.Build.0 = Release|Any CPU + {21CD75E5-1155-45E2-97C8-ACA00C60AAA2}.Release|x86.ActiveCfg = Release|Any CPU + {21CD75E5-1155-45E2-97C8-ACA00C60AAA2}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE