Контекст:
В настоящее время я пишу приложение, которое позволяет пользователю открывать решение Visual Studio (файл .sln). Затем они смогут редактировать определенные аспекты открытого проекта через пользовательский интерфейс моего приложения, вместо того, чтобы редактировать код самостоятельно. Во избежание путаницы я говорю о Visual Studio, хотя технически файл будет использоваться и открываться TwinCatXAEShell, что по сути одно и то же.
Проблема:
Чтобы открыть файл решения, я использую System.Diagnostics.Process.Start(). Однако для отправки команд работающему проекту мне нужна ссылка на интерфейс EnvDTE.DTE этого проекта.
Вот код, который я использую для открытия файла:// get TwinCAT application
string applicationPath = getTwinCatInstallPath();
if (!File.Exists(applicationPath)) return;
// start TwinCAT with provided file
System.Diagnostics.Process fileopener = new System.Diagnostics.Process();
fileopener.StartInfo = new ProcessStartInfo()
{
FileName = applicationPath,
Arguments = $"\"{solutionPath}\"",
WindowStyle = ProcessWindowStyle.Minimized
};
fileopener.Start();
Некоторые «решения»:
Вариант 1:
То, что я делаю до сих пор, это для поиска в таблице запущенных объектов Windows и поиска идентификатора процесса в именах запущенных объектов. Но я продолжаю думать, что должна быть возможность напрямую получить доступ к экземпляру System.Diagnostics.Process...
Вот код для поиска в таблице запущенных объектов Windows:
(очевидно, не полностью мое ^^)
static DTE ProcessToDte(System.Diagnostics.Process process)
{
// get list of windows processes
IRunningObjectTable runningObjectTable;
GetRunningObjectTable(0, out runningObjectTable);
// get enumerator for the list
runningObjectTable.EnumRunning(out IEnumMoniker monikerEnumerator);
monikerEnumerator.Reset();
// iterate over list and crate a subset with fitting processes
IMoniker[] monikers = new IMoniker[1];
while (monikerEnumerator.Next(1, monikers, IntPtr.Zero) == 0)
{
CreateBindCtx(0, out IBindCtx ctx);
monikers[0].GetDisplayName(ctx, null, out string runningObjectName);
if (!runningObjectName.Contains("TcXaeShell")) continue;
if (runningObjectName.Contains(process.Id.ToString()))
{
runningObjectTable.GetObject(monikers[0], out object runningObjectData);
DTE ide;
try { ide = runningObjectData as DTE; } catch { continue; }
return ide;
}
}
return null;
}
[DllImport("ole32.dll")]
static extern int GetRunningObjectTable(int reserved, out IRunningObjectTable rot); // needed for ProcessToDte()
[DllImport("ole32.dll")]
static extern int CreateBindCtx(uint reserved, out IBindCtx ppbc); // needed for ProcessToDte()
Вариант 2:
Я обнаружил, что другой способ обойти эту проблему — никогда даже не использовать System.Diagnostics.Process и вместо этого откройте файл решения, как показано ниже, но процесс.Start() кажется гораздо более удобным и понятным для будущих проверок кода.
Type t = Type.GetTypeFromProgID("TcXaeShell.DTE.15.0");
if (t == null) return;
DTE dte;
dte = (DTE)Activator.CreateInstance(t);
dte.SuppressUI = false;
dte.MainWindow.Visible = true;
dte.MainWindow.WindowState = vsWindowState.vsWindowStateMinimize;
dte.UserControl = true;
Подробнее здесь: https://stackoverflow.com/questions/785 ... tance-of-s
C# получает интерфейс EnvDTE.DTE решения Visual Studio через экземпляр System.Diagnostics.Process ⇐ C#
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение