Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/263.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何从外部64位进程自动化Visual Studio?_C#_Visual Studio_Automation_64 Bit - Fatal编程技术网

C# 如何从外部64位进程自动化Visual Studio?

C# 如何从外部64位进程自动化Visual Studio?,c#,visual-studio,automation,64-bit,C#,Visual Studio,Automation,64 Bit,我想从一个外部C#程序自动化Visual Studio。如前所述,我获取给定processId的DTE对象。然后我从DTE对象中获取一个ServiceProvider和IVsActivityLog,如前所述 作为x86,所有这些都可以正常工作,但一旦我构建为x64(对于任何CPU,当且仅当它作为32位进程的一部分运行时,它才能工作)。在状态栏中设置文本是可行的,但我在转换为IVsActivityLog时遇到一个异常: Unhandled Exception: System.InvalidCast

我想从一个外部C#程序自动化Visual Studio。如前所述,我获取给定processId的DTE对象。然后我从DTE对象中获取一个ServiceProvider和IVsActivityLog,如前所述

作为
x86
,所有这些都可以正常工作,但一旦我构建为
x64
(对于
任何CPU
,当且仅当它作为32位进程的一部分运行时,它才能工作)。在状态栏中设置文本是可行的,但我在转换为
IVsActivityLog
时遇到一个异常:

Unhandled Exception: System.InvalidCastException: Unable to cast COM object of type 'System.__ComObject' to interface type 'Microsoft.VisualStudio.Shell.Interop.IVsActivityLog'. This operation failed because the QueryInterface call on the COM component for the interface with IID '{76AF73F9-A322-42B0-A515-D4D7553508FE}' failed due to the following error: Class not registered (Exception from HRESULT: 0x80040154 (REGDB_E_CLASSNOTREG)).
这是一个简化的例子:

    static void Main(string[] args)
    {
        int processID = 42;  // well... replace by the correct PID
        _DTE dte = GetDTE(processID);
        dte.StatusBar.Text = $"Hello World!";

        var serviceProvider = new ServiceProvider((Microsoft.VisualStudio.OLE.Interop.IServiceProvider)dte.DTE);
        var log = (IVsActivityLog)serviceProvider.GetService(typeof(SVsActivityLog));
        log.LogEntry((uint)__ACTIVITYLOG_ENTRYTYPE.ALE_WARNING, typeof(Program).ToString(), "Test");
    }

    [DllImport("ole32.dll")]
    private static extern int CreateBindCtx(int reserved, out IBindCtx ppbc);

    [DllImport("ole32.dll")]
    private static extern int GetRunningObjectTable(int reserved, out IRunningObjectTable prot);

    public static _DTE GetDTE(int processId)
    {
        IntPtr numFetched = IntPtr.Zero;
        IRunningObjectTable runningObjectTable;
        IEnumMoniker monikerEnumerator;
        IMoniker[] monikers = new IMoniker[1];

        GetRunningObjectTable(0, out runningObjectTable);
        runningObjectTable.EnumRunning(out monikerEnumerator);
        monikerEnumerator.Reset();

        while (monikerEnumerator.Next(1, monikers, numFetched) == 0)
        {
            IBindCtx ctx;
            CreateBindCtx(0, out ctx);

            string runningObjectName;
            monikers[0].GetDisplayName(ctx, null, out runningObjectName);

            object runningObjectVal;
            runningObjectTable.GetObject(monikers[0], out runningObjectVal);

            if (runningObjectVal is _DTE && runningObjectName.StartsWith("!VisualStudio"))
            {
                int currentProcessId = int.Parse(runningObjectName.Split(':')[1]);

                if (currentProcessId == processId)
                {
                    return (_DTE)runningObjectVal;
                }
            }
        }

        return null;
    }

有人有想法吗?

从技术上讲,这是可能的。实际上并非如此,VS安装程序会写入大量注册表项。它们只对32位进程可见。嗯:-/谢谢,这是可能的。实际上并非如此,VS安装程序会写入大量注册表项。它们只对32位进程可见。嗯:-/谢谢,汉斯