This API review was also recorded and is available on Google+.
In this API review we discussed several proposals on how to update Process
so that we can remove the API dependency to SecureString
while preserving
the ability to start processes with a given user name and password.
Status: Approved | API Diff | Video
In order to preserve the ability to start new process, we need to expose new
APIs that instead of taking SecureString
take string
. However, we just
shipped .NET Framework 4.6, so we can't make this API set immediately compatible
with .NET Framework.
So in order to have a version of Process
that works on both, .NET Core as well
as .NET Framework, we need to expose a contract that doesn't have these new
APIs. This contract (versioned as 4.0.0) will be compatible with both platforms.
In addition, we'll create a new version of System.Diagnostics.Process.dll
that will have the new APIs. This contract will be versioned as 4.1.0.0.
-
Only expose
Process.Start
static APIs that take in the credentials options.public static Process Start(string userName, string password, string domain); public static Process Start(string userName, string password, string domain, bool loadUserProfile); // or just this one.
- Pros. Minimum API additions, removes the need for a property like
PlainTextPassword
and thePassword
string is not rooted. - Cons. Some of the
Process
scenarios can't be supported this way. For example no way to redirect streams when a process is created with credentials.
- Pros. Minimum API additions, removes the need for a property like
-
Build on top of (1) and expose static APIs that take in
ProcessStartInfo
and credentialspublic static Process Start(ProcessStartInfo startInfo, string userName, string password, string domain); public static Process Start(ProcessStartInfo startInfo, string userName, string password, string domain, bool loadUserProfile); // or just this one.
- Pros. Same as above
- Cons. There will be still some scenarios that won't light up for
example no way to support
OnExited
andasync
stream reading when a process is created with credentials (they are only supported viaProcess.Start()
instance method).
-
Build on top of (2) and expose variants of
Process.Start()
instance methods that take in credentials.public static Process Start(ProcessStartInfo startInfo, string userName, string password, string domain); public static Process Start(ProcessStartInfo startInfo, string userName, string password, string domain, bool loadUserProfile); // or just this one. public bool Start(string userName, string password, string domain); public bool Start(string userName, string password, string domain, bool loadUserProfile); // or just this one.
- Pros. Same as above
- Cons. We add new APIs to an already long list of
Process.Start()
options. Desktop design becomes much more complex where credentials can be added viaProcessStartInfo
and new Start APIs.
-
Proposed contract
namespace System.Diagnostics { public class Process : IDisposable { public static Process Start(string fileName, string userName, string password, string domain); public static Process Start(string fileName, string arguments, string userName, string password, string domain); } public sealed class ProcessStartInfo { public string Domain { get; set; } public bool LoadUserProfile { get; set; } public string PlainTextPassword { get; set; } public string UserName { get; set; } } }
- Pros. Story remains more or less the same and the Desktop gets to stay cleaner.
- Cons. Adds an alternate property for
Password
and keeps it rooted.
We all agreed that the rooting argument for the password is artificial. It's a
knee-jerk reaction that doesn't quite make sense given how the system is
implemented. In end, the string will put the password on the heap anyways. The
rooting doesn't really change that. Granted, it may prolong the lifetime of
the string but in many cases the lifetime of the ProcessStartInfo
will likely
be identical.
We feel that creating a process with credentials is an advanced scenario. Hence,
we feel we don't need to expose a static convenience helper that can create
processes with different credentials. This avoids the problem of having two
overloads on desktop that have both, string
versions as well as SecureString
versions.
The only downside is that this may make people's life harder when they port .NET Framework code to .NET Core. However, none of the apps in our compat lab are using the existing static methods that take credentials.
This means we only need to add a single API to the .NET Framework:
ProcessStartInfo.PasswordInClearText
.
This begs the question what behavior we should have if consumers on the .NET
Framework set both, the existing ProcessStartInfo.Password
as well as the
new ProcessStartInfo.PasswordInClearText
. We concluded that we throw from
the instance Process.Start
method if we detect both properties are non-null.
In other words, we'll require callers to either use Password
or
PasswordInClearText
.
- PallaviT will make the changes to
Process