From 12077af05a545d682f72d4b5710dca8222c2f541 Mon Sep 17 00:00:00 2001 From: ahcantarim Date: Tue, 13 Jul 2021 10:18:22 -0300 Subject: [PATCH] Tutorial 5: Topics and 6: RPC --- .github/tutorial-5-01.png | Bin 0 -> 11049 bytes .github/tutorial-6-01.png | Bin 0 -> 14454 bytes README.md | 21 +++- .../EmitLogTopic.cs | 41 ++++++++ ...orial.RabbitMQ.Console.EmitLogTopic.csproj | 12 +++ .../RPCClient.cs | 82 +++++++++++++++ ...Tutorial.RabbitMQ.Console.RPCClient.csproj | 12 +++ .../RPCServer.cs | 96 ++++++++++++++++++ ...Tutorial.RabbitMQ.Console.RPCServer.csproj | 12 +++ .../ReceiveLogsTopic.cs | 64 ++++++++++++ ...l.RabbitMQ.Console.ReceiveLogsTopic.csproj | 12 +++ src/Tutorial.RabbitMQ.sln | 32 ++++++ 12 files changed, 380 insertions(+), 4 deletions(-) create mode 100644 .github/tutorial-5-01.png create mode 100644 .github/tutorial-6-01.png create mode 100644 src/Tutorial.RabbitMQ.Console.EmitLogTopic/EmitLogTopic.cs create mode 100644 src/Tutorial.RabbitMQ.Console.EmitLogTopic/Tutorial.RabbitMQ.Console.EmitLogTopic.csproj create mode 100644 src/Tutorial.RabbitMQ.Console.RPCClient/RPCClient.cs create mode 100644 src/Tutorial.RabbitMQ.Console.RPCClient/Tutorial.RabbitMQ.Console.RPCClient.csproj create mode 100644 src/Tutorial.RabbitMQ.Console.RPCServer/RPCServer.cs create mode 100644 src/Tutorial.RabbitMQ.Console.RPCServer/Tutorial.RabbitMQ.Console.RPCServer.csproj create mode 100644 src/Tutorial.RabbitMQ.Console.ReceiveLogsTopic/ReceiveLogsTopic.cs create mode 100644 src/Tutorial.RabbitMQ.Console.ReceiveLogsTopic/Tutorial.RabbitMQ.Console.ReceiveLogsTopic.csproj diff --git a/.github/tutorial-5-01.png b/.github/tutorial-5-01.png new file mode 100644 index 0000000000000000000000000000000000000000..48b784febaac1995529251cb9f82268a52689eaf GIT binary patch literal 11049 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�iA(mV-Mv7k3>9pa+K>{Z`9G7wl>{G zv^nrSt`8$e#9K`<_WtYypKSE!lN7T+E3G=@0~uWNxn%e>tsJ?o1ffIXG`po7QyJCG ztC`%MC9r2<$HlE;Di zX@q(rfYoxX>8EP9Bsj}j5+DKZrx@KliM$-D4jEv~Z;tY~G~2ULBv%{+iQ5ZR2#mGT z7%lP%yPhbGq})Z+yCMWpY0hyq7PSkmaSWPq5v!5ij(@Vp2p?69(1ZFp-O00)H*3l> zU&Z70Gm|w5<3I4w?X~$SJP{_LxqZbF2}vcBBF~rrqJAK*ptCM)_092emz%Wn9{0QR z)8Ad`0|by5#tVG646Um|w}Cm-XX;-c&+84K+fqLlA)l{*fV%9FvmyPkf4GPxg4=$0 zSq5Jv?-m!05M&g58%8YSY4d!#XV+1utF!;W$!4$8tf9WP)ZkKeDmR|af0V27{?KSo zsJbV9B{q|z>EJZ&F$P$J>?!r=xI3c2U=LbEj`Gos>!RU+pM^uQOg^O_-FeImJy`)G z_3*%1wl)?zlhp9NjD{txQ1s)=adB~m#I3t*D*pjZXUYPo+G z)Vrg{r%9euk<4CwA?zyKiSyuWr|j~Ks&J=r0bbm+O^yT37so6Y=`MwB*K6i&C-~qQ zguU?V3YvFnWKfRCSFn-9uNj$>{e+i9@w>x)JF8#1?*55DQULD+<;Cr9DRT2igXK_9 zysUp!y_-0z%@?#2nm%nuR(69rgvE2ZiLUV}DZnQ?sza|*x+_rz^IM!#yX2{Ga(A!s zmg-`0mRWPH-dXBt)koc4Wq+MLBOP^FMW?%Ysxj}~DhUDhyLNNKzQl%gi|R!DL85L% zbBpPZ&IxCJcI4T~hVS2Zs9?czg1F!Gn1#~Vs(5^FYhDjA#xwW3Yf=tXxb!5rSO0mr zi0(bK?l)LmyyS_x0 z`}rQ7!MA|Q`ZPP&-PLSGNw$5dw8%Y&U2E@^w`pc7v|>#H2^kd%u|H2Yq*8P4_NCZF z;~XERdN*cG1MUWIt|rtq8N5t>ZWjJTi3+Lb7-*eu2v^^5suT-eiaZW(9bRtnht+mQ z5t=r_S9unsxV*z-CW`cB!!Ckl8kHs`1!@QYXGZOp(S?<{q9?kW-ux$`Wtu-fh%^8V z$YIYJT6e?wB}PQgM_!7gEN}n#uvCoYDS1B>ULI)7@SG>@PxbSby3&cqNnrUmX?L(! zNJBA`&}lS?Rtpq?TPth~BrgKtZHx1jU-SjW?gt?7vOjgoF0#zkyI(>*+qT8cNMNO} z@w)zQK=0!o6L}U(XoHKouiT!?@z0=-JZcVZ9#O~&IlI`g=mo64N`D#QwJjfr`kq^z zo!^vw?wsRetNRNPC!)n256Wvqp4ssiBcv?S(xRve=zg( znXIWKGI8BX_Tv%ft6k-dx!p+=uj(758b6A#s68_Oc%q*K?(oMUSCy=Id28J%Y@pvH z4mReSuBe2P=uWh*T94B*i55?KT_2oc-wiNg73Ug#s{es$fdPSRCHrDG3jy~H(e8km zRKcF6i=EY_n7lugltg>dzlx1t%wBwFD%4|B|z}A9%yDw$i!aRBJF&vyglp?e$VlJ+H33C@SGGR5zHkA0oM^D;rIL6VgW- zj07kUC&;J{MPJe6U5dfepuOU|@V-fOSLXl^D literal 0 HcmV?d00001 diff --git a/.github/tutorial-6-01.png b/.github/tutorial-6-01.png new file mode 100644 index 0000000000000000000000000000000000000000..8592115f5c793d808f4214c56ea62d1c4adcc66d GIT binary patch literal 14454 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 literal 0 HcmV?d00001 diff --git a/README.md b/README.md index 17006f1..a9d435a 100644 --- a/README.md +++ b/README.md @@ -91,7 +91,7 @@ Para obter uma cópia local atualizada e que possa ser executada corretamente, s ### Pré-requisitos -Garanta que o **RabbitMQ** está instalado e sendo executado em `localhost` na porta padrão `5672`. +Os tutoriais assumem que o **RabbitMQ** está instalado e sendo executado em `localhost` na porta padrão (`5672`). - **Management:** http://localhost:15672 - **Username:** guest @@ -114,11 +114,15 @@ dotnet restore ``` -## Visão geral +## Introdução -O **RabbitMQ** - e outras ferramentas de mensagens no geral, usa alguns jargões: +**RabbitMQ** é um *message broker*: ele aceita e encaminha mensagens. Você pode pensar sobre isso como se fossem os *Correios*: quando você coloca a carta que você quer em uma caixa de postagem, você pode ter certeza de que eventualmente o carteiro irá entregar sua carta ao destinatário. Nesta analogia, o **RabbitMQ** é a caixa de postagem, a agência dos *Correios* e o carteiro. -- Um programa que envia mensagens é um `Producer`: +A maior diferença entre o **RabbitMQ** e uma agência dos *Correios* é que ele não lida com papel, ao invés disso aceita, armazena e encaminha blobs binários de dados ‒ *mensagens*. + +O **RabbitMQ** ‒ e outras ferramentas de mensagens no geral ‒ usa alguns jargões: + +- *Producing* significa nada mais do que *enviando*. Um programa que envia mensagens é um `Producer` (*produtor*): ![Producer](.github/producer.png) @@ -380,6 +384,15 @@ dotnet run No próximo tutorial iremos aprender como escutar um subconjunto de mensagens. +## Tutorial 4 » Routing + +[Routing](https://www.rabbitmq.com/tutorials/tutorial-four-dotnet.html) + +No tutorial anterior, criamos um sistema de *log* simples. Fomos capazes de transmitir mensagens para vários receptores. + +Neste tutorial vamos adicionar uma funcionalidade à ele - vamos tornar possível se subscrever apenas a um subconjunto de mensagens. Por exemplo, teremos a possibilidade de direcionar apenas as mensagens de *erro crítico* para o arquivo em disco, enquanto ainda é possível exibir todas as mensagens de *log* em tela. + + ## Licença Distribuído através da licença MIT. Veja `LICENSE` para mais informações. diff --git a/src/Tutorial.RabbitMQ.Console.EmitLogTopic/EmitLogTopic.cs b/src/Tutorial.RabbitMQ.Console.EmitLogTopic/EmitLogTopic.cs new file mode 100644 index 0000000..bd16394 --- /dev/null +++ b/src/Tutorial.RabbitMQ.Console.EmitLogTopic/EmitLogTopic.cs @@ -0,0 +1,41 @@ +using RabbitMQ.Client; +using System; +using System.Linq; +using System.Text; + +namespace Tutorial.RabbitMQ.Console.EmitLogTopic +{ + class EmitLogTopic + { + static void Main(string[] args) + { + var factory = new ConnectionFactory() { HostName = "localhost" }; + var exchangeName = "topic_logs"; + + using (var connection = factory.CreateConnection()) + using (var channel = connection.CreateModel()) + { + channel.ExchangeDeclare(exchange: exchangeName, + type: ExchangeType.Topic); + + var routingKey = (args.Length > 0) ? args[0] : "anonymous.info"; + + var message = (args.Length > 1) + ? string.Join(" ", args.Skip(1).ToArray()) + : "Hello World!"; + + var body = Encoding.UTF8.GetBytes(message); + + channel.BasicPublish(exchange: "topic_logs", + routingKey: routingKey, + basicProperties: null, + body: body); + + System.Console.WriteLine($"{DateTime.Now}: Sent '{routingKey}':'{message}'"); + } + + System.Console.WriteLine($"{DateTime.Now}: Press [enter] to exit."); + System.Console.ReadLine(); + } + } +} diff --git a/src/Tutorial.RabbitMQ.Console.EmitLogTopic/Tutorial.RabbitMQ.Console.EmitLogTopic.csproj b/src/Tutorial.RabbitMQ.Console.EmitLogTopic/Tutorial.RabbitMQ.Console.EmitLogTopic.csproj new file mode 100644 index 0000000..6c67a5e --- /dev/null +++ b/src/Tutorial.RabbitMQ.Console.EmitLogTopic/Tutorial.RabbitMQ.Console.EmitLogTopic.csproj @@ -0,0 +1,12 @@ + + + + Exe + netcoreapp3.1 + + + + + + + diff --git a/src/Tutorial.RabbitMQ.Console.RPCClient/RPCClient.cs b/src/Tutorial.RabbitMQ.Console.RPCClient/RPCClient.cs new file mode 100644 index 0000000..46e0bc4 --- /dev/null +++ b/src/Tutorial.RabbitMQ.Console.RPCClient/RPCClient.cs @@ -0,0 +1,82 @@ +using RabbitMQ.Client; +using RabbitMQ.Client.Events; +using System; +using System.Collections.Concurrent; +using System.Text; + +namespace Tutorial.RabbitMQ.Console.RPCClient +{ + class RPCClient + { + private readonly IConnection connection; + private readonly IModel channel; + private readonly string queueName = "rpc_queue"; + private readonly string replyQueueName; + private readonly EventingBasicConsumer consumer; + private readonly BlockingCollection respQueue = new BlockingCollection(); + private readonly IBasicProperties props; + private readonly string CorrelationId; + + public RPCClient() + { + var factory = new ConnectionFactory() { HostName = "localhost" }; + + connection = factory.CreateConnection(); + channel = connection.CreateModel(); + replyQueueName = channel.QueueDeclare().QueueName; + consumer = new EventingBasicConsumer(channel); + + props = channel.CreateBasicProperties(); + CorrelationId = Guid.NewGuid().ToString(); + props.CorrelationId = CorrelationId; + props.ReplyTo = replyQueueName; + + consumer.Received += Consumer_Received; + } + + private void Consumer_Received(object sender, BasicDeliverEventArgs e) + { + var body = e.Body.ToArray(); + var response = Encoding.UTF8.GetString(body); + if (e.BasicProperties.CorrelationId == CorrelationId) + { + respQueue.Add(response); + } + } + + public string Call(string message) + { + var messageBytes = Encoding.UTF8.GetBytes(message); + + channel.BasicPublish(exchange: string.Empty, + routingKey: queueName, + basicProperties: props, + body: messageBytes); + + channel.BasicConsume(consumer: consumer, + queue: replyQueueName, + autoAck: true); + + return respQueue.Take(); + } + + public void Close() + { + connection.Close(); + } + } + + public class Rpc + { + static void Main(string[] args) + { + var rpcClient = new RPCClient(); + + System.Console.WriteLine($"{DateTime.Now}: Press Requesting fib(30)."); + var response = rpcClient.Call("4"); + System.Console.WriteLine($"{DateTime.Now}: Got '{response}'"); + + rpcClient.Close(); + } + } +} diff --git a/src/Tutorial.RabbitMQ.Console.RPCClient/Tutorial.RabbitMQ.Console.RPCClient.csproj b/src/Tutorial.RabbitMQ.Console.RPCClient/Tutorial.RabbitMQ.Console.RPCClient.csproj new file mode 100644 index 0000000..6c67a5e --- /dev/null +++ b/src/Tutorial.RabbitMQ.Console.RPCClient/Tutorial.RabbitMQ.Console.RPCClient.csproj @@ -0,0 +1,12 @@ + + + + Exe + netcoreapp3.1 + + + + + + + diff --git a/src/Tutorial.RabbitMQ.Console.RPCServer/RPCServer.cs b/src/Tutorial.RabbitMQ.Console.RPCServer/RPCServer.cs new file mode 100644 index 0000000..8cd4b53 --- /dev/null +++ b/src/Tutorial.RabbitMQ.Console.RPCServer/RPCServer.cs @@ -0,0 +1,96 @@ +using RabbitMQ.Client; +using RabbitMQ.Client.Events; +using System; +using System.Text; + +namespace Tutorial.RabbitMQ.Console.RPCServer +{ + class RPCServer + { + static void Main(string[] args) + { + var factory = new ConnectionFactory() { HostName = "localhost" }; + var queueName = "rpc_queue"; + + using (var connection = factory.CreateConnection()) + using (var channel = connection.CreateModel()) + { + channel.QueueDeclare(queue: queueName, + durable: false, + exclusive: false, + autoDelete: false, + arguments: null); + + channel.BasicQos(0, 1, false); + + var consumer = new EventingBasicConsumer(channel); + + channel.BasicConsume(queue: queueName, + autoAck: false, + consumer: consumer); + + System.Console.WriteLine($"{DateTime.Now}: Awaiting RPC requests."); + + consumer.Received += Consumer_Received; + + System.Console.WriteLine($"{DateTime.Now}: Press [enter] to exit."); + System.Console.ReadLine(); + } + } + + private static void Consumer_Received(object sender, BasicDeliverEventArgs e) + { + var channel = ((EventingBasicConsumer)sender).Model; + string response = null; + + var body = e.Body.ToArray(); + var props = e.BasicProperties; + var replyProps = channel.CreateBasicProperties(); + replyProps.CorrelationId = props.CorrelationId; + + try + { + var message = Encoding.UTF8.GetString(body); + int n = int.Parse(message); + + System.Console.WriteLine($"{DateTime.Now}: fib({message})"); + response = fib(n).ToString(); + + } + catch (Exception ex) + { + System.Console.WriteLine($"{DateTime.Now}: ERROR {ex.Message}"); + response = string.Empty; + } + finally + { + var responseBytes = Encoding.UTF8.GetBytes(response); + + channel.BasicPublish(exchange: string.Empty, + routingKey: props.ReplyTo, + basicProperties: replyProps, + body: responseBytes); + + channel.BasicAck(deliveryTag: e.DeliveryTag, + multiple: false); + } + } + + /// + /// Assumes only valid positive integer input. + /// Don't expect this one to work for big numbers, and it's + /// probably the slowest recursive implementation possible. + /// + /// + /// + private static int fib(int n) + { + if (n == 0 || n == 1) + { + return n; + } + + return fib(n - 1) + fib(n - 2); + } + } +} diff --git a/src/Tutorial.RabbitMQ.Console.RPCServer/Tutorial.RabbitMQ.Console.RPCServer.csproj b/src/Tutorial.RabbitMQ.Console.RPCServer/Tutorial.RabbitMQ.Console.RPCServer.csproj new file mode 100644 index 0000000..6c67a5e --- /dev/null +++ b/src/Tutorial.RabbitMQ.Console.RPCServer/Tutorial.RabbitMQ.Console.RPCServer.csproj @@ -0,0 +1,12 @@ + + + + Exe + netcoreapp3.1 + + + + + + + diff --git a/src/Tutorial.RabbitMQ.Console.ReceiveLogsTopic/ReceiveLogsTopic.cs b/src/Tutorial.RabbitMQ.Console.ReceiveLogsTopic/ReceiveLogsTopic.cs new file mode 100644 index 0000000..0b12e2f --- /dev/null +++ b/src/Tutorial.RabbitMQ.Console.ReceiveLogsTopic/ReceiveLogsTopic.cs @@ -0,0 +1,64 @@ +using RabbitMQ.Client; +using RabbitMQ.Client.Events; +using System; +using System.Text; + +namespace Tutorial.RabbitMQ.Console.ReceiveLogsTopic +{ + class ReceiveLogsTopic + { + static void Main(string[] args) + { + var factory = new ConnectionFactory() { HostName = "localhost" }; + var exchangeName = "topic_logs"; + + using (var connection = factory.CreateConnection()) + using (var channel = connection.CreateModel()) + { + channel.ExchangeDeclare(exchange: exchangeName, + type: ExchangeType.Topic); + + var queueName = channel.QueueDeclare().QueueName; + + if (args.Length < 1) + { + System.Console.Error.WriteLine($"{DateTime.Now}: Usage: {Environment.GetCommandLineArgs()[0]} [info] [warning] [error]."); + + System.Console.WriteLine($"{DateTime.Now}: Press [enter] to exit."); + System.Console.ReadLine(); + + Environment.ExitCode = 1; + return; + } + + foreach (var bindingKey in args) + { + channel.QueueBind(queue: queueName, + exchange: exchangeName, + routingKey: bindingKey); + } + + System.Console.WriteLine($"{DateTime.Now}: Waiting for messages."); + + var consumer = new EventingBasicConsumer(channel); + consumer.Received += Consumer_Received; + + channel.BasicConsume(queue: queueName, + autoAck: true, + consumer: consumer); + + System.Console.WriteLine($"{DateTime.Now}: Press [enter] to exit."); + System.Console.ReadLine(); + } + } + + private static void Consumer_Received(object sender, BasicDeliverEventArgs e) + { + var body = e.Body.ToArray(); + var message = Encoding.UTF8.GetString(body); + var routingKey = e.RoutingKey; + + System.Console.WriteLine($"{DateTime.Now}: Received '{routingKey}':'{message}'"); + } + } +} diff --git a/src/Tutorial.RabbitMQ.Console.ReceiveLogsTopic/Tutorial.RabbitMQ.Console.ReceiveLogsTopic.csproj b/src/Tutorial.RabbitMQ.Console.ReceiveLogsTopic/Tutorial.RabbitMQ.Console.ReceiveLogsTopic.csproj new file mode 100644 index 0000000..6c67a5e --- /dev/null +++ b/src/Tutorial.RabbitMQ.Console.ReceiveLogsTopic/Tutorial.RabbitMQ.Console.ReceiveLogsTopic.csproj @@ -0,0 +1,12 @@ + + + + Exe + netcoreapp3.1 + + + + + + + diff --git a/src/Tutorial.RabbitMQ.sln b/src/Tutorial.RabbitMQ.sln index 2eb5c18..6912a84 100644 --- a/src/Tutorial.RabbitMQ.sln +++ b/src/Tutorial.RabbitMQ.sln @@ -27,6 +27,18 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tutorial.RabbitMQ.Console.E EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tutorial.RabbitMQ.Console.ReceiveLogsDirect", "Tutorial.RabbitMQ.Console.ReceiveLogsDirect\Tutorial.RabbitMQ.Console.ReceiveLogsDirect.csproj", "{9F3ECD8E-BEB4-459D-89BD-0705E87FED73}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "5. Tutorial 5 - Topics", "5. Tutorial 5 - Topics", "{E13BE1D4-CB15-4A45-8097-397D9E552000}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tutorial.RabbitMQ.Console.EmitLogTopic", "Tutorial.RabbitMQ.Console.EmitLogTopic\Tutorial.RabbitMQ.Console.EmitLogTopic.csproj", "{09AB929F-73B6-4024-B911-AF2F03A1837B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tutorial.RabbitMQ.Console.ReceiveLogsTopic", "Tutorial.RabbitMQ.Console.ReceiveLogsTopic\Tutorial.RabbitMQ.Console.ReceiveLogsTopic.csproj", "{6C0F7FED-3833-430C-9CB1-1E635030A48B}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "6. Tutorial 6 - RPC", "6. Tutorial 6 - RPC", "{97523ADE-31E1-4C9D-B7FD-BC9C6C1C2DF9}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tutorial.RabbitMQ.Console.RPCServer", "Tutorial.RabbitMQ.Console.RPCServer\Tutorial.RabbitMQ.Console.RPCServer.csproj", "{B1D95063-4309-425E-9134-A2C3C4B019F8}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tutorial.RabbitMQ.Console.RPCClient", "Tutorial.RabbitMQ.Console.RPCClient\Tutorial.RabbitMQ.Console.RPCClient.csproj", "{0E2ACEEA-FF23-4BD6-9410-BC3961D83EDD}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -65,6 +77,22 @@ Global {9F3ECD8E-BEB4-459D-89BD-0705E87FED73}.Debug|Any CPU.Build.0 = Debug|Any CPU {9F3ECD8E-BEB4-459D-89BD-0705E87FED73}.Release|Any CPU.ActiveCfg = Release|Any CPU {9F3ECD8E-BEB4-459D-89BD-0705E87FED73}.Release|Any CPU.Build.0 = Release|Any CPU + {09AB929F-73B6-4024-B911-AF2F03A1837B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {09AB929F-73B6-4024-B911-AF2F03A1837B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {09AB929F-73B6-4024-B911-AF2F03A1837B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {09AB929F-73B6-4024-B911-AF2F03A1837B}.Release|Any CPU.Build.0 = Release|Any CPU + {6C0F7FED-3833-430C-9CB1-1E635030A48B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6C0F7FED-3833-430C-9CB1-1E635030A48B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6C0F7FED-3833-430C-9CB1-1E635030A48B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6C0F7FED-3833-430C-9CB1-1E635030A48B}.Release|Any CPU.Build.0 = Release|Any CPU + {B1D95063-4309-425E-9134-A2C3C4B019F8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B1D95063-4309-425E-9134-A2C3C4B019F8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B1D95063-4309-425E-9134-A2C3C4B019F8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B1D95063-4309-425E-9134-A2C3C4B019F8}.Release|Any CPU.Build.0 = Release|Any CPU + {0E2ACEEA-FF23-4BD6-9410-BC3961D83EDD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0E2ACEEA-FF23-4BD6-9410-BC3961D83EDD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0E2ACEEA-FF23-4BD6-9410-BC3961D83EDD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0E2ACEEA-FF23-4BD6-9410-BC3961D83EDD}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -78,6 +106,10 @@ Global {BB96A1AD-69F5-4D7A-B305-4E5D7E87A2BF} = {ECFD14A2-DC0A-4F2E-A12B-5F9C2D57CE11} {36029E5A-A2EF-445F-ABB0-5BCBD25E44FD} = {C487ED4B-21F0-4969-86BB-863B088BD7B0} {9F3ECD8E-BEB4-459D-89BD-0705E87FED73} = {C487ED4B-21F0-4969-86BB-863B088BD7B0} + {09AB929F-73B6-4024-B911-AF2F03A1837B} = {E13BE1D4-CB15-4A45-8097-397D9E552000} + {6C0F7FED-3833-430C-9CB1-1E635030A48B} = {E13BE1D4-CB15-4A45-8097-397D9E552000} + {B1D95063-4309-425E-9134-A2C3C4B019F8} = {97523ADE-31E1-4C9D-B7FD-BC9C6C1C2DF9} + {0E2ACEEA-FF23-4BD6-9410-BC3961D83EDD} = {97523ADE-31E1-4C9D-B7FD-BC9C6C1C2DF9} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {F38BDFBB-F9A8-4372-973D-39FB03E21EA4}