static void Main(string[] argv) {
      if (argv == null || argv.Length < 1) {
        Console.WriteLine("Usage: Main <assemblys> [<outputPath>]");
      }

      using (var host = new PeReader.DefaultHost()) {
        var module = host.LoadUnitFrom(argv[0]) as IModule;
        if (module == null || module == Dummy.Module || module == Dummy.Assembly) {
          throw new Exception(argv[0] + " is not a PE file containing a CLR assembly, or an error occurred when loading it.");
        } 

        PdbReader pdbReader = null;
        string pdbFile = Path.ChangeExtension(module.Location, "pdb");
        if (File.Exists(pdbFile)) {
          using (var pdbStream = File.OpenRead(pdbFile)) {
            pdbReader = new PdbReader(pdbStream, host);
          }
        } else
          Console.WriteLine("Could not load the PDB file for '" + module.Name.Value + "' . Proceeding anyway.");

        using (pdbReader) {

          var copy = new MetadataDeepCopier(host).Copy(module);
          var shadowFieldsAddedAssembly = new ShadowFieldRewriter(host).Rewrite(copy);
          var shadowFieldsAndMethodsAddedAssembly = new ShadowMethodRewriter(host).Rewrite(shadowFieldsAddedAssembly);
          var rewrittenAssembly = new FinalizeMethodRewriter(host).Rewrite(shadowFieldsAndMethodsAddedAssembly);

          var main = rewrittenAssembly.EntryPoint.ResolvedMethod;
          if (main != Dummy.Method) {
            var body = main.Body as MethodBody;
            if (body != null)
              new AddGCWaitForFinalization(host, body).Rewrite();
          }

          var validator = new MetadataValidator(host);
          validator.Validate(rewrittenAssembly as IAssembly);

          string outputPath = rewrittenAssembly.Location + ".meta";
          var outputFileName = Path.GetFileNameWithoutExtension(outputPath);

          // Need to not pass in a local scope provider until such time as we have one that will use the mutator
          // to remap things (like the type of a scope constant) from the original assembly to the mutated one.
          using (var peStream = File.Create(outputPath)) {
            using (var pdbWriter = new PdbWriter(outputFileName + ".pdb", pdbReader)) {
              PeWriter.WritePeToStream(rewrittenAssembly, host, peStream, pdbReader, null, pdbWriter);
            }
          }
        }
      }
    }
    void AssertWriteToPeFile(PeVerifyResult expectedResult, IAssembly assembly, string pdbPath) {
      var validator = new MetadataValidator(this.host);
      List<Microsoft.Cci.ErrorEventArgs> errorEvents = new List<Microsoft.Cci.ErrorEventArgs>();
      this.host.Errors += (object sender, Microsoft.Cci.ErrorEventArgs e) => errorEvents.Add(e);
      validator.Validate(assembly);
      Debug.Assert(errorEvents.Count == 0);
      using (var rewrittenFile = File.Create(assembly.Location)) {
        if (pdbPath != null) {
          using (var f = File.OpenRead(pdbPath)) {
            using (var pdbReader = new PdbReader(f, host)) {
              using (var pdbWriter = new PdbWriter(Path.GetFullPath(assembly.Location + ".pdb"), pdbReader)) {
                PeWriter.WritePeToStream(assembly, host, rewrittenFile, pdbReader, pdbReader, pdbWriter);
              }
            }
          }
        } else {
          using (var pdbWriter = new PdbWriter(Path.GetFullPath(assembly.Location + ".pdb"), null)) {
            PeWriter.WritePeToStream(assembly, host, rewrittenFile, null, null, pdbWriter);
          }
        }
      }

      Assert.True(File.Exists(assembly.Location));
      PeVerify.Assert(expectedResult, PeVerify.VerifyAssembly(assembly.Location, true));
    }