签署一个 F# 程序集(强名称组件)

9
我在 CodeProject 上发现了这篇文章:http://www.codeproject.com/Articles/512956/NET-Shell-Extensions-Shell-Context-Menus,觉得它值得一试,但用 F#。以下是我想到的代码:
open System
open System.IO
open System.Text
open System.Runtime.InteropServices
open System.Windows.Forms
open SharpShell
open SharpShell.Attributes
open SharpShell.SharpContextMenu

[<ComVisible(true)>]
[<COMServerAssociation(AssociationType.ClassOfExtension, ".txt")>]
type CountLinesExtension() =
    inherit SharpContextMenu.SharpContextMenu()

    let countLines =
        let builder = new StringBuilder()
        do 
            base.SelectedItemPaths |> Seq.iter (fun x -> builder.AppendLine(sprintf "%s - %d Lines" (Path.GetFileName(x)) (File.ReadAllLines(x).Length)) |> ignore  )
            MessageBox.Show(builder.ToString()) |> ignore

    let createMenu =
        let menu = new ContextMenuStrip()
        let itemCountLines = new ToolStripMenuItem(Text = "Count Lines")
        do
            itemCountLines.Click.Add (fun _ -> countLines)
            menu.Items.Add(itemCountLines) |> ignore
        menu

    override this.CanShowMenu() = true
    override this.CreateMenu() = createMenu

然而,我注意到在VS2012中没有支持签署F#程序集(文章的步骤4)。我了解到,如果我想这样做,我需要手动创建一个密钥(在命令提示符中输入“sn -k keyName.snk”)然后在“项目属性 -> 构建 -> 其他标志”中添加一个标志(--keyfile: keyName.snk)。
但我仍然无法成功运行它。此外,在使用作者的应用程序(在“调试Shell扩展”部分)时,我会收到一个错误消息,指出我的程序集不包含COM服务器。
我认为我在签署组件方面做错了什么。您能帮助我运行它吗?

我相信你遇到的COM服务器错误问题与F#无关,而是与你的密钥有关。请确保你正在使用的证书已在本地机器上注册。 - N_A
“Doesnt contain a COM server” 表示您的 COM 组件的可见性/注册存在问题。 您可以使用 sn -v(或者是 -V?)来验证签名,但最重要的是,如果这是问题,将会有一个错误提示说 authenticode 签名错误。并且请使用 ProcMon 和 DbgView 进行排查。如果您获得了更多关于确切错误消息的详细信息等,请在此处添加该详细信息,这样也无妨。 - Ruben Bartelink
我运行了“sn -v <myAssemblyName.dll>”,结果显示 程序集'ShellExtentions.dll'是有效的。更准确地说,当我尝试在服务器管理器(来自文章)中加载此程序集时,我收到一个错误 "<myAssebly>不是SharpShell扩展"。我还尝试将程序集注册到GAC中,但也没有起作用。 - LA.27
2个回答

15

通过使用AssemblyFileKeyAttribute特性之一,可以对一个F#程序集进行签名。

创建一个新的模块,并在其中添加以下内容:

module AssemblyProperties

open System
open System.Reflection;
open System.Runtime.InteropServices;

[<assembly:AssemblyKeyFileAttribute("MyKey.snk")>]

do()

"MyKey.snk"是相对于项目目录的密钥路径。

另外一种方法是在这个Microsoft Connect的bug报告中发现的,即将--keyfile:MyKey.snk添加到属性-->生成选项卡中的其他标志字段中。

使用任何一种方法后,运行sn -v myfsharpassembly.dll会在编译后断言程序集有效。


1
也许问题是该程序集不是“ComVisible”吗?
我在 F# 中使用此库,如下所示:
[<assembly:ComVisible(true)>]
[<assembly:AssemblyKeyFile("Key.snk")>]
do
   ()

也就是说,我在顶层 do 块中指定汇编级别的属性。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接