Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

StartInfo of Process throws with Process was not started by this object, so requested information cannot be determined. #33525

Closed
soyang2828 opened this issue Mar 12, 2020 · 9 comments
Labels
area-System.Diagnostics.Process breaking-change Issue or PR that represents a breaking API or functional change over a prerelease. question Answer questions and provide assistance, not an issue with source code or documentation.

Comments

@soyang2828
Copy link

If this is not supported, what is the recommended way to pass around the environment variables of a process?

Here is our callstack:
System.InvalidOperationException
HResult=0x80131509
Message=Process was not started by this object, so requested information cannot be determined.
Source=System.Diagnostics.Process
StackTrace:
at System.Diagnostics.Process.get_StartInfo()
at Microsoft.Office.Audit.Schema.RecordSerializer..cctor() in H:\subrepo2\src\sources\dev\common\src\ComplianceAuditSchema\RecordSerializer.cs:line 112

[External Code]	
Microsoft.Office.Audit.dll!Microsoft.Office.Audit.Schema.RecordSerializer.RecordSerializer() Line 112	C#
[External Code]	
Microsoft.Office.Audit.dll!Microsoft.Office.Audit.Schema.RecordSerializer.RecordSerializer() Line 126	C#

Microsoft.Exchange.Data.Storage.dll!Microsoft.Exchange.Data.Storage.Auditing.UnifiedAuditLogger.ConvertAuditRecord(Microsoft.Office.Audit.Schema.AuditRecord record, out Microsoft.Exchange.Diagnostics.LogRowFormatter logRowFormatter) Line 157 C#
Microsoft.Exchange.Data.Storage.dll!Microsoft.Exchange.Data.Storage.Auditing.UnifiedAuditLogger.WriteAuditRecord(Microsoft.Office.Audit.Schema.AuditRecord record) Line 100 C#
Microsoft.Exchange.Data.Storage.dll!Microsoft.Exchange.Data.Storage.COWAudit.InternalAuditOperation(Microsoft.Exchange.Data.Storage.COWTriggerAction operation, Microsoft.Exchange.Data.Storage.MailboxSession auditingMailboxSession, Microsoft.Exchange.Data.Storage.MailboxSession mailboxSession, Microsoft.Exchange.Data.Directory.MailboxAuditOperations auditOperation, Microsoft.Exchange.Data.Storage.COWSettings settings, Microsoft.Exchange.Data.StoreObjects.OperationResult result, Microsoft.Exchange.Data.StoreObjects.LogonType effectiveLogonType, bool

@Dotnet-GitSync-Bot Dotnet-GitSync-Bot added area-System.Diagnostics.Process untriaged New issue has not been triaged by the area owner labels Mar 12, 2020
@vcsjones
Copy link
Member

If you are trying to get the environment variables for your current process, you can use Environment.GetEnvironmentVariables.

If you are trying to do this for a different process other than the current one, I don't believe there is a way to do that. See #14329 for more background.

@soyang2828
Copy link
Author

I think I shouldn't say environment varaibles, but rather it's process related variables. How do I associated those to a process?

@vcsjones
Copy link
Member

What information are you trying to get from the ProcessStartInfo? Even for the .NET Framework, the documentation states

You should only access the StartInfo property on a Process object returned by the Start method. For example, you should not access the StartInfo property on a Process object returned by GetProcesses. Otherwise, on .NET Core the StartInfo property will throw an InvalidOperationException and on .NET Framework it will return a dummy ProcessStartInfo object.

So if you are trying to do this with a Process object for a process that your own code did not start, this doesn't work correctly in .NET Framework and .NET Core throws an exception to prevent that incorrect behavior.

If you are doing this for a process your own code did start using Process.Start, then you should just use the same ProcessStartInfo object you used to start the process.

@stephentoub stephentoub added the question Answer questions and provide assistance, not an issue with source code or documentation. label Mar 13, 2020
@StephenBonikowsky StephenBonikowsky added this to Proposed/Not Committed in .NET Core impacting internal partners via automation Mar 13, 2020
@eiriktsarpalis
Copy link
Member

Hi @soyang2828, would you mind sharing reproduction steps, sdk version and operating system? I couldn't reproduce the exception in a couple of simple examples that I tried.

My understanding of ProcessStartInfo is that it is meant to be passed as an argument when creating a process, and not querying it after it has been started. This is documented here. So in your use case you'd need to update the EnvironmentVariables dictionary before calling the myProcess.Start() method.

@vcsjones
Copy link
Member

vcsjones commented Mar 17, 2020

@eiriktsarpalis you can reproduce it like so:

using System.Diagnostics;

public class Program {
    static void Main() {
        foreach(var p in Process.GetProcesses()) {
            _ = p.StartInfo;
        }
    }
}

In .NET Framework, this does not throw an exception (although it may not work as some people expect it to). In .NET Core 3.1, this throws an exception.

@eiriktsarpalis eiriktsarpalis removed the untriaged New issue has not been triaged by the area owner label Mar 17, 2020
@eiriktsarpalis
Copy link
Member

Based on what I'm reading, accessing environment variables of other processes is not supported by the windows api. TBH I'd be surprised if the opposite were the case. In that sense I'd probably treat the current behaviour as by-design, though happy to be corrected on this.

@soyang2828
Copy link
Author

soyang2828 commented Mar 25, 2020

Thanks @vcsjones for the repro. Here is a usage code snippet. What do you suggest we do here?

                // Copy current process properties to worker process
                using (Process currentProcess = Process.GetCurrentProcess())
                {

...                    workerProcessInfo.FileName = Path.Combine(Path.GetDirectoryName(currentProcess.MainModule.FileName), WorkerProcess.ExecutableName);
                    workerProcessInfo.CreateNoWindow = currentProcess.StartInfo.CreateNoWindow;
                    workerProcessInfo.ErrorDialog = currentProcess.StartInfo.ErrorDialog;
                    workerProcessInfo.ErrorDialogParentHandle = currentProcess.StartInfo.ErrorDialogParentHandle;

@StephenBonikowsky StephenBonikowsky moved this from Proposed/Not Committed to 5.0 Release - Like to Have in .NET Core impacting internal partners May 6, 2020
@danmoseley danmoseley added the breaking-change Issue or PR that represents a breaking API or functional change over a prerelease. label May 8, 2020
@danmoseley
Copy link
Member

@soyang2828 that code is not doing anything useful. It is simply reading the defaults off of a new ProcessStartInfo.

If you create a ProcessStartInfo object yourself, you can set its properties as you like, and read them off again.
If you get a ProcessStartInfo from someProcess.StartInfo it is basically useless. It returns default values from all its properties, with the exception of EnvironmentVariables - and that returns the environment of the process your're currently in, rather than the one you think. If you want that, you can just call Environment.GetEnvironmentVariables() directly. I am not sure why .NET Framework behaved like this. In .NET Core we apparently stopped giving you this useless object.

You can see the details here: https://referencesource.microsoft.com/#System/services/monitoring/system/diagnosticts/ProcessStartInfo.cs,173

To answer your specific question, you can replace that code with

           // Copy current process properties to worker process
                using (Process currentProcess = Process.GetCurrentProcess())
                {

...                    workerProcessInfo.FileName = Path.Combine(Path.GetDirectoryName(currentProcess.MainModule.FileName), WorkerProcess.ExecutableName);
                    workerProcessInfo.CreateNoWindow = false;
                    workerProcessInfo.ErrorDialog = false;
                    workerProcessInfo.ErrorDialogParentHandle = null;

However note that either way, the code is not doing what the comment claims it is doing.

I'm closing this as by-design, but marking 'breaking change' so it can get into docs.

.NET Core impacting internal partners automation moved this from 5.0 Release - Like to Have to Done May 8, 2020
@danmoseley
Copy link
Member

Actually it's already documented in Process.StartInfo as a breaking change, and I opened dotnet/docs#18310 as well.

@dotnet dotnet locked as resolved and limited conversation to collaborators Dec 10, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-System.Diagnostics.Process breaking-change Issue or PR that represents a breaking API or functional change over a prerelease. question Answer questions and provide assistance, not an issue with source code or documentation.
Projects
No open projects
Development

No branches or pull requests

6 participants