在桌面C# - .website扩展上创建可修复的快捷方式

时间:2016-08-26 17:50:43

标签: c# asp.net visual-studio-2010

尝试通过单击按钮(C#)在桌面上创建.website快捷方式(可快捷键)。

我有现有代码(可行 - 但浏览器打开,立即关闭)

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.IO;

namespace ShortcutUpdater
{
    public partial class UserControl1 : UserControl
    {

    private void urlShortcutToDesktop(string linkName, string linkUrl)
    {
        string deskDir = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);

        using (StreamWriter writer = new StreamWriter(deskDir + "\\" + linkName + ".website"))
        {
            writer.WriteLine("[InternetShortcut]");
            writer.WriteLine("URL=" + linkUrl);
            writer.Flush();
        }
    }


        public UserControl1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            string linkName = "My Site";
            string linkUrl = "https://Asite.org";
            urlShortcutToDesktop(linkName, linkUrl);
        }

在记事本中打开时,创建的文件如下所示:

[InternetShortcut]
URL=https://Asite.org

如果我通过从浏览器将图标拖到我的桌面然后用记事本打开它来创建一个可用的快捷方式,它看起来像这样(这是我想要实现的,所以它不会只是打开然后关闭浏览器) :

[{000214A0-0000-0000-C000-000000000046}]
Prop4=31,asite.org
Prop3=19,11
[{A7AF692E-098D-4C08-A225-D433CA835ED0}]
Prop5=3,0
Prop9=19,0
[InternetShortcut]
URL=https://asite.org/
IDList=
IconFile=https://asite.org/favicon.ico
IconIndex=1
[{9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3}]
Prop5=8,Microsoft.Website.50DFA192.38C0BBDC

实现这一目标的最佳方法是什么?

1 个答案:

答案 0 :(得分:0)

实际上有一个正式的编程接口来创建internet shortcuts。遗憾的是,.NET程序无法使用这些接口,并且没有类型库可用于Tlbimp.exe (Type Library Importer)。这只留下两个选项:尝试在C#中复制接口定义,或使用本机实现。

我建议使用本机实现,特别是C ++ / CLI 类库,可以通过.NET代码立即使用 1 。该实现由两种类型组成:本机实现类(InternetShortcutImpl)和向托管代码公开功能的代理,实现为ref类(InternetShortcut)。这两个类都可以放在同一个文件中。

这是本机访问类的实现:

#pragma once

#include <comip.h>
#include <comdef.h>
#include <IntShCut.h>
#include <ShObjIdl.h>
#include <string>

using namespace System::Runtime::InteropServices;

_COM_SMARTPTR_TYPEDEF( IUniformResourceLocatorW, __uuidof( IUniformResourceLocatorW ) );
_COM_SMARTPTR_TYPEDEF( IPersistFile, __uuidof( IPersistFile ) );
_COM_SMARTPTR_TYPEDEF( IShellLinkW, __uuidof( IShellLinkW ) );
class InternetShortcutImpl
{
public:
    InternetShortcutImpl()
    {
        HRESULT hr = ::CoCreateInstance( CLSID_InternetShortcut, nullptr,
                                         CLSCTX_INPROC_SERVER,
                                         IID_IUniformResourceLocatorW,
                                         (void**)&m_spURL );
        if ( FAILED( hr ) ) {
            throw gcnew ExternalException( nullptr, hr );
        }
    }

    void SetURL( const std::wstring& url ) {
        HRESULT hr = m_spURL->SetURL( url.c_str(), 0x0 );
        if ( FAILED( hr ) ) {
            throw gcnew ExternalException( nullptr, hr );
        }
    }

    void SetIconLocation( const std::wstring& iconpath, int index ) {
        IShellLinkWPtr spLink;
        HRESULT hr = m_spURL->QueryInterface( IID_PPV_ARGS( &spLink ) );
        if ( SUCCEEDED( hr ) ) {
            hr = spLink->SetIconLocation( iconpath.c_str(), index );
        }
        if ( FAILED( hr ) ) {
            throw gcnew ExternalException( nullptr, hr );
        }
    }

    void Save( const std::wstring& pathname, bool remember ) {
        IPersistFilePtr spFile;
        HRESULT hr = m_spURL->QueryInterface( IID_PPV_ARGS( &spFile ) );
        if SUCCEEDED( hr ) {
            hr = spFile->Save( pathname.c_str(), remember ? TRUE : FALSE );
        }
        if ( FAILED( hr ) ) {
            throw gcnew ExternalException( nullptr, hr );
        }
    }
private:
    IUniformResourceLocatorWPtr m_spURL;
};

这是代理类,它基本上只转发从.NET到本机类的调用,它作为成员包含:

#include <msclr\marshal_cppstd.h>

using namespace System;

namespace ShortcutInteropLib {
#pragma warning(push)
#pragma warning(disable : 4461)  // "this class has a finalizer but no destructor"
    public ref class InternetShortcut
    {
    public:
        InternetShortcut() {
            m_pImpl = new InternetShortcutImpl();
        }

        void SetURL( String^ url ) {
            m_pImpl->SetURL( msclr::interop::marshal_as<std::wstring>( url ) );
        }

        void SetIconLocation( String^ iconpath, int index ) {
            m_pImpl->SetIconLocation( msclr::interop::marshal_as<std::wstring>( iconpath ),
                                      index );
        }

        void Save( String^ pathname, bool remember ) {
            m_pImpl->Save( msclr::interop::marshal_as<std::wstring>( pathname ),
                           remember );
        }

        !InternetShortcut() {
            delete m_pImpl;
        }

    private:
        InternetShortcutImpl* m_pImpl;
    };
#pragma warning(pop)
}

这构成了整个库,可以从.NET程序集中引用它。调用代码非常简单:

class Program
{
    [STAThread]
    static void Main(string[] args)
    {
        var shortcut = new InternetShortcut();
        shortcut.SetURL(@"http://www.example.com");
        //shortcut.SetIconLocation(@"http://www.example.com/favicon", 1);
        shortcut.Save(Environment.GetFolderPath(Environment.SpecialFolder.Desktop)
                      + @"\MyShortCut.url", false);
    }
}

这会在桌面上创建http://www.example.com的快捷方式。请注意,虽然我实施了SetIconLocation,但我不知道如何将其与网址一起使用。虽然图标索引正确存储在生成的 MyShortCut.url 文件中,但该路径被解释为本地文件系统 2 的路径。

代码在我的系统上生成以下互联网快捷方式:

[{000214A0-0000-0000-C000-000000000046}]
Prop3=19,2
[InternetShortcut]
IDList=
URL=http://www.example.com/

<小时/> 1 由于C ++ / CLI类库包含本机代码,因此您必须选择目标体系结构。客户端代码必须引用相应的程序集。

2 我不知道是否存在允许传递URL的特殊语法,并且系统没有将该参数解释为本地文件系统路径。如果有人知道,我会很高兴听到它。