Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / AddIn / AddIn / System / Addin / Hosting / AddInProcess.cs / 1305376 / AddInProcess.cs
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
/*============================================================
**
** Class: AddInProcess
**
** Purpose:
**
===========================================================*/
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Runtime.Remoting;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Threading;
using System.AddIn.Contract;
using System.AddIn.Pipeline;
using System.AddIn;
using Microsoft.Win32;
using System.Diagnostics.Contracts;
namespace System.AddIn.Hosting
{
[Serializable]
public enum Platform
{
Host = 0,
AnyCpu = 1,
X86 = 2,
X64 = 3
}
public sealed class AddInProcess
{
private bool _keepAlive = false;
private volatile Process _process = null;
private Guid _guid;
private Platform _platform;
private String _pathToAddInProcess;
private readonly Object _processLock = new Object();
// Win32Error NativeErrorCode values
const int ERROR_FILE_NOT_FOUND = 2;
const int ERROR_ACCESS_DENIED = 5;
// Time to wait for the external process to start up and report for duty
// Default to 10 seconds
private TimeSpan _startupTimeout = new TimeSpan(0, 0, 10);
public TimeSpan StartupTimeout
{
get
{
return _startupTimeout;
}
set
{
if (value.TotalSeconds < 0) throw new ArgumentOutOfRangeException("value");
lock(_processLock)
{
if(_process == null)
{
_startupTimeout = value;
}
else
{
throw new InvalidOperationException(Res.ProcessAlreadyRunning);
}
}
}
}
public Platform Platform
{
get
{
return _platform;
}
}
// This is used to represent in-process situations
private static AddInProcess s_currentProcess = new AddInProcess(true);
//
//
//
[System.Security.SecurityCritical]
[PermissionSet(SecurityAction.Demand, Name="FullTrust")]
public AddInProcess() : this(Platform.Host)
{
}
// Overloaded constructor to customize the addin process platform architecture and CLR version.
[System.Security.SecurityCritical]
[PermissionSet(SecurityAction.Demand, Name="FullTrust")]
public AddInProcess(Platform platform)
{
_platform = platform;
// Process the arguments early so we can throw an exception if they were invalid.
String folder = RuntimeEnvironment.GetRuntimeDirectory();
String exeName = GetProcessName(platform);
_pathToAddInProcess = Path.Combine(folder, exeName);
if(!File.Exists(_pathToAddInProcess))
{
throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Res.MissingAddInProcessExecutable, _pathToAddInProcess));
}
// Eagerly call this. Any MBRO objects created before this initialization
// will not be usable.
RemotingHelper.InitializeClientChannel();
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "internalOnly", Justification = "Reviewed")]
internal AddInProcess(bool internalOnly)
{
// don't initialize remoting in this version. Therefore we don't need to be Full Trust.
}
// We should keep processId and Guid in [....]. That is, either
// both are null or neither are null.
public int ProcessId
{
// do the same LinkDemand that Process.GetCurrentProcess().Id demands
[PermissionSet(SecurityAction.LinkDemand, Name="FullTrust")]
get
{
lock(_processLock)
{
if (this == s_currentProcess)
return Process.GetCurrentProcess().Id;
if (_process == null)
return -1;
return _process.Id;
}
}
}
internal static AddInProcess Current
{
get { return s_currentProcess; }
}
internal Guid Guid
{
get
{
if (IsCurrentProcess)
return Guid.Empty;
Start();
return _guid;
}
}
// Flag
public bool IsCurrentProcess
{
get { return this == s_currentProcess; }
}
public bool KeepAlive
{
get { return _keepAlive; }
set { _keepAlive = value; }
}
public event EventHandler ShuttingDown;
// Message from the OOP AddInServer indicating there are no addins currently running.
internal void SendShuttingDown(CancelEventArgs args)
{
if (KeepAlive)
{
args.Cancel = true;
return;
}
ShutDownUnlessCancelled(args);
}
// This helper method may be called indirectly from user code via Shutdown()
// or by a finalizer thread cleaning up the remote process.
private void ShutDownUnlessCancelled(CancelEventArgs args)
{
if (ShuttingDown != null)
ShuttingDown(this, args);
if (args.Cancel)
return;
try
{
lock (_processLock) {
// Give addins a chance to clean up by running finalizers
// We'll get a remoting exception trying to read the response from this though.
AddInServer server = GetAddInServer();
_process = null;
_guid = Guid.Empty;
// Warning - if this was called from the finalizer thread of AddInProcess,
// nothing after this next call will execute, even if it's in a finally block,
// due to the calling process being torn down.
server.ExitProcess();
}
}
catch (RemotingException) {}
catch (System.Runtime.Serialization.SerializationException) {}
}
internal AddInServer GetAddInServer()
{
return RemotingHelper.GetAddInServer(Guid.ToString());
}
//
//
//
//
[System.Security.SecurityCritical]
public bool Start()
{
if (this == s_currentProcess)
throw new InvalidOperationException(Res.OperationNotValidOnCurrentProcess);
if (_process == null)
{
lock (_processLock) {
if (_process == null)
{
_process = CreateAddInProcess();
// register for SendShuttingDown callbacks
AddInServer addInServer = GetAddInServer();
addInServer.Initialize(new EventWorker(this));
}
}
return true;
}
return false;
}
// returns true if it was successfully shut down by this method, false otherwise
public bool Shutdown()
{
if (this == s_currentProcess)
throw new InvalidOperationException(Res.OperationNotValidOnCurrentProcess);
if (_process == null)
return false;
CancelEventArgs args = new CancelEventArgs();
ShutDownUnlessCancelled(args);
if (args.Cancel)
{
return false;
}
return true;
}
[System.Security.SecurityCritical]
private static String GetProcessName(Platform platform)
{
String exeName;
switch(platform)
{
case Platform.Host:
exeName = CurrentlyRunning32Bit() ? "AddInProcess32.exe" : "AddInProcess.exe";
break;
case Platform.X86:
exeName = "AddInProcess32.exe";
break;
case Platform.X64:
if(!CurrentlyRunning32Bit() || CurrentlyRunningWow64()) // verify we are on a 64bit os
{
exeName = "AddInProcess.exe";
}
else
{
throw new InvalidOperationException(Res.Invalid64bitPlatformOn32bitOS);
}
break;
case Platform.AnyCpu:
exeName = "AddInProcess.exe";
break;
default:
throw new ArgumentOutOfRangeException("platform");
}
return exeName;
}
private static bool CurrentlyRunning32Bit()
{
return System.IntPtr.Size == 4;
}
// Finds out whether we are in a WOW64 process (i.e. a process is 32bit and the OS is 64bit).
// Returns false if we are in a 64bit process or on a 32bit OS.
[System.Security.SecurityCritical]
private static bool CurrentlyRunningWow64()
{
bool isWow = false;
try
{
if(!NativeMethods.IsWow64Process(System.Diagnostics.Process.GetCurrentProcess().Handle, ref isWow))
{
throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error()); // call failed
}
}
catch(EntryPointNotFoundException)
{
return false; // Call doesn't exist in the current OS, so it means we're not in a wow process.
}
return isWow; // Return whatever IsWow64Process() returned through the out argument.
}
//
//
//
//
//
//
//
//
//
//
//
//
//
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Justification = "Reviewed")]
[System.Security.SecurityCritical]
private Process CreateAddInProcess()
{
Process addInProcess = new Process();
Guid guid = Guid.NewGuid();
String args = String.Format(CultureInfo.InvariantCulture, "/guid:{0} /pid:{1}", guid, Process.GetCurrentProcess().Id);
addInProcess.StartInfo.CreateNoWindow = true;
addInProcess.StartInfo.UseShellExecute = false;
addInProcess.StartInfo.Arguments = args;
addInProcess.StartInfo.FileName = _pathToAddInProcess;
#if _DEBUG
String debuggerPath = Environment.GetEnvironmentVariable("COMPLUS_AddInProcessDebugger");
String debuggerArgs = Environment.GetEnvironmentVariable("COMPLUS_AddInProcessDebuggerArgs");
if(!String.IsNullOrEmpty(debuggerPath))
{
addInProcess.StartInfo.Arguments = "";
if(!String.IsNullOrEmpty(debuggerArgs))
{
addInProcess.StartInfo.Arguments = debuggerArgs + " ";
}
addInProcess.StartInfo.Arguments += _pathToAddInProcess + " " + args;
addInProcess.StartInfo.FileName = debuggerPath;
}
#endif
// wait until it's ready
EventWaitHandle readyEvent = new EventWaitHandle(false, EventResetMode.ManualReset, "AddInProcess:" + guid);
addInProcess.Start();
bool success = readyEvent.WaitOne(_startupTimeout, false);
readyEvent.Close();
if (!success) {
// Here's an effort to avoid leaving a half-baked process around if possible.
try {
addInProcess.Kill();
}
catch (Exception) {}
throw new InvalidOperationException(Res.CouldNotCreateAddInProcess);
}
_guid = guid;
return addInProcess;
}
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- MyContact.cs
- PerfCounterSection.cs
- MediaPlayer.cs
- SafeNativeMethods.cs
- DataStreams.cs
- WeakReadOnlyCollection.cs
- EasingKeyFrames.cs
- _LoggingObject.cs
- KerberosSecurityTokenAuthenticator.cs
- FormsAuthenticationTicket.cs
- PageAsyncTaskManager.cs
- Accessible.cs
- XmlSchemaImport.cs
- MemberRelationshipService.cs
- TextEffectResolver.cs
- DictionaryChange.cs
- DynamicILGenerator.cs
- UriSection.cs
- MultiByteCodec.cs
- AsyncCompletedEventArgs.cs
- CompiledWorkflowDefinitionContext.cs
- MessageRpc.cs
- FastEncoderStatics.cs
- TemplateKeyConverter.cs
- BCryptNative.cs
- CodeTypeDelegate.cs
- InheritanceContextHelper.cs
- SchemaTypeEmitter.cs
- CodeIdentifier.cs
- LoadRetryStrategyFactory.cs
- AssemblyInfo.cs
- _LocalDataStore.cs
- ConsoleKeyInfo.cs
- HttpHandlerAction.cs
- CachingHintValidation.cs
- TextDecorationCollection.cs
- PropertyGridCommands.cs
- SyndicationSerializer.cs
- activationcontext.cs
- DataColumnMapping.cs
- UInt32Storage.cs
- SqlBooleanMismatchVisitor.cs
- TypeListConverter.cs
- DateRangeEvent.cs
- UnknownWrapper.cs
- BamlLocalizerErrorNotifyEventArgs.cs
- CheckedPointers.cs
- Span.cs
- uribuilder.cs
- TextBoxRenderer.cs
- AxisAngleRotation3D.cs
- DataViewManagerListItemTypeDescriptor.cs
- NextPreviousPagerField.cs
- GridViewCancelEditEventArgs.cs
- TextRunCacheImp.cs
- controlskin.cs
- AndCondition.cs
- LinkConverter.cs
- WebMessageBodyStyleHelper.cs
- NumberFormatter.cs
- FlowDocument.cs
- ControlType.cs
- Binding.cs
- HttpHostedTransportConfiguration.cs
- AlphaSortedEnumConverter.cs
- PenThreadWorker.cs
- TdsRecordBufferSetter.cs
- DrawingContextWalker.cs
- AssertFilter.cs
- ProtectedConfigurationProviderCollection.cs
- ToolStripGrip.cs
- SmiGettersStream.cs
- ReversePositionQuery.cs
- UnknownWrapper.cs
- RSAPKCS1KeyExchangeFormatter.cs
- SignatureHelper.cs
- ComponentConverter.cs
- VirtualDirectoryMapping.cs
- CustomCategoryAttribute.cs
- FtpWebResponse.cs
- FrameworkReadOnlyPropertyMetadata.cs
- EventsTab.cs
- FileNotFoundException.cs
- ConnectionConsumerAttribute.cs
- RSACryptoServiceProvider.cs
- ExpressionBindingCollection.cs
- WebBrowserHelper.cs
- CollectionTraceRecord.cs
- FrameAutomationPeer.cs
- StorageComplexPropertyMapping.cs
- IdSpace.cs
- shaper.cs
- FixUp.cs
- QueryContext.cs
- SessionEndingEventArgs.cs
- InProcStateClientManager.cs
- ReadWriteSpinLock.cs
- MD5.cs
- BaseParaClient.cs
- UnsafeNativeMethods.cs