Нет, невозможно создать Rc<T>
из Rc<Option<T>>
, который оставляет последний все еще существующим. Однако можно создать Rc<&T>
из Rc<Option<T>>
, оставив при этом последнюю переменную существующей.
Если вы пытаетесь создать новый Rc<T>
, которому принадлежит T
внутри Rc<Option<T>>
, вам придется использовать оригинал Rc<Option<T>>
. Вы также не можете иметь несколько экземпляров Rc<Option<T>>
, потому что тогда вы перемещаете общее значение, пока еще существуют указатели, что очень небезопасно.
Но есть способ сделать это безопасно! Используя Rc::try_unwrap
, вы можете попытаться переместить значение наружу, но это вернет ошибку, если существует несколько экземпляров оригинала Rc
. Имейте в виду, что вы также должны разобраться со сценарием, в котором Option<T>
заканчивается None
.
Вот пример этого:
let rc_option: Rc<Option<T>> = Rc::new(Some(value));
match Rc::try_unwrap(rc_option) {
Ok(option) => {
match option {
Some(t) => {
let ok_value: Rc<T> = Rc::new(t);
// Do something with ok_value
}
None => {
// Do something else here
}
}
}
Err(rc_option) => {
// There are multiple owners, do something else here
}
}
Если вы хотите сохранить оригинал, вы можете сделать это:
match &*rc_option {
Some(ref t) => {
let ok_ref: Rc<&T> = Rc::new(t);
}
None => { /* Do something else, there's no internal value */ }
}
РЕДАКТИРОВАТЬ: Как хронический упомянуто, обратите внимание, что ok_ref
не может пережить rc_option
(потому что это ссылка на rc_option
), что, возможно, не то, что вы хотите, чтобы.
WMI - это более простой способ сделать это в C #. Класс Win32_Process имеет свойство ParentProcessId. Вот пример:
using System;
using System.Management; // <=== Add Reference required!!
using System.Diagnostics;
class Program {
public static void Main() {
var myId = Process.GetCurrentProcess().Id;
var query = string.Format("SELECT ParentProcessId FROM Win32_Process WHERE ProcessId = {0}", myId);
var search = new ManagementObjectSearcher("root\\CIMV2", query);
var results = search.Get().GetEnumerator();
results.MoveNext();
var queryObj = results.Current;
var parentId = (uint)queryObj["ParentProcessId"];
var parent = Process.GetProcessById((int)parentId);
Console.WriteLine("I was started by {0}", parent.ProcessName);
Console.ReadLine();
}
}
Вывод при запуске из Visual Studio:
Я был запущен devenv
Проверьте элемент th32ParentProcessID перечисления CreateToolhelp32Snapshot.
Пример того, как это сделать , см. В моем посте здесь .
Поскольку вы используете C #, вам нужно использовать DllImports. В связанном посте есть страницы MSDN для каждой функции, которая вам нужна. Внизу каждой страницы MSDN есть код для DllImport для C #.
Существует также более простой способ с использованием только управляемого кода , но он не работает, если у вас запущено несколько имен процессов, запущенных различными приложениями.
Если у вас есть контроль над родительским приложением, вы можете изменить его так, чтобы он передавал свой PID потомку, когда оно запускает процесс.