gpt4 book ai didi

c# - 外部工具 Visual Studio

转载 作者:太空宇宙 更新时间:2023-11-03 20:57:56 25 4
gpt4 key购买 nike

我创建了一个要运行的应用程序,但从该应用程序为 Visual Studio 构建了一个外部工具。直到 15.4.0 应用程序运行良好,但他们修改了注册表。根据微软的改动,External Tools保存在这个子键下:

SOFTWARE\Microsoft\VisualStudio\14.0_Config\External Tools

观察键时,您会清楚地看到工具文件夹(子键)、Guid、Error Lookup 以及 Visual Studio 附带的其他几个。但问题是,如果您在 Visual Studio 中手动创建工具,则 key 信息会直接转储到根外部工具 key 。

因此,如果我采用以下任一方法:

var user = RegistryKey.OpenBaseKey(RegistryHive.CurrenUser, RegistryView.Default);
var tools = user.OpenSubKey(@"SOFTWARE\Microsoft\VisualStudio\14.0_Config\External Tools", true);
var path = Environment.GetCommandLineArgs()[0];

tools.SetValue("ToolArg", "$(ItemPath)");
tools.SetValue("ToolCmd", path);
tools.SetValue("ToolDir", String.Empty);
tools.SetValue("ToolOpt", 0x12);
tools.SetValue("ToolsSourceKey", String.Empty);
tools.SetValue("ToolTitle", "My Tool");

    var user = RegistryKey.OpenBaseKey(RegistryHive.CurrenUser, RegistryView.Default);
var tools = user.OpenSubKey(@"SOFTWARE\Microsoft\VisualStudio\14.0_Config\External Tools", true);
var sub = tools.CreateSubKey("MyTool");
var path = Environment.GetCommandLineArgs()[0];

sub.SetValue("ToolArg", "$(ItemPath)");
sub.SetValue("ToolCmd", path);
sub.SetValue("ToolDir", String.Empty);
sub.SetValue("ToolOpt", 0x12);
sub.SetValue("ToolsSourceKey", String.Empty);
sub.SetValue("ToolTitle", "My Tool");

该工具未出现在列表或工具栏中。 Visual Studio 2017 15.5.* 有什么不同吗?这使得它不再适用于代码?更糟糕的是,在 Visual Studio 2017 中手动创建时, key 并不总是出现。

最佳答案

在 Visual Studio 2017 中,外部工具存储在用户本地应用程序数据文件夹中的私有(private)注册表配置单元中。如果您运行 Sysinternals Process Monitor 工具,您将看到 Visual Studio 读取/写入以 \REGISTRY\A\ 开头的键 - 这就是您知道它是私有(private)注册表配置单元的方式。要更新它们,您需要通过 P/Invoking RegLoadAppKey 加载该注册表配置单元并附加到生成的句柄。可以在这里找到一个例子:

RegLoadAppKey working fine on 32-bit OS, failing on 64-bit OS, even if both processes are 32-bit

标题乍一看似乎具有误导性,但问题中给出的示例准确地显示了如何调用 RegLoadAppKey 并打开下面的子键。

接下来您必须解决的问题是找到私有(private)注册表配置单元。 Visual Studio 将私有(private)注册表配置单元存储在用户本地应用程序数据文件夹的子文件夹中。子文件夹名称将以 Microsoft\VisualStudio\15.0_ 开头,然后是一个 32 位十六进制值。我不太确定那个值是什么,或者如何优雅地发现它。每个用户都是不同的。我的方法是选择以“15.0”开头的最新文件夹并假设它是正确的。如果有人有更好的方法来识别这个文件夹,我很乐意看到它。

我将版本号和十六进制字符串的组合称为“版本标签”。您需要跟踪它,因为版本标记将再次用作私有(private)注册表配置单元中的子键。

总而言之,我创建了一个 VisualStudioContext 类,用于定位私有(private)注册表配置单元并加载根键。

public class VisualStudioContext : IDisposable
{
public string VersionTag { get; }
public string UserFolder { get; }
public string PrivateRegistryPath { get; }
public SafeRegistryHandle RegistryHandle { get; }
public RegistryKey RootKey { get; }

private static readonly Lazy<VisualStudioContext> LazyInstance = new Lazy<VisualStudioContext>(() => new VisualStudioContext());

public static VisualStudioContext Instance => LazyInstance.Value;

private VisualStudioContext()
{
try
{
string localAppDataFolder = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
string vsFolder = $"{localAppDataFolder}\\Microsoft\\VisualStudio";
var vsFolderInfo = new DirectoryInfo(vsFolder);
DateTime lastDateTime = DateTime.MinValue;

foreach (DirectoryInfo dirInfo in vsFolderInfo.GetDirectories("15.0_*"))
{
if (dirInfo.CreationTime <= lastDateTime)
continue;

UserFolder = dirInfo.FullName;
lastDateTime = dirInfo.CreationTime;
}

if (UserFolder == null)
throw new Exception($"No Visual Studio folders found in \"{vsFolder}\"");
}
catch (Exception ex)
{
throw new Exception("Unable to open Visual Studio folder", ex);
}

VersionTag = Path.GetFileName(UserFolder);

PrivateRegistryPath = $"{UserFolder}\\privateregistry.bin";
int handle = RegistryNativeMethods.RegLoadAppKey(PrivateRegistryPath);

RegistryHandle = new SafeRegistryHandle(new IntPtr(handle), true);
RootKey = RegistryKey.FromHandle(RegistryHandle);
}

public void Dispose()
{
RootKey?.Close();
RegistryHandle?.Dispose();
}

public class Exception : ApplicationException
{
public Exception(string message) : base(message)
{
}

public Exception(string message, Exception innerException) : base(message, innerException)
{
}
}

internal static class RegistryNativeMethods
{
[Flags]
public enum RegSAM
{
AllAccess = 0x000f003f
}

private const int REG_PROCESS_APPKEY = 0x00000001;

// approximated from pinvoke.net's RegLoadKey and RegOpenKey
// NOTE: changed return from long to int so we could do Win32Exception on it
[DllImport("advapi32.dll", SetLastError = true)]
private static extern int RegLoadAppKey(String hiveFile, out int hKey, RegSAM samDesired, int options, int reserved);

public static int RegLoadAppKey(String hiveFile)
{
int hKey;
int rc = RegLoadAppKey(hiveFile, out hKey, RegSAM.AllAccess, REG_PROCESS_APPKEY, 0);

if (rc != 0)
{
throw new Win32Exception(rc, "Failed during RegLoadAppKey of file " + hiveFile);
}

return hKey;
}
}
}

您可以像这样使用它打开外部工具键:

using (var context = VisualStudioContext.Instance)
{
RegistryKey keyExternalTools =
context.RootKey.OpenSubKey($"Software\\Microsoft\\VisualStudio\\{context.VersionTag}\\External Tools", true);

// Do something interesting here
}

关于c# - 外部工具 Visual Studio,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48528291/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com