static void XapFiles(ZipArchive zip, string dir) { ICollection<LanguageInfo> langs = FindSourceLanguages(dir); string manifestPath = Path.Combine(dir, "AppManifest.xaml"); IList<Uri> assemblies; if (File.Exists(manifestPath)) { assemblies = GetManifestAssemblies(manifestPath); } else { assemblies = GetLanguageAssemblies(langs); // generate the manfiest using (Stream appManifest = zip.Create("AppManifest.xaml")) { Chiron.ManifestTemplate.Generate(assemblies).Save(appManifest); } } AddAssemblies(zip, dir, assemblies); GenerateLanguagesConfig(zip, langs); AddPathDirectories(zip); // add files on disk last so they always overwrite generated files zip.CopyFromDirectory(dir, ""); zip.Close(); }
static void XapFiles(ZipArchive zip, string dir) { ICollection<LanguageInfo> langs; IList<Uri> assemblies, externals; string manifestPath = Path.Combine(dir, "AppManifest.xaml"); if (File.Exists(manifestPath)) { langs = FindSourceLanguages(dir); assemblies = GetManifestAssemblies(manifestPath); // Note: because the manifest file already exists, nothing // needs to be done to support TPEs: Chiron doesn't need to host // them because they are assumed to be a well-known internet location. externals = null; } else { using (Stream appManifest = zip.Create("AppManifest.xaml")) { GenerateManifest(dir, out langs, out assemblies, out externals).Save(appManifest); } } AddAssemblies(zip, dir, assemblies); GenerateLanguagesConfig(zip, langs); AddPathDirectories(zip); // add files on disk last so they always overwrite generated files zip.CopyFromDirectory(dir, ""); zip.Close(); }
static void XapFiles(ZipArchive zip, string dir) { ICollection<LanguageInfo> langs; IList<Uri> assemblies, externals; string manifestPath = Path.Combine(dir, "AppManifest.xaml"); if (File.Exists(manifestPath)) { langs = FindSourceLanguages(dir); GetManifestParts(manifestPath, out assemblies, out externals); } else { using (Stream appManifest = zip.Create("AppManifest.xaml")) { GenerateManifest(dir, out langs, out assemblies, out externals).Save(appManifest); } } AddAssemblies(zip, dir, assemblies); GenerateLanguagesConfig(zip, langs); AddPathDirectories(zip); // add files on disk last so they always overwrite generated files zip.CopyFromDirectory(dir, ""); zip.Close(); }
// add directories that are on Chiron's path internal static void AddPathDirectories(ZipArchive zip) { if (Chiron.LocalPath != null) { foreach (var path in Chiron.LocalPath) { string[] splitPath = path.Split(Path.DirectorySeparatorChar); zip.CopyFromDirectory(path, splitPath[splitPath.Length - 1]); } } }
public override void ProcessRequest(HttpContext context) { InternalProcessRequest(context, delegate(string pdirpath, string path) { // create in memory XAP archive if (Directory.Exists(pdirpath)) { MemoryStream ms = new MemoryStream(); ZipArchive xap = new ZipArchive(ms, FileAccess.Write); xap.CopyFromDirectory(pdirpath, ""); xap.Close(); var xapBuffer = ms.ToArray(); context.Response.OutputStream.Write(xapBuffer, 0, xapBuffer.Length); } else { throw new HttpException(404, "Missing " + path); } }); }
// Generates languages.config file // this is needed by the DLR to load arbitrary DLR-based languages implementations private static void GenerateLanguagesConfig(ZipArchive zip, ICollection<LanguageInfo> langs) { bool needLangConfig = false; foreach (LanguageInfo lang in langs) { if (lang.LanguageContext != "") { needLangConfig = true; break; } } // Only need language configuration file for non-builtin languages if (needLangConfig) { Stream outStream = zip.Create("languages.config"); StreamWriter writer = new StreamWriter(outStream); writer.WriteLine("<Languages>"); foreach (LanguageInfo lang in langs) { writer.WriteLine(" <Language"); writer.WriteLine(" names=\"{0}\"", lang.GetNames()); writer.WriteLine(" languageContext=\"{0}\"", lang.LanguageContext); writer.WriteLine(" extensions=\"{0}\"", lang.GetExtensionsString()); writer.WriteLine(" assemblies=\"{0}\"", lang.GetAssemblyNames()); writer.WriteLine(" external=\"{0}\"", lang.External); writer.WriteLine(" />"); } writer.WriteLine("</Languages>"); writer.Close(); } }
// Adds assemblies with relative paths into the XAP file private static void AddAssemblies(ZipArchive zip, string dir, IList<Uri> assemblyLocations) { foreach (Uri uri in assemblyLocations) { if (IsPathRooted(uri)) { continue; } string targetPath = uri.OriginalString; string localPath = Path.Combine(dir, targetPath); if (!File.Exists(localPath)) { localPath = Chiron.TryGetAssemblyPath(targetPath); if (localPath == null) { throw new ApplicationException("Could not find assembly: " + uri); } } zip.CopyFromFile(localPath, targetPath); // Copy PDBs if available string pdbPath = Path.ChangeExtension(localPath, ".pdb"); string pdbTarget = Path.ChangeExtension(targetPath, ".pdb"); if (File.Exists(pdbPath)) { zip.CopyFromFile(pdbPath, pdbTarget); } } }
static int Main(string[] args) { ParseOptions(args); if (!_NoLogo) { Console.WriteLine( "Chiron - Silverlight Dynamic Language Development Utility. Version {0}", typeof(Chiron).Assembly.GetName().Version ); } if (_Help) { Console.WriteLine( @"Usage: Chiron [<options>] Common usages: Chiron.exe /b Starts the web-server on port 2060, and opens the default browser to the root of the web-server. This is used for developing an application, as Chiron will rexap you application's directory for every request. Chiron.exe /d:app /z:app.xap Takes the contents of the app directory and generates an app.xap from it, which embeds the DLR and language assemblies according to the settings in Chiron.exe.config. This is used for deployment, so you can take the generated app.xap, along with any other files, and host them on any web-server. Options: Note: forward-slashes (/) in option names can be substituted for dashes (-). For example ""Chiron.exe -w"" instead of ""Chiron.exe /w"". /w[ebserver][:<port number>] Launches a development web server that automatically creates XAP files for dynamic language applications (runs /z for every request of a XAP file, but generates it in memory). Optionally specifies server port number (default: 2060) /b[rowser][:<start url>] Launches the default browser and starts the web server Implies /w, cannot be combined with /x or /z /z[ipdlr]:<file> Generates a XAP file, including dynamic language dependencies, and auto-generates AppManifest.xaml (equivalent of /m in memory), if it does not exist. Does not start the web server, cannot be combined with /w or /b /m[anifest] Saves the generated AppManifest.xaml file to disk Use /d to set the directory containing the sources Can only be combined with /d, /n and /s /d[ir[ectory]]:<path> Specifies directory on disk (default: the current directory). Implies /w. /r[efpath]:<path> Path where assemblies are located. Defaults to the same directory where Chiron.exe exists. Overrides appSettings.localAssemblyPath in Chiron.exe.config. /p[ath]:<path1;path2;..;pathn> Semi-colon-separated directories to be included in the XAP file, in addition to what is specified by /d /u[rlprefix]:<relative or absolute uri> Appends a relative or absolute Uri to each language assembly or extension added to the AppManifest.xaml. If a relative Uri is provided, Chiron will serve all files located in the /refpath at this Uri, relative to the root of the web-server. Overrides appSettings.urlPrefix in Chiron.exe.config. /nl /noLanguageDetection Without this flag, Chiron scans the current application directory for files with a valid language's file extension, and only makes those languages available to the XAP file. See /useExtensions for whether the languages assemblies or extension files are used. With this flag, no language-specific assemblies/extensions are added to the XAP, so the Silverlight application is responsible for parsing the languages.config file in the XAP and downloading the languages it needs. Overrides appSettings.detectLanguages in Chiron.exe.config. /e /useExtensions:true|false (default false) Toggles whether or not language and DLR assemblies are embedded in the XAP file, or whether their equivalent extension files are used. /a /anyAddress By default Chiron listens on just the loopback IP address, meaning it only works for local requests. Providing this flag will cause Chiron to listen on any IP address, making it an internet-facing webserver. This option should only be used during development when running the Silverlight app on one machine and testing on many machines; Chiron is not optimized as a production webserver. /x[ap[file]]:<file> Specifies XAP file to generate. Only XAPs a directory; does not generate a manifest or add dynamic language DLLs; see /z for that functionality. Does not start the web server, cannot be combined with /w or /b /notification Display notification icon /n[ologo] Suppresses display of the logo banner /s[ilent] Suppresses display of all output "); } else if (_Error != null) { return Error(1000, "options", _Error); } else if (!string.IsNullOrEmpty(_XapFile)) { try { if (!_Silent) Console.WriteLine("Generating XAP {0} from {1}", _XapFile, _Directory); if (_XapDlr) { XapBuilder.XapToDisk(_Directory, _XapFile); } else { ZipArchive xap = new ZipArchive(_XapFile, FileAccess.Write); XapBuilder.AddPathDirectories(xap); xap.CopyFromDirectory(_Directory, ""); xap.Close(); } } catch (Exception ex) { return Error(1001, "xap", ex.Message); } } else if (_SaveManifest) { try { string manifest = Path.Combine(_Directory, "AppManifest.xaml"); if (File.Exists(manifest)) { return Error(3002, "manifest", "AppManifest.xaml already exists at path " + manifest); } // Generate the AppManifest.xaml file to disk, as we would if we were // generating it in the XAP XapBuilder.GenerateManifest(_Directory).Save(manifest); } catch (Exception ex) { return Error(3001, "manifest", ex.Message); } } else { string uri = string.Format("http://localhost:{0}/", _Port); if (!_Silent) Console.WriteLine("Chiron serving '{0}' as {1}", _Directory, uri); try { HttpServer server = new HttpServer(_Port, _Directory); server.Start(); if (_LaunchBrowser) { if (_StartPage != null) { uri += _StartPage; } ProcessStartInfo startInfo = new ProcessStartInfo(uri); startInfo.UseShellExecute = true; startInfo.WorkingDirectory = _Directory; Process p = new Process(); p.StartInfo = startInfo; p.Start(); } if (_NotifyIcon) { Thread notify = new Thread( () => { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); var notification = new Notification(_Directory, _Port); Application.Run(); } ); notify.SetApartmentState(ApartmentState.STA); notify.IsBackground = true; notify.Start(); } while (server.IsRunning) Thread.Sleep(500); } catch (Exception ex) { return Error(2001, "server", ex.Message); } } return 0; }
bool TryProcessXapListingRequest(HttpSocket s, string uri, string path) { // path should end with '\' (for XAP listing) if (!path.EndsWith(Path.DirectorySeparatorChar.ToString())) return false; path = path.Substring(0, path.Length - 1); // must end with XAP if (string.Compare(Path.GetExtension(path), ".xap", StringComparison.OrdinalIgnoreCase) != 0) return false; // file must exist if (!File.Exists(path)) return false; // see if need to serve file from XAP string filename = null; int iq = uri.IndexOf('?'); if (iq >= 0) filename = uri.Substring(iq + 1); ZipArchive xap = null; try { // open XAP file xap = new ZipArchive(path, FileAccess.Read); if (string.IsNullOrEmpty(filename)) { // list contents List<ZipArchiveFile> xapContents = new List<ZipArchiveFile>(); foreach (KeyValuePair<string, ZipArchiveFile> p in xap.entries) xapContents.Add(p.Value); s.WriteTextResponse(200, "html", HtmlFormatter.FormatXapListing(uri, xapContents), false); return true; } // server file from XAP ZipArchiveFile f = null; if (!xap.entries.TryGetValue(filename, out f)) { s.WriteErrorResponse(404, "Resource not found in XAP"); return true; } // check mime type string mimeType = HttpSocket.GetMimeType(filename); if (string.IsNullOrEmpty(mimeType)) { s.WriteErrorResponse(403); return true; } // get the content byte[] body = new byte[(int)f.Length]; if (body.Length > 0) { using (Stream fs = f.OpenRead()) { fs.Read(body, 0, body.Length); } } // write the resposne s.WriteResponse(200, string.Format("Content-type: {0}\r\n", mimeType), body, false); return true; } catch { s.WriteErrorResponse(500, "error reading XAP"); return true; } finally { if (xap != null) xap.Close(); } }
static int Main(string[] args) { ParseOptions(args); if (!_nologo) { Console.WriteLine( "Chiron - Silverlight Development Utility. Version {0}", typeof(Chiron).Assembly.GetName().Version ); } if (_help) { Console.WriteLine( @"Usage: Chiron [<options>] Options: /w[ebserver][:<port number>] Launches a development web server that automatically creates XAP files for dynamic language applications (runs /z for every request of a XAP file, but generates it in memory). Optionally specifies server port number (default: 2060) /b[rowser][:<start url>] Launches the default browser and starts the web server Implies /w, cannot be combined with /x or /z /z[ipdlr]:<file> Generates a XAP file, including dynamic language DLLs, and auto-generates AppManifest.xaml (equivalent of /m in memory), if it does not exist. Does not start the web server, cannot be combined with /w or /b /m[anifest] Saves the generated AppManifest.xaml file to disk Use /d to set the directory containing the sources Can only be combined with /d, /n and /s /d[ir[ectory]]:<path> Specifies directory on disk (default: the current directory) /r[efpath]:<path> Path where assemblies are located. Overrides appSettings.localAssemblyPath in Chiron.exe.config /p[ath]:<path1;path2;..;pathn> semi-color-separated directories to be included in the XAP file, in addition to what is specified by /d /l[ocalAppRoot]:<relative path> Path to look for script files on the web-server, rather than in the XAP file (which is default). Path is relative to the XAP file. If Chiron is generating the AppManifest.xaml, it will use this to find which languages the application depends on. /e[xtUrlPrefix]:<absolute uri> (>= Silverlight 3 only) Does not put the assemblies inside the XAP file, and references the appropriate slvx files from the Uri provided. Overrides appSettings.externalUrlPrefix in Chiron.exe.config /u[rlprefix]:<relative or absolute uri> appends a relative or absolute Uri to each language assembly added to the AppManifest.xaml. Also does not put the assemblies inside the xap. If it's a relative Uri and /w is also given, Chiron will serve the assemblies from the Uri, relative to the server root. Overrides appSettings.urlPrefix in Chiron.exe.config /x[ap[file]]:<file> Specifies XAP file to generate. Only XAPs a directory; does not generate a manifest or add dynamic language DLLs; see /z for that functionality. Does not start the web server, cannot be combined with /w or /b /n[ologo] Suppresses display of the logo banner /s[ilent] Suppresses display of all output "); } else if (_error != null) { return Error(1000, "options", _error); } else if (!string.IsNullOrEmpty(_xapfile)) { try { if (!_silent) Console.WriteLine("Generating XAP {0} from {1}", _xapfile, _dir); if (_zipdlr) { XapBuilder.XapToDisk(_dir, _xapfile); } else { ZipArchive xap = new ZipArchive(_xapfile, FileAccess.Write); XapBuilder.AddPathDirectories(xap); xap.CopyFromDirectory(_dir, ""); xap.Close(); } } catch (Exception ex) { return Error(1001, "xap", ex.Message); } } else if (_saveManifest) { try { string manifest = Path.Combine(_dir, "AppManifest.xaml"); if (File.Exists(manifest)) { return Error(3002, "manifest", "AppManifest.xaml already exists at path " + manifest); } // Generate the AppManifest.xaml file to disk, as we would if we were // generating it in the XAP XapBuilder.GenerateManifest(_dir).Save(manifest); } catch (Exception ex) { return Error(3001, "manifest", ex.Message); } } else { string uri = string.Format("http://localhost:{0}/", _port); if (!_silent) Console.WriteLine("Chiron serving '{0}' as {1}", _dir, uri); try { HttpServer server = new HttpServer(_port, _dir); server.Start(); if (_browser) { if (_startPage != null) { uri += _startPage; } ProcessStartInfo startInfo = new ProcessStartInfo(uri); startInfo.UseShellExecute = true; startInfo.WorkingDirectory = _dir; Process p = new Process(); p.StartInfo = startInfo; p.Start(); } while (server.IsRunning) Thread.Sleep(500); } catch (Exception ex) { return Error(2001, "server", ex.Message); } } return 0; }
static int Main(string[] args) { ParseOptions(args); if (!_nologo) { Console.WriteLine( @"Microsoft(R) Silverlight(TM) Development Utility. Version {0} Copyright (c) Microsoft Corporation. All rights reserved. ", typeof(Chiron).Assembly.GetName().Version); } if (_help) { Console.WriteLine( @"Usage: Chiron [<options>] General Options: /d[irectory]:<path> Specifies directory on disk (default: the current directory) /x[ap]:<file> Specifies XAP file to generate Does not start the web server, cannot be combined with /w or /b /n[ologo] Suppresses display of the logo banner /s[ilent] Suppresses display of all output Dynamic Language Options: /z[ipdlr]:<file> Like /x, but includes files needed for dynamic language apps Does not start the web server, cannot be combined with /w or /b /w[ebserver][:<port number>] Launches a development web server that automatically creates XAP files for dynamic language applications Optionally specifies server port number (default: 2060) /b[rowser][:<start url>] Launches the default browser and starts the web server Implies /w, cannot be combined with /x or /z /m[anifest] Saves the generated AppManifest.xaml file to disk Use /d to set the directory containing the sources Can only be combined with /d, /n and /s "); } else if (_error != null) { return Error(1000, "options", _error); } else if (!string.IsNullOrEmpty(_xapfile)) { try { if (!_silent) Console.WriteLine("Generating XAP {0} from {1}", _xapfile, _dir); if (_zipdlr) { XapBuilder.XapToDisk(_dir, _xapfile); } else { ZipArchive xap = new ZipArchive(_xapfile, FileAccess.Write); xap.CopyFromDirectory(_dir, ""); xap.Close(); } } catch (Exception ex) { return Error(1001, "xap", ex.Message); } } else if (_saveManifest) { try { string manifest = Path.Combine(_dir, "AppManifest.xaml"); if (File.Exists(manifest)) { return Error(3002, "manifest", "AppManifest.xaml already exists at path " + manifest); } // Generate the AppManifest.xaml file to disk, as we would if we were // generating it in the XAP XapBuilder.GenerateManifest(_dir).Save(manifest); } catch (Exception ex) { return Error(3001, "manifest", ex.Message); } } else { string uri = string.Format("http://localhost:{0}/", _port); if (!_silent) Console.WriteLine("Chiron serving '{0}' as {1}", _dir, uri); try { HttpServer server = new HttpServer(_port, _dir); server.Start(); if (_browser) { if (_startPage != null) { uri += _startPage; } ProcessStartInfo startInfo = new ProcessStartInfo(uri); startInfo.UseShellExecute = true; startInfo.WorkingDirectory = _dir; Process p = new Process(); p.StartInfo = startInfo; p.Start(); } while (server.IsRunning) Thread.Sleep(500); } catch (Exception ex) { return Error(2001, "server", ex.Message); } } return 0; }
static int Main(string[] args) { ParseOptions(args); if (!_nologo) { Console.WriteLine( "Chiron - Silverlight Development Utility. Version {0}", typeof(Chiron).Assembly.GetName().Version ); } if (_help) { Console.WriteLine( @"Usage: Chiron [<options>] Common usages: Chiron.exe /b Starts the web-server on port 2060, and opens the default browser to the root of the web-server. This is used for developing an application, as Chiron will rexap you application's directory for every request. Chiron.exe /d:app /z:app.xap Takes the contents of the app directory and generates an app.xap from it, which embeds the DLR and language assemblies according to the settings in Chiron.exe.config. This is used for deployment, so you can take the generated app.xap, along with any other files, and host them on any web-server. Options: Note: forward-slashes (/) in option names can be substituted for dashes (-). For example ""Chiron.exe -w"" instead of ""Chiron.exe /w"". /w[ebserver][:<port number>] Launches a development web server that automatically creates XAP files for dynamic language applications (runs /z for every request of a XAP file, but generates it in memory). Optionally specifies server port number (default: 2060) /b[rowser][:<start url>] Launches the default browser and starts the web server Implies /w, cannot be combined with /x or /z /z[ipdlr]:<file> Generates a XAP file, including dynamic language dependencies, and auto-generates AppManifest.xaml (equivalent of /m in memory), if it does not exist. Does not start the web server, cannot be combined with /w or /b /m[anifest] Saves the generated AppManifest.xaml file to disk Use /d to set the directory containing the sources Can only be combined with /d, /n and /s /d[ir[ectory]]:<path> Specifies directory on disk (default: the current directory). Implies /w. /r[efpath]:<path> Path where assemblies are located. Defaults to the same directory where Chiron.exe exists. Overrides appSettings.localAssemblyPath in Chiron.exe.config. /p[ath]:<path1;path2;..;pathn> Semi-colon-separated directories to be included in the XAP file, in addition to what is specified by /d /u[rlprefix]:<relative or absolute uri> Appends a relative or absolute Uri to each language assembly or extension added to the AppManifest.xaml. If a relative Uri is provided, Chiron will serve all files located in the /refpath at this Uri, relative to the root of the web-server. Overrides appSettings.urlPrefix in Chiron.exe.config. /l /detectLanguages:true|false (default true) Scans the current application directory for files with a valid language's file extension, and only makes those languages available to the XAP file. See /useExtensions for whether the languages assemblies or extension files are used. If false, no language-specific assemblies/extensions are added to the XAP, so the Silverlight application is responsible for parsing the languages.config file in the XAP and downloading the languages it needs. Overrides appSettings.detectLanguages in Chiron.exe.config. /e /useExtensions:true|false (default false) Toggles whether or not language and DLR assemblies are embedded in the XAP file, or whether their equivalent extension files are used. /x[ap[file]]:<file> Specifies XAP file to generate. Only XAPs a directory; does not generate a manifest or add dynamic language DLLs; see /z for that functionality. Does not start the web server, cannot be combined with /w or /b /notification Display notification icon /n[ologo] Suppresses display of the logo banner /s[ilent] Suppresses display of all output "); } else if (_error != null) { return(Error(1000, "options", _error)); } else if (!string.IsNullOrEmpty(_xapfile)) { try { if (!_silent) { Console.WriteLine("Generating XAP {0} from {1}", _xapfile, _dir); } if (_zipdlr) { XapBuilder.XapToDisk(_dir, _xapfile); } else { ZipArchive xap = new ZipArchive(_xapfile, FileAccess.Write); XapBuilder.AddPathDirectories(xap); xap.CopyFromDirectory(_dir, ""); xap.Close(); } } catch (Exception ex) { return(Error(1001, "xap", ex.Message)); } } else if (_saveManifest) { try { string manifest = Path.Combine(_dir, "AppManifest.xaml"); if (File.Exists(manifest)) { return(Error(3002, "manifest", "AppManifest.xaml already exists at path " + manifest)); } // Generate the AppManifest.xaml file to disk, as we would if we were // generating it in the XAP XapBuilder.GenerateManifest(_dir).Save(manifest); } catch (Exception ex) { return(Error(3001, "manifest", ex.Message)); } } else { string uri = string.Format("http://localhost:{0}/", _port); if (!_silent) { Console.WriteLine("Chiron serving '{0}' as {1}", _dir, uri); } try { HttpServer server = new HttpServer(_port, _dir); server.Start(); if (_browser) { if (_startPage != null) { uri += _startPage; } ProcessStartInfo startInfo = new ProcessStartInfo(uri); startInfo.UseShellExecute = true; startInfo.WorkingDirectory = _dir; Process p = new Process(); p.StartInfo = startInfo; p.Start(); } if (_notifyIcon) { Thread notify = new Thread( () => { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); var notification = new Notification(_dir, _port); Application.Run(); } ); notify.SetApartmentState(ApartmentState.STA); notify.IsBackground = true; notify.Start(); } while (server.IsRunning) { Thread.Sleep(500); } } catch (Exception ex) { return(Error(2001, "server", ex.Message)); } } return(0); }