aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--OpenSim/ConsoleClient/ConsoleClient.cs185
-rw-r--r--OpenSim/ConsoleClient/Requester.cs86
-rw-r--r--OpenSim/Framework/Console/CommandConsole.cs92
-rw-r--r--OpenSim/Framework/Console/RemoteConsole.cs44
-rw-r--r--bin/OpenSim.ConsoleClient.exe.config33
-rw-r--r--bin/OpenSim.ConsoleClient.ini.example1
-rw-r--r--prebuild.xml32
7 files changed, 461 insertions, 12 deletions
diff --git a/OpenSim/ConsoleClient/ConsoleClient.cs b/OpenSim/ConsoleClient/ConsoleClient.cs
new file mode 100644
index 0000000..0d4f3cf
--- /dev/null
+++ b/OpenSim/ConsoleClient/ConsoleClient.cs
@@ -0,0 +1,185 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using Nini.Config;
29using log4net;
30using System.Reflection;
31using System;
32using System.Xml;
33using System.Collections.Generic;
34using OpenSim.Server.Base;
35using OpenSim.Framework.Console;
36using OpenMetaverse;
37
38namespace OpenSim.ConsoleClient
39{
40 public class OpenSimConsoleClient
41 {
42 private static readonly ILog m_log =
43 LogManager.GetLogger(
44 MethodBase.GetCurrentMethod().DeclaringType);
45
46 protected static ServicesServerBase m_Server = null;
47 private static string m_Host;
48 private static int m_Port;
49 private static string m_User;
50 private static string m_Pass;
51 private static UUID m_SessionID;
52
53 static int Main(string[] args)
54 {
55 m_Server = new ServicesServerBase("Client", args);
56
57 IConfig serverConfig = m_Server.Config.Configs["Startup"];
58 if (serverConfig == null)
59 {
60 System.Console.WriteLine("Startup config section missing in .ini file");
61 throw new Exception("Configuration error");
62 }
63
64 ArgvConfigSource argvConfig = new ArgvConfigSource(args);
65
66 argvConfig.AddSwitch("Startup", "host", "h");
67 argvConfig.AddSwitch("Startup", "port", "p");
68 argvConfig.AddSwitch("Startup", "user", "u");
69 argvConfig.AddSwitch("Startup", "pass", "P");
70
71 m_Server.Config.Merge(argvConfig);
72
73 m_User = serverConfig.GetString("user", "Test");
74 m_Host = serverConfig.GetString("host", "localhost");
75 m_Port = serverConfig.GetInt("port", 8003);
76 m_Pass = serverConfig.GetString("pass", "secret");
77
78 Requester.MakeRequest("http://"+m_Host+":"+m_Port.ToString()+"/StartSession/", String.Format("USER={0}&PASS={1}", m_User, m_Pass), LoginReply);
79
80 int res = m_Server.Run();
81
82 Environment.Exit(res);
83
84 return 0;
85 }
86
87 private static void SendCommand(string module, string[] cmd)
88 {
89 string sendCmd = String.Join(" ", cmd);
90
91 Requester.MakeRequest("http://"+m_Host+":"+m_Port.ToString()+"/SessionCommand/", String.Format("ID={0}&COMMAND={1}", m_SessionID, sendCmd), CommandReply);
92 }
93
94 public static void LoginReply(string requestUrl, string requestData, string replyData)
95 {
96 XmlDocument doc = new XmlDocument();
97
98 doc.LoadXml(replyData);
99
100 XmlNodeList rootL = doc.GetElementsByTagName("ConsoleSession");
101 if (rootL.Count != 1)
102 {
103 MainConsole.Instance.Output("Connection data info was not valid");
104 Environment.Exit(1);
105 }
106 XmlElement rootNode = (XmlElement)rootL[0];
107
108 if (rootNode == null)
109 {
110 MainConsole.Instance.Output("Connection data info was not valid");
111 Environment.Exit(1);
112 }
113
114 XmlNodeList helpNodeL = rootNode.GetElementsByTagName("HelpTree");
115 if (helpNodeL.Count != 1)
116 {
117 MainConsole.Instance.Output("Connection data info was not valid");
118 Environment.Exit(1);
119 }
120
121 XmlElement helpNode = (XmlElement)helpNodeL[0];
122 if (helpNode == null)
123 {
124 MainConsole.Instance.Output("Connection data info was not valid");
125 Environment.Exit(1);
126 }
127
128 XmlNodeList sessionL = rootNode.GetElementsByTagName("SessionID");
129 if (sessionL.Count != 1)
130 {
131 MainConsole.Instance.Output("Connection data info was not valid");
132 Environment.Exit(1);
133 }
134
135 XmlElement sessionNode = (XmlElement)sessionL[0];
136 if (sessionNode == null)
137 {
138 MainConsole.Instance.Output("Connection data info was not valid");
139 Environment.Exit(1);
140 }
141
142 if (!UUID.TryParse(sessionNode.InnerText, out m_SessionID))
143 {
144 MainConsole.Instance.Output("Connection data info was not valid");
145 Environment.Exit(1);
146 }
147
148 MainConsole.Instance.Commands.FromXml(helpNode, SendCommand);
149
150 Requester.MakeRequest("http://"+m_Host+":"+m_Port.ToString()+"/ReadResponses/"+m_SessionID.ToString()+"/", String.Empty, ReadResponses);
151 }
152
153 public static void ReadResponses(string requestUrl, string requestData, string replyData)
154 {
155 XmlDocument doc = new XmlDocument();
156
157 doc.LoadXml(replyData);
158
159 XmlNodeList rootNodeL = doc.GetElementsByTagName("ConsoleSession");
160 if (rootNodeL.Count != 1 || rootNodeL[0] == null)
161 {
162 Requester.MakeRequest(requestUrl, requestData, ReadResponses);
163 return;
164 }
165
166 foreach (XmlNode part in rootNodeL[0].ChildNodes)
167 {
168 if (part.Name != "Line")
169 continue;
170
171 string[] parts = part.InnerText.Split(new char[] {':'}, 3);
172 if (parts.Length != 3)
173 continue;
174
175 MainConsole.Instance.Output(parts[2], parts[1]);
176 }
177
178 Requester.MakeRequest(requestUrl, requestData, ReadResponses);
179 }
180
181 public static void CommandReply(string requestUrl, string requestData, string replyData)
182 {
183 }
184 }
185}
diff --git a/OpenSim/ConsoleClient/Requester.cs b/OpenSim/ConsoleClient/Requester.cs
new file mode 100644
index 0000000..af7860d
--- /dev/null
+++ b/OpenSim/ConsoleClient/Requester.cs
@@ -0,0 +1,86 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.IO;
30using System.Net;
31using System.Reflection;
32using System.Text;
33using System.Xml;
34using System.Xml.Serialization;
35using log4net;
36
37namespace OpenSim.ConsoleClient
38{
39 public delegate void ReplyDelegate(string requestUrl, string requestData, string replyData);
40
41 public class Requester
42 {
43 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
44
45 public static void MakeRequest(string requestUrl, string data,
46 ReplyDelegate action)
47 {
48 WebRequest request = WebRequest.Create(requestUrl);
49 WebResponse response = null;
50
51 request.Method = "POST";
52
53 request.ContentType = "application/x-www-form-urlencoded";
54
55 byte[] buffer = new System.Text.ASCIIEncoding().GetBytes(data);
56 int length = (int) buffer.Length;
57 request.ContentLength = length;
58
59 request.BeginGetRequestStream(delegate(IAsyncResult res)
60 {
61 Stream requestStream = request.EndGetRequestStream(res);
62
63 requestStream.Write(buffer, 0, length);
64
65 request.BeginGetResponse(delegate(IAsyncResult ar)
66 {
67 string reply = String.Empty;
68
69 response = request.EndGetResponse(ar);
70
71 try
72 {
73 StreamReader r = new StreamReader(response.GetResponseStream());
74 reply = r.ReadToEnd();
75
76 }
77 catch (System.InvalidOperationException)
78 {
79 }
80
81 action(requestUrl, data, reply);
82 }, null);
83 }, null);
84 }
85 }
86}
diff --git a/OpenSim/Framework/Console/CommandConsole.cs b/OpenSim/Framework/Console/CommandConsole.cs
index 7af8204..3387013 100644
--- a/OpenSim/Framework/Console/CommandConsole.cs
+++ b/OpenSim/Framework/Console/CommandConsole.cs
@@ -373,10 +373,28 @@ namespace OpenSim.Framework.Console
373 373
374 public XmlElement GetXml(XmlDocument doc) 374 public XmlElement GetXml(XmlDocument doc)
375 { 375 {
376 CommandInfo help = (CommandInfo)((Dictionary<string, object>)tree["help"])[String.Empty];
377 ((Dictionary<string, object>)tree["help"]).Remove(string.Empty);
378 if (((Dictionary<string, object>)tree["help"]).Count == 0)
379 tree.Remove("help");
380
381 CommandInfo quit = (CommandInfo)((Dictionary<string, object>)tree["quit"])[String.Empty];
382 ((Dictionary<string, object>)tree["quit"]).Remove(string.Empty);
383 if (((Dictionary<string, object>)tree["quit"]).Count == 0)
384 tree.Remove("quit");
385
376 XmlElement root = doc.CreateElement("", "HelpTree", ""); 386 XmlElement root = doc.CreateElement("", "HelpTree", "");
377 387
378 ProcessTreeLevel(tree, root, doc); 388 ProcessTreeLevel(tree, root, doc);
379 389
390 if (!tree.ContainsKey("help"))
391 tree["help"] = (object) new Dictionary<string, object>();
392 ((Dictionary<string, object>)tree["help"])[String.Empty] = help;
393
394 if (!tree.ContainsKey("quit"))
395 tree["quit"] = (object) new Dictionary<string, object>();
396 ((Dictionary<string, object>)tree["quit"])[String.Empty] = quit;
397
380 return root; 398 return root;
381 } 399 }
382 400
@@ -426,8 +444,80 @@ namespace OpenSim.Framework.Console
426 } 444 }
427 } 445 }
428 446
429 public void FromXml(XmlElement root) 447 public void FromXml(XmlElement root, CommandDelegate fn)
448 {
449 CommandInfo help = (CommandInfo)((Dictionary<string, object>)tree["help"])[String.Empty];
450 ((Dictionary<string, object>)tree["help"]).Remove(string.Empty);
451 if (((Dictionary<string, object>)tree["help"]).Count == 0)
452 tree.Remove("help");
453
454 CommandInfo quit = (CommandInfo)((Dictionary<string, object>)tree["quit"])[String.Empty];
455 ((Dictionary<string, object>)tree["quit"]).Remove(string.Empty);
456 if (((Dictionary<string, object>)tree["quit"]).Count == 0)
457 tree.Remove("quit");
458
459 tree.Clear();
460
461 ReadTreeLevel(tree, root, fn);
462
463 if (!tree.ContainsKey("help"))
464 tree["help"] = (object) new Dictionary<string, object>();
465 ((Dictionary<string, object>)tree["help"])[String.Empty] = help;
466
467 if (!tree.ContainsKey("quit"))
468 tree["quit"] = (object) new Dictionary<string, object>();
469 ((Dictionary<string, object>)tree["quit"])[String.Empty] = quit;
470 }
471
472 private void ReadTreeLevel(Dictionary<string, object> level, XmlNode node, CommandDelegate fn)
430 { 473 {
474 Dictionary<string, object> next;
475 string name;
476
477 XmlNodeList nodeL = node.ChildNodes;
478 XmlNodeList cmdL;
479 CommandInfo c;
480
481 foreach (XmlNode part in nodeL)
482 {
483 switch (part.Name)
484 {
485 case "Level":
486 name = ((XmlElement)part).GetAttribute("Name");
487 next = new Dictionary<string, object>();
488 level[name] = next;
489 ReadTreeLevel(next, part, fn);
490 break;
491 case "Command":
492 cmdL = part.ChildNodes;
493 c = new CommandInfo();
494 foreach (XmlNode cmdPart in cmdL)
495 {
496 switch (cmdPart.Name)
497 {
498 case "Module":
499 c.module = cmdPart.InnerText;
500 break;
501 case "Shared":
502 c.shared = Convert.ToBoolean(cmdPart.InnerText);
503 break;
504 case "HelpText":
505 c.help_text = cmdPart.InnerText;
506 break;
507 case "LongHelp":
508 c.long_help = cmdPart.InnerText;
509 break;
510 case "Description":
511 c.descriptive_help = cmdPart.InnerText;
512 break;
513 }
514 }
515 c.fn = new List<CommandDelegate>();
516 c.fn.Add(fn);
517 level[String.Empty] = c;
518 break;
519 }
520 }
431 } 521 }
432 } 522 }
433 523
diff --git a/OpenSim/Framework/Console/RemoteConsole.cs b/OpenSim/Framework/Console/RemoteConsole.cs
index dbf8f8c..da8556a 100644
--- a/OpenSim/Framework/Console/RemoteConsole.cs
+++ b/OpenSim/Framework/Console/RemoteConsole.cs
@@ -98,7 +98,12 @@ namespace OpenSim.Framework.Console
98 m_LineNumber++; 98 m_LineNumber++;
99 m_Scrollback.Add(String.Format("{0}", m_LineNumber)+":"+level+":"+text); 99 m_Scrollback.Add(String.Format("{0}", m_LineNumber)+":"+level+":"+text);
100 } 100 }
101 System.Console.Write(text); 101 System.Console.WriteLine(text.Trim());
102 }
103
104 public override void Output(string text)
105 {
106 Output(text, "normal");
102 } 107 }
103 108
104 public override string ReadLine(string p, bool isCommand, bool e) 109 public override string ReadLine(string p, bool isCommand, bool e)
@@ -152,9 +157,8 @@ namespace OpenSim.Framework.Console
152 157
153 foreach (UUID id in expired) 158 foreach (UUID id in expired)
154 { 159 {
155 System.Console.WriteLine("Expired {0}", id.ToString());
156 CloseConnection(id);
157 m_Connections.Remove(id); 160 m_Connections.Remove(id);
161 CloseConnection(id);
158 } 162 }
159 } 163 }
160 } 164 }
@@ -244,8 +248,8 @@ namespace OpenSim.Framework.Console
244 { 248 {
245 if (m_Connections.ContainsKey(id)) 249 if (m_Connections.ContainsKey(id))
246 { 250 {
247 CloseConnection(id);
248 m_Connections.Remove(id); 251 m_Connections.Remove(id);
252 CloseConnection(id);
249 } 253 }
250 } 254 }
251 255
@@ -346,9 +350,15 @@ namespace OpenSim.Framework.Console
346 350
347 public void CloseConnection(UUID id) 351 public void CloseConnection(UUID id)
348 { 352 {
349 string uri = "/ReadResponses/" + id.ToString() + "/"; 353 try
354 {
355 string uri = "/ReadResponses/" + id.ToString() + "/";
350 356
351 m_Server.RemovePollServiceHTTPHandler("", uri); 357 m_Server.RemovePollServiceHTTPHandler("", uri);
358 }
359 catch (Exception)
360 {
361 }
352 } 362 }
353 363
354 private bool HasEvents(UUID sessionID) 364 private bool HasEvents(UUID sessionID)
@@ -394,8 +404,11 @@ namespace OpenSim.Framework.Console
394 lock (m_Scrollback) 404 lock (m_Scrollback)
395 { 405 {
396 long startLine = m_LineNumber - m_Scrollback.Count; 406 long startLine = m_LineNumber - m_Scrollback.Count;
407 long sendStart = startLine;
408 if (sendStart < c.lastLineSeen)
409 sendStart = c.lastLineSeen;
397 410
398 for (long i = startLine ; i < m_LineNumber ; i++) 411 for (long i = sendStart ; i < m_LineNumber ; i++)
399 { 412 {
400 XmlElement res = xmldoc.CreateElement("", "Line", ""); 413 XmlElement res = xmldoc.CreateElement("", "Line", "");
401 long line = i + 1; 414 long line = i + 1;
@@ -422,12 +435,21 @@ namespace OpenSim.Framework.Console
422 { 435 {
423 Hashtable result = new Hashtable(); 436 Hashtable result = new Hashtable();
424 437
425 result["int_response_code"] = 502; 438 XmlDocument xmldoc = new XmlDocument();
426 result["content_type"] = "text/plain"; 439 XmlNode xmlnode = xmldoc.CreateNode(XmlNodeType.XmlDeclaration,
440 "", "");
441
442 xmldoc.AppendChild(xmlnode);
443 XmlElement rootElement = xmldoc.CreateElement("", "ConsoleSession",
444 "");
445
446 xmldoc.AppendChild(rootElement);
447
448 result["str_response_string"] = xmldoc.InnerXml;
449 result["int_response_code"] = 200;
450 result["content_type"] = "text/xml";
427 result["keepalive"] = false; 451 result["keepalive"] = false;
428 result["reusecontext"] = false; 452 result["reusecontext"] = false;
429 result["str_response_string"] = "Upstream error: ";
430 result["error_status_text"] = "Upstream error:";
431 453
432 return result; 454 return result;
433 } 455 }
diff --git a/bin/OpenSim.ConsoleClient.exe.config b/bin/OpenSim.ConsoleClient.exe.config
new file mode 100644
index 0000000..c2d93c0
--- /dev/null
+++ b/bin/OpenSim.ConsoleClient.exe.config
@@ -0,0 +1,33 @@
1<?xml version="1.0" encoding="utf-8" ?>
2<configuration>
3 <configSections>
4 <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net" />
5 </configSections>
6 <runtime>
7 <gcConcurrent enabled="true" />
8 <gcServer enabled="true" />
9 </runtime>
10 <appSettings>
11 </appSettings>
12 <log4net>
13 <appender name="Console" type="OpenSim.Framework.Console.OpenSimAppender, OpenSim.Framework.Console">
14 <layout type="log4net.Layout.PatternLayout">
15 <conversionPattern value="%date{HH:mm:ss} - %message%newline" />
16 </layout>
17 </appender>
18
19 <appender name="LogFileAppender" type="log4net.Appender.FileAppender">
20 <file value="OpenSim.log" />
21 <appendToFile value="true" />
22 <layout type="log4net.Layout.PatternLayout">
23 <conversionPattern value="%date %-5level - %logger %message%newline" />
24 </layout>
25 </appender>
26
27 <root>
28 <level value="DEBUG" />
29 <appender-ref ref="Console" />
30 <appender-ref ref="LogFileAppender" />
31 </root>
32 </log4net>
33</configuration>
diff --git a/bin/OpenSim.ConsoleClient.ini.example b/bin/OpenSim.ConsoleClient.ini.example
new file mode 100644
index 0000000..beea7d8
--- /dev/null
+++ b/bin/OpenSim.ConsoleClient.ini.example
@@ -0,0 +1 @@
[Startup]
diff --git a/prebuild.xml b/prebuild.xml
index 922d108..35976cc 100644
--- a/prebuild.xml
+++ b/prebuild.xml
@@ -1595,6 +1595,38 @@
1595 </Files> 1595 </Files>
1596 </Project> 1596 </Project>
1597 1597
1598 <Project frameworkVersion="v3_5" name="OpenSim.ConsoleClient" path="OpenSim/ConsoleClient" type="Exe">
1599 <Configuration name="Debug">
1600 <Options>
1601 <OutputPath>../../bin/</OutputPath>
1602 </Options>
1603 </Configuration>
1604 <Configuration name="Release">
1605 <Options>
1606 <OutputPath>../../bin/</OutputPath>
1607 </Options>
1608 </Configuration>
1609
1610 <ReferencePath>../../bin/</ReferencePath>
1611 <Reference name="System"/>
1612 <Reference name="System.Xml"/>
1613 <Reference name="OpenMetaverseTypes.dll"/>
1614 <Reference name="OpenMetaverse.dll"/>
1615 <Reference name="OpenMetaverse.StructuredData.dll"/>
1616 <Reference name="OpenSim.Framework"/>
1617 <Reference name="OpenSim.Framework.Console"/>
1618 <Reference name="OpenSim.Framework.Servers.HttpServer"/>
1619 <Reference name="OpenSim.Server.Base"/>
1620 <Reference name="Nini.dll" />
1621 <Reference name="log4net.dll"/>
1622
1623 <Files>
1624 <Match pattern="*.cs" recurse="false">
1625 <Exclude pattern="Tests" />
1626 </Match>
1627 </Files>
1628 </Project>
1629
1598 <Project frameworkVersion="v3_5" name="OpenSim.Region.CoreModules" path="OpenSim/Region/CoreModules" type="Library"> 1630 <Project frameworkVersion="v3_5" name="OpenSim.Region.CoreModules" path="OpenSim/Region/CoreModules" type="Library">
1599 <Configuration name="Debug"> 1631 <Configuration name="Debug">
1600 <Options> 1632 <Options>