public AddInActivatorProcess(string friendlyName, bool redirectOutput, AddInDomainSetup addInDomainSetup) { this._friendlyName = friendlyName; this._redirectOutput = redirectOutput; this._addInDomainSetup = addInDomainSetup; this._assemblyFile = AddInActivatorHostAssemblyCompiler.CreateRemoteHostAssembly(friendlyName, addInDomainSetup); this._addInDomainSetupFile = Path.Combine(addInDomainSetup.TempFilesDirectory, string.Format(ConfigFileStringFormat, friendlyName)); this._addInDomainLogFile = Path.Combine(addInDomainSetup.TempFilesDirectory, string.Format(LogFileStringFormat, friendlyName)); ProcessStartInfo processStartInfo = new ProcessStartInfo(); processStartInfo.CreateNoWindow = true; processStartInfo.ErrorDialog = false; processStartInfo.FileName = this._assemblyFile; processStartInfo.RedirectStandardError = true; processStartInfo.RedirectStandardOutput = true; processStartInfo.UseShellExecute = false; processStartInfo.Verb = "runas"; processStartInfo.WorkingDirectory = this._addInDomainSetup.WorkingDirectory; if (this._addInDomainSetup.EnvironmentVariables != null) { foreach (KeyValuePair <string, string> item in this._addInDomainSetup.EnvironmentVariables) { processStartInfo.EnvironmentVariables[item.Key] = item.Value; } } this._process = new Process(); this._process.StartInfo = processStartInfo; this._process.OutputDataReceived += this.OnProcessDataReceived; this._process.ErrorDataReceived += this.OnProcessDataReceived; this._process.Exited += this.OnProcessExited; this._process.EnableRaisingEvents = true; }
/// <summary> /// Static Method WriteSetupFile. /// </summary> /// <param name="addInDomainSetup">Instance of AddInDomainSetup.</param> /// <param name="filename">Setup file name.</param> internal static void WriteSetupFile(AddInDomainSetup addInDomainSetup, string filename) { BinaryFormatter formatter = new BinaryFormatter(); using (FileStream fileStream = new FileStream(filename, FileMode.Create, FileAccess.Write)) { formatter.Serialize(fileStream, addInDomainSetup); } }
public static string CreateRemoteHostAssembly(string friendlyName, AddInDomainSetup addInDomainSetup) { if (!Directory.Exists(addInDomainSetup.TempFilesDirectory)) { Directory.CreateDirectory(addInDomainSetup.TempFilesDirectory); } ////Dictionary<string, string> providerOptions = new Dictionary<string, string> { { "CompilerVersion", "v2.0" } }; CompilerResults results = null; List <string> compilerArgs = new List <string> { AddInPlatformTarget.GetPlatformTargetCompilerArgument(addInDomainSetup.Platform) }; #if DEBUG compilerArgs.Add("/define:DEBUG"); #endif CompilerParameters compilerParameters = new CompilerParameters(); compilerParameters.CompilerOptions = string.Join(" ", compilerArgs.ToArray()); compilerParameters.GenerateExecutable = true; compilerParameters.GenerateInMemory = false; compilerParameters.OutputAssembly = Path.Combine(addInDomainSetup.TempFilesDirectory, string.Format(OutputAssemblyFileStringFormat, friendlyName)); compilerParameters.ReferencedAssemblies.AddRange(ReferencedAssemblies); string assemblySource = DevLib.AddIn.Properties.Resources.Program.Replace("$[AddInActivatorHostTypeName]", typeof(AddInActivatorHost).AssemblyQualifiedName).Replace("$[AddInAssemblyName]", typeof(AddInActivatorHost).Assembly.FullName); ////using (CSharpCodeProvider provider = new CSharpCodeProvider(providerOptions)) using (CSharpCodeProvider provider = new CSharpCodeProvider()) { results = provider.CompileAssemblyFromSource(compilerParameters, assemblySource); } if (results.Errors.HasWarnings) { AddInAssemblyCompilerException addInAssemblyCompilerException = new AddInAssemblyCompilerException("Succeeded to compile assembly for AddInDomain with warnings.", results.Errors); Debug.WriteLine(string.Format(AddInConstants.WarningStringFormat, "DevLib.AddIn.AddInActivatorHostAssemblyCompiler.CreateRemoteHostAssembly", results.ToString(), addInAssemblyCompilerException.ToString(), results.Output.ToString(), string.Empty)); } if (results.Errors.HasErrors) { AddInAssemblyCompilerException addInAssemblyCompilerException = new AddInAssemblyCompilerException("Failed to compile assembly for AddInDomain due to compiler errors.", results.Errors); Debug.WriteLine(string.Format(AddInConstants.ExceptionStringFormat, "DevLib.AddIn.AddInActivatorHostAssemblyCompiler.CreateRemoteHostAssembly", results.ToString(), addInAssemblyCompilerException.ToString(), results.Output.ToString(), string.Empty)); throw addInAssemblyCompilerException; } return(results.PathToAssembly); }
public void Start() { this.CheckDisposed(); this.DisposeClient(); string guid = Guid.NewGuid().ToString(); bool isCreated; using (EventWaitHandle serverStartedHandle = new EventWaitHandle(false, EventResetMode.ManualReset, string.Format(AddInActivatorHost.AddInDomainEventNameStringFormat, guid), out isCreated)) { if (!isCreated) { throw new Exception(AddInConstants.EventHandleAlreadyExistedException); } string addInDomainAssemblyPath = typeof(AddInActivatorProcess).Assembly.Location; AddInDomainSetup.WriteSetupFile(this._addInDomainSetup, this._addInDomainSetupFile); //// args[0] = AddInDomain assembly path //// args[1] = GUID //// args[2] = PID //// args[3] = AddInDomainSetup file //// args[4] = Redirect output or not this._process.StartInfo.Arguments = string.Format("\"{0}\" {1} {2} \"{3}\" {4}", addInDomainAssemblyPath, guid, Process.GetCurrentProcess().Id.ToString(), this._addInDomainSetupFile, this._redirectOutput.ToString()); this.IsRunning = this._process.Start(); if (!this.IsRunning) { Debug.WriteLine(string.Format(AddInConstants.ProcessStartExceptionStringFormat, this._process.StartInfo.FileName)); throw new Exception(string.Format(AddInConstants.ProcessStartExceptionStringFormat, this._process.StartInfo.FileName)); } if (!serverStartedHandle.WaitOne(this._addInDomainSetup.ProcessStartTimeout)) { Debug.WriteLine(AddInConstants.ProcessStartTimeoutException); throw new Exception(AddInConstants.ProcessStartTimeoutException); } this._process.BeginOutputReadLine(); this._process.BeginErrorReadLine(); this._process.PriorityClass = this._addInDomainSetup.ProcessPriority; this._addInActivatorClient = new AddInActivatorClient(guid, this._addInDomainSetup); this.RaiseEvent(this.Attached); } }
public AddInActivatorClient(string guid, AddInDomainSetup addInDomainSetup) { BinaryServerFormatterSinkProvider serverProvider = new BinaryServerFormatterSinkProvider(); serverProvider.TypeFilterLevel = addInDomainSetup.TypeFilterLevel; BinaryClientFormatterSinkProvider clientProvider = new BinaryClientFormatterSinkProvider(); Hashtable properties = new Hashtable(); properties[AddInConstants.KeyIpcPortName] = string.Format(AddInActivatorHost.AddInClientChannelNameStringFormat, guid); properties[AddInConstants.KeyIpcChannelName] = string.Format(AddInActivatorHost.AddInClientChannelNameStringFormat, guid); this._ipcChannel = new IpcChannel(properties, clientProvider, serverProvider); ChannelServices.RegisterChannel(this._ipcChannel, false); this._addInActivator = (AddInActivator)Activator.GetObject(typeof(AddInActivator), string.Format(AddInConstants.IpcUrlStringFormat, string.Format(AddInActivatorHost.AddInServerChannelNameStringFormat, guid), AddInActivatorHost.AddInActivatorName)); }
/// <summary> /// Initializes a new instance of the <see cref="AddInActivatorHost" /> class. /// </summary> /// <param name="guid">Guid string.</param> /// <param name="processId">Process Id.</param> /// <param name="addInDomainSetup">Instance of AddInDomainSetup.</param> public AddInActivatorHost(string guid, int processId, AddInDomainSetup addInDomainSetup) { try { Directory.SetCurrentDirectory(addInDomainSetup.DllDirectory); } catch (Exception e) { InternalLogger.Log(e); throw; } this._process = Process.GetProcessById(processId); BinaryServerFormatterSinkProvider serverProvider = new BinaryServerFormatterSinkProvider(); serverProvider.TypeFilterLevel = addInDomainSetup.TypeFilterLevel; BinaryClientFormatterSinkProvider clientProvider = new BinaryClientFormatterSinkProvider(); Hashtable properties = new Hashtable(); properties[AddInConstants.KeyIpcPortName] = string.Format(AddInServerChannelNameStringFormat, guid); properties[AddInConstants.KeyIpcChannelName] = string.Format(AddInServerChannelNameStringFormat, guid); this._ipcChannel = new IpcChannel(properties, clientProvider, serverProvider); ChannelServices.RegisterChannel(this._ipcChannel, false); RemotingConfiguration.RegisterWellKnownServiceType(typeof(AddInActivator), AddInActivatorName, WellKnownObjectMode.Singleton); bool isCreated; using (EventWaitHandle serverStartedHandle = new EventWaitHandle(false, EventResetMode.ManualReset, string.Format(AddInDomainEventNameStringFormat, guid), out isCreated)) { if (isCreated) { throw new Exception(AddInConstants.EventHandleNotExist); } serverStartedHandle.Set(); } }
/// <summary> /// Runs AddInActivatorHost until the parent process exits. /// </summary> /// <param name="args">Command line arguments.</param> public static void Run(string[] args) { //// args[0] = AddInDomain assembly path //// args[1] = GUID //// args[2] = PID //// args[3] = AddInDomainSetup file //// args[4] = Redirect output or not if (args.Length < 4) { return; } string friendlyName = Path.GetFileNameWithoutExtension(Assembly.GetEntryAssembly().Location); string guid = args[1]; int processId = int.Parse(args[2]); AddInDomainSetup addInDomainSetup = AddInDomainSetup.ReadSetupFile(args[3]); AppDomain appDomain = AppDomain.CreateDomain(friendlyName, addInDomainSetup.Evidence, addInDomainSetup.AppDomainSetup); Type type = Assembly.GetEntryAssembly().GetType("DevLib.AddIn.AssemblyResolver"); if (type == null) { throw new TypeLoadException(AddInConstants.AssemblyResolverException); } // add AddInDomain assembly to resolver if (addInDomainSetup.ExternalAssemblies == null) { addInDomainSetup.ExternalAssemblies = new Dictionary <AssemblyName, string>(); } addInDomainSetup.ExternalAssemblies[typeof(AddInActivatorHost).Assembly.GetName()] = typeof(AddInActivatorHost).Assembly.Location; object resolver = appDomain.CreateInstanceFromAndUnwrap( type.Assembly.Location, type.FullName, false, BindingFlags.CreateInstance | BindingFlags.Public | BindingFlags.Instance, null, new[] { addInDomainSetup.ExternalAssemblies }, null, null, null); type.InvokeMember("Mount", BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.Public, null, resolver, null); AddInActivatorHost host = (AddInActivatorHost)appDomain.CreateInstanceFromAndUnwrap( typeof(AddInActivatorHost).Assembly.Location, typeof(AddInActivatorHost).FullName, false, BindingFlags.CreateInstance | BindingFlags.Public | BindingFlags.Instance, null, new object[] { guid, processId, addInDomainSetup }, null, null, null); host.WaitForExit(); type.InvokeMember("Unmount", BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.Public, null, resolver, null); // if parent process (host) finishes, the current process must end Environment.Exit(0); }
/// <summary> /// Constructor of AddInDomainEventArgs. /// </summary> /// <param name="friendlyName"></param> /// <param name="addInTypeName"></param> /// <param name="addInObject"></param> /// <param name="addInDomainSetupInfo"></param> /// <param name="processInfo"></param> public AddInDomainEventArgs(string friendlyName, string addInTypeName, object addInObject, AddInDomainSetup addInDomainSetupInfo, AddInActivatorProcessInfo processInfo) { this.FriendlyName = friendlyName; this.AddInTypeName = addInTypeName; this.AddInObject = addInObject; this.AddInDomainSetupInfo = addInDomainSetupInfo; this.ProcessInfo = processInfo; }
/// <summary> /// Initializes a new instance of the <see cref="AddInDomain" /> class. /// </summary> /// <param name="friendlyName">The friendly name of the AddInDomain.</param> /// <param name="showRedirectConsoleOutput">Whether the output of AddInActivatorProcess is shown in current console.</param> /// <param name="addInDomainSetup">Additional settings for creating AddInDomain.</param> public AddInDomain(string friendlyName = null, bool showRedirectConsoleOutput = true, AddInDomainSetup addInDomainSetup = null) { this.FriendlyName = string.IsNullOrEmpty(friendlyName) ? AddInConstants.DefaultFriendlyName : friendlyName; this.AddInDomainSetupInfo = addInDomainSetup ?? new AddInDomainSetup(); this.RedirectOutput = showRedirectConsoleOutput; this.CreateAddInActivatorProcess(); }