private static void UnpackResources() { // We don't unpack into the final directory so we can be transactional (all or nothing). string prepDir = SupportFileDir + ".new"; Directory.CreateDirectory(prepDir); // Unpack the files. // We used to used GetEntryAssembly, but that makes using PerfView as a component of a larger EXE // problematic. Instead use GetExecutingAssembly, which means that you have to put SupportFiles.cs // in your main program var resourceAssembly = System.Reflection.Assembly.GetExecutingAssembly(); foreach (var resourceName in resourceAssembly.GetManifestResourceNames()) { if (resourceName.StartsWith(@".\") || resourceName.StartsWith(@"./")) { // Unpack everything, inefficient, but insures ldr64 works. string targetPath = Path.Combine(prepDir, resourceName); if (!ResourceUtilities.UnpackResourceAsFile(resourceName, targetPath, resourceAssembly)) { throw new ApplicationException("Could not unpack support file " + resourceName); } } } // Commit the unpack, we try several times since antiviruses often lock the directory for (int retries = 0; ; retries++) { try { Directory.Move(prepDir, SupportFileDir); break; } catch (Exception) { if (retries > 5) { throw; } } System.Threading.Thread.Sleep(100); } }
/// <summary> /// Displayes an the embeded HTML user's guide in a browser. /// </summary> /// <returns>true if successful.</returns> public static bool DisplayUsersGuide(string resourceName) { string tempDir = Environment.GetEnvironmentVariable("TEMP"); if (tempDir == null) { tempDir = "."; } string appPath = System.Reflection.Assembly.GetExecutingAssembly().ManifestModule.FullyQualifiedName; string appName = Path.GetFileNameWithoutExtension(appPath); string usersGuideFilePath = Path.Combine(tempDir, appName + "." + resourceName); if (ResourceUtilities.UnpackResourceAsFile(resourceName, usersGuideFilePath)) { Process process = new Process(); process.StartInfo = new ProcessStartInfo(usersGuideFilePath); process.Start(); // TODO I am leaking the file (but it is in the temp directory. return(true); } return(false); }
/// <summary> /// Takes an manifest XML in manifestXmlPath and compiles it into a DLL that can /// be registered using wevtutil placing it in string manifestDllPath /// </summary> private static void CompileManifest(string manifestXmlPath, string manifestDllPath) { DirectoryUtilities.Clean(WorkingDir); // Get the tools and put them on my path. string toolsDir = Path.Combine(WorkingDir, "tools"); Directory.CreateDirectory(toolsDir); ResourceUtilities.UnpackResourceAsFile(@".\mc.exe", Path.Combine(toolsDir, "mc.exe")); ResourceUtilities.UnpackResourceAsFile(@".\rc.exe", Path.Combine(toolsDir, "rc.exe")); ResourceUtilities.UnpackResourceAsFile(@".\rcdll.dll", Path.Combine(toolsDir, "rcdll.dll")); // put runtimeDir directory on the path so that we have the CSC on the path. string runtimeDir = RuntimeEnvironment.GetRuntimeDirectory(); Environment.SetEnvironmentVariable("PATH", toolsDir + ";" + runtimeDir + ";" + Environment.GetEnvironmentVariable("PATH")); // Unpack the winmeta.xml file string dataDir = Path.Combine(WorkingDir, "data"); Directory.CreateDirectory(dataDir); ResourceUtilities.UnpackResourceAsFile(@".\winmeta.xml", Path.Combine(dataDir, "winmeta.xml")); // Compile Xml manifest into a binary reasource, this produces a // * MANIFEST.rc A text description of the resource which refers to // * MANIFESTTEMP.Bin The binary form of the manifest // * MANIFEST_MSG00001.Bin The localized strings from the manifest Console.WriteLine("Compiling Manifest {0} to ETW binary form.", manifestXmlPath); try { string inputXml = Path.Combine(dataDir, Path.GetFileName(manifestXmlPath)); File.Copy(manifestXmlPath, inputXml); Command.Run(string.Format("{0} -W \"{1}\" -b \"{2}\"", Path.Combine(toolsDir, "mc.exe"), Path.Combine(dataDir, "winmeta.xml"), inputXml), new CommandOptions().AddCurrentDirectory(dataDir)); string rcFilePath = Path.ChangeExtension(inputXml, ".rc"); Debug.Assert(File.Exists(rcFilePath)); // Compile the .rc file into a .res file (which is the binary form of everything in the // .rc file Command.Run(string.Format("rc \"{0}\"", rcFilePath)); string resFilePath = Path.ChangeExtension(inputXml, ".res"); Debug.Assert(File.Exists(resFilePath)); // Make a dummy c# file string csFilePath = Path.Combine(dataDir, Path.GetFileNameWithoutExtension(inputXml) + ".cs"); File.WriteAllText(csFilePath, ""); // At this point we have .RES file, we now create a etw manifest dll to hold it a Console.WriteLine("Creating Manifest DLL to hold binary Manifest at {0}.", manifestDllPath); FileUtilities.ForceDelete(manifestDllPath); Command.Run(string.Format("csc /nologo /target:library \"/out:{0}\" \"/win32res:{1}\" \"{2}\"", manifestDllPath, resFilePath, csFilePath)); Debug.Assert(File.Exists(manifestDllPath)); } catch (Exception e) { throw new ApplicationException( "ERROR: compilation of the ETW manifest failed.\r\n" + "File: " + manifestXmlPath + "\r\n" + "Details:\r\n" + e.Message); } finally { DirectoryUtilities.Clean(WorkingDir); } }