سؤال

لديّ أداة مخصصة الخاصة بي لـ Visual Studio 2008 SP1. وهو يتكون من 5 مجموعات: 3 مجموعات مع رمز تستخدم بكثافة في مشاريعي الأخرى ، و 1 تجميع التجميع فوق VS2008 SDK وتجميع مع الأداة.

إذا كنت أقوم بتصحيح أدواتي من Visual Studio ، باستخدام خيار "تشغيل البرنامج الخارجي" مع سطر الأوامر "C: Program Files (x86) Microsoft Visual Studio 9.0 Common7 Ide devenv.exe" والوسائط " /RANU / Rootsuffix exp "كل شيء يعمل بشكل مثالي.

بعد ذلك أحاول نشره على نسخة العمل مقابل الخلية التجريبية ، والقيام: gacutil /i Asm1.dll لجميع تجميعاتي والقيام RegAsm Asm1.dll فقط للتجميع مع أداة مخصصة. لا يطبع أي من Utils أي خطأ ، كل العمل كما هو مخطط له ، حتى مفاتيح التسجيل. لكن أداتي لا تعمل (حدث خطأ "لا يمكن العثور على أداة مخصصة" Transporgeneratortool "على هذا النظام") حتى بعد إعادة تشغيل الكمبيوتر. أي خطأ ارتكبت؟

الغلاف يبدو هكذا:

[ComVisible(true)]
public abstract class CustomToolBase : IVsSingleFileGenerator, IObjectWithSite
{
    #region IVsSingleFileGenerator Members
    int IVsSingleFileGenerator.DefaultExtension(out string pbstrDefaultExtension)
    {
        pbstrDefaultExtension = ".cs";
        return 0;
    }

    int IVsSingleFileGenerator.Generate(string wszInputFilePath, string bstrInputFileContents, string wszDefaultNamespace, IntPtr[] rgbOutputFileContents, out uint pcbOutput, IVsGeneratorProgress pGenerateProgress)
    {
        GenerationEventArgs gea = new GenerationEventArgs(
            bstrInputFileContents,
            wszInputFilePath,
            wszDefaultNamespace,
            new ServiceProvider(Site as Microsoft.VisualStudio.OLE.Interop.IServiceProvider)
                .GetService(typeof(ProjectItem)) as ProjectItem,
            new GenerationProgressFacade(pGenerateProgress)
                );

        if (OnGenerateCode != null)
        {
            OnGenerateCode(this, gea);
        }

        byte[] bytes = gea.GetOutputCodeBytes();

        int outputLength = bytes.Length;
        rgbOutputFileContents[0] = Marshal.AllocCoTaskMem(outputLength);
        Marshal.Copy(bytes, 0, rgbOutputFileContents[0], outputLength);
        pcbOutput = (uint)outputLength;
        return VSConstants.S_OK;
    }
    #endregion

    #region IObjectWithSite Members
    void IObjectWithSite.GetSite(ref Guid riid, out IntPtr ppvSite)
    {
        IntPtr pUnk = Marshal.GetIUnknownForObject(Site);
        IntPtr intPointer = IntPtr.Zero;
        Marshal.QueryInterface(pUnk, ref riid, out intPointer);
        ppvSite = intPointer;
    }

    void IObjectWithSite.SetSite(object pUnkSite)
    {
        Site = pUnkSite;
    }
    #endregion

    #region Public Members
    public object Site { get; private set; }

    public event EventHandler<GenerationEventArgs> OnGenerateCode;

    [ComRegisterFunction]
    public static void Register(Type type)
    {
        using (var parent = Registry.LocalMachine.OpenSubKey(@"Software\Microsoft\VisualStudio\9.0", true))
            foreach (CustomToolRegistrationAttribute ourData in type.GetCustomAttributes(typeof(CustomToolRegistrationAttribute), false))
                ourData.Register(x => parent.CreateSubKey(x), (x, name, value) => x.SetValue(name, value));
    }

    [ComUnregisterFunction]
    public static void Unregister(Type type)
    {
        using (var parent = Registry.LocalMachine.OpenSubKey(@"Software\Microsoft\VisualStudio\9.0", true))
            foreach (CustomToolRegistrationAttribute ourData in type.GetCustomAttributes(typeof(CustomToolRegistrationAttribute), false))
                ourData.Unregister(x => parent.DeleteSubKey(x, false));
    }

    #endregion
}

رمز الأداة الخاص بي:

[ComVisible(true)]
[Guid("55A6C192-D29F-4e22-84DA-DBAF314ED5C3")]
[CustomToolRegistration(ToolName, typeof(TransportGeneratorTool))]
[ProvideObject(typeof(TransportGeneratorTool))]
public class TransportGeneratorTool : CustomToolBase
{
    private const string ToolName = "TransportGeneratorTool";

    public TransportGeneratorTool()
    {
        OnGenerateCode += GenerateCode;
    }

    private static void GenerateCode(object s, GenerationEventArgs e)
    {
        try
        {
            var serializer = new XmlSerializer(typeof (Parser.System));
            using (var reader = new StringReader(e.InputText))
            using (var writer = new StringWriter(e.OutputCode))
            {
                Generator.System = (Parser.System) serializer.Deserialize(reader);
                Generator.System.Namespace = e.Namespace;
                Generator.GenerateSource(writer);
            }
        }
        catch (Exception ex)
        {
            e.Progress.GenerateError(ex.ToString());
        }
    }
}

مفاتيح التسجيل الناتجة:

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\9.0\Generators]

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\9.0\Generators\{FAE04EC1-301F-11D3-BF4B-00C04F79EFBC}]

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\9.0\Generators\{FAE04EC1-301F-11D3-BF4B-00C04F79EFBC}\TransportGeneratorTool]
@="TransportGeneratorTool"
"CLSID"="{55a6c192-d29f-4e22-84da-dbaf314ed5c3}"
"GeneratesDesignTimeSource"=dword:00000001
"GeneratesSharedDesignTimeSource"=dword:00000001

فيما يلي رمز السمة المخصصة الخاصة بي (إنه في مجموعة Wrapper):

[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
public class CustomToolRegistrationAttribute : RegistrationAttribute
{
    public CustomToolRegistrationAttribute(string name, Type customToolType)
    {
        Name = name;
        CustomToolType = customToolType;
    }

    /// <summary>
    /// The type that implements the custom tool.  This starts 
    /// as MyCustomTool by default in the template.
    /// </summary>
    public Type CustomToolType { get; set; }

    public string Name { get; set; }

    #region RegistrationAttribute abstract member implementations
    public override void Register(RegistrationContext context)
    {
        Register(x => context.CreateKey(x), (x, key, value) => x.SetValue(key, value));
    }

    public void Register<T>(Func<string, T> keyCreator, Action<T, string, object> valueCreator)
    {
        var keyName = CreateKeyName(Name);
        var key = keyCreator(keyName);

        valueCreator(key, string.Empty, Name);
        valueCreator(key, "CLSID", CustomToolType.GUID.ToString("B"));
        valueCreator(key, "GeneratesDesignTimeSource", 1);
        valueCreator(key, "GeneratesSharedDesignTimeSource", 1);

        var disposable = key as IDisposable;
        if (disposable != null)
            disposable.Dispose();
    }

    private static string CreateKeyName(string name)
    {
        return string.Format(@"Generators\{0}\{1}", vsContextGuids.vsContextGuidVCSProject, name);
    }

    public override void Unregister(RegistrationContext context)
    {
        Unregister(context.RemoveKey);
    }

    public void Unregister(Action<string> keyRemover)
    {
        keyRemover(CreateKeyName(Name));
    }

    #endregion
}
هل كانت مفيدة؟

المحلول

الحل الخاص بي هو إنشاء مشروع إعداد. أحصل على إعدادات التسجيل من ملف PKGDEF عن طريق إضافة ما يلي إلى ملف CSPROJ للحزمة:

<Target Name="GeneratePackageRegistryFiles">
  <Exec Command="&quot;$(VSSDK90Install)VisualStudioIntegration\Tools\Bin\RegPkg.exe&quot; /root:Software\Microsoft\VisualStudio\9.0 /codebase &quot;$(TargetPath)&quot; /regfile:&quot;$(OutDir)$(TargetName).reg&quot;" />
</Target>
<PropertyGroup> 
  <BuildDependsOn>$(BuildDependsOn);GeneratePackageRegistryFiles;</BuildDependsOn>
</PropertyGroup>

عند إنشاء البناء في دليل الإخراج ، يجب أن تجد ملف .reg الذي يمكنك استيراده في مشروع الإعداد.

من الواضح أنه يمكنك تشغيل regpkg.exe من سطر الأوامر إذا كان تعديل المشروع ليس خيارًا.

نصائح أخرى

هذا ما انتهى بي الأمر مع آخر مرة عندما ناضلت لتسجيل الأداة المخصصة الخاصة بي. آمل أن تكون هذه التعليمات مفصلة بما فيه الكفاية وتغطي كل شيء حتى لا تقضي الكثير من الوقت في محاربة ذلك. تم استخدام مقالة MSDN التالية كنقطة انطلاق. http://msdn.microsoft.com/en-us/library/bb166527(v=vs.80).aspx للأسف لا يمكنك استخدامه بمفردك. ما عليك فعله حقًا هو:

  1. تأكد من توقيع التجميع. لماذا ا؟ لأنه وإلا فلن تتمكن من وضعه في GAC في الخطوة 6 أدناه. لتوقيع التجميع الخاص بك اتبع الخطوات هذه:

    1.1. اذهب إلى الخصائص شاشة المشروع.

    1.2. مرة واحدة هناك اذهب إلى التوقيع التبويب.

    1.3. بمجرد التحقق من التوقيع على التجمع مربع الاختيار.

  2. تأكد من معرفة رقم إصدار التجميع الخاص بك. ستحتاج إلى هذا الرقم لتحديد Assembly_version المعلمة لاحقًا. من أجل فتح هذا الرقم AssemblyInfo.cs ملف في الخصائص مجلد مشروعك وابحث عن الخط الذي يبدأ بـ: [التجميع: AssemblyVersion (

  3. تأكد من أنك تعرف GUID من فئة المولد. ستحتاج إليها لتحديد generator_guid المعلمة لاحقًا. من أجل الحصول على هذا GUID افتح الملف باستخدام فئة المولد والبحث عن GUID class-attribute التي تزين هذه الفئة ، شيء مثل: [GUID ("1779E85-421B-4684-B59E-650E34ECC718")]

  4. بناء المشروع

  5. احصل على مفتاح الرمز المميز للتجميع. من أجل القيام بذلك ، سيتعين عليك تشغيل الأمر التالي:

    sn.exe -t Assembly_file

    ستحتاج إلى هذه المعلومات لاحقًا public_token_key. ال sn.exe يمكن العثور على الملف في C: Program Files Microsoft SDKS Windows v8.0a bin sn.exeانتبه إلى رقم إصدار الإطار (V8.0A) في FilePath أعلاه. يجب أن تكون متسقة مع إصدار الإطار المستخدم لتجميع المشروع.

  6. ضع التجميع على GAC باستخدام الأمر التالي:

    gacutil.exe /i Assembly_file /F

    يتطلب الحصول على تسجيل في GAC أذونات إدارية. ال gacutil.exe يمكن العثور على الملف في C: Program Files Microsoft SDKS Windows V8.0a Bin Netfx 4.0 Tools gacutil.exeانتبه إلى رقم إصدار الإطار (V8.0A) في FilePath أعلاه. يجب أن تكون متسقة مع إصدار الإطار المستخدم لتجميع المشروع.

  7. قم بإجراء التغييرات التالية على ملف .reg (انظر أدناه). يرجى ملاحظة: يجب تزويد كل من generator_guid و project_type_guid بأقواس مجعد: {xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}

    7.1. يتم استخدام رقم الإصدار Fix من Visual Studio (على سبيل المثال: 10.0 أو 9.0): vs_version

    7.2. إصلاح GUID من المولد: generator_guid

    7.3. إصلاح مساحة اسم التجميع: اسم الاسم

    7.4. إصلاح اسم فئة المولد: generator_type_name

    7.5. من أجل تسجيل المولد ، يحتاج Visual Studio إلى معرفة أنواع المشروع التي يمكن تطبيقها على هذا المولد. لذلك تحتاج إلى الحصول على GUID لأنواع المشاريع المناسبة (C#، VB.NET ، إلخ). لمعرفة Guids لأنواع المشروع ، تحتاج إلى فتح ملف مشروع Visual Studio (*.csproj) في محرر نصوص وابحث عن Guid's في ProjectTypeguids عنصر XML. لكل من هذه GUIDs كرر كتلة آخر 3 إدخالات في ملف .reg استبدال project_type_guid مع A GUID وجدت للتو.

    7.6. إصلاح امتداد الملف المرتبط بالأداة المخصصة: file_extenstion

  8. تشغيل ملف .reg. قد تحتاج إلى الحصول على أذونات إدارية للقيام بذلك.

ملف .reg:

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\VS_VERSION\CLSID\GENERATOR_GUID]
@="COM+ class: NAMESPACE_NAME.GENERATOR_TYPE_NAME"
"InprocServer32"="C:\\WINDOWS\\system32\\mscoree.dll"
"ThreadingModel"="Both"
"Class"="NAMESPACE_NAME.GENERATOR_TYPE_NAME"
"Assembly"="NAMESPACE_NAME, Version=ASSEMBLY_VERSION, Culture=Neutral, PublicKeyToken=PUBLIC_TOKEN_KEY"

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\VS_VERSION\Generators]

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\VS_VERSION\Generators\PROJECT_TYPE_GUID]

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\VS_VERSION\Generators\PROJECT_TYPE_GUID\\.FILE_EXTENSTION]
@="GENERATOR_TYPE_NAME"

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\VS_VERSION\Generators\PROJECT_TYPE_GUID\GENERATOR_TYPE_NAME]
@="Code generator for whatever you like"
"CLSID"="GENERATOR_GUID"
"GeneratesDesignTimeSource"=dword:00000001

ملاحظة. آسف لعدم تمكنه من جعل العوامل الرائعة في ملف Reg متميزًا ، للأسف لا يمكن لمحرر النص الذي يستخدمه StackOverFlow التمييز بين عناصر الترميز عن المحتوى.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top