Create a Windows Shortcut (.lnk) in Go

huangapple go评论91阅读模式
英文:

Create a Windows Shortcut (.lnk) in Go

问题

我想在Golang中创建一个到桌面和开始菜单的Windows快捷方式(.lnk)。

我已经通过gowin模块获取了桌面和开始菜单文件夹,我想要创建到这些位置的快捷方式。

我搜索了一下,但没有找到任何关于此的Golang项目。我应该自己创建吗?还有其他更好的方法吗?

英文:

I would like to create a Windows Shortcut (.lnk) to the desktop and the startmenu in Golang.

I actually got the Desktop & Startmenu folders via the gowin module and I would like to create a shortcut to thoses locations.

I searched but I did not find any golang project for it. Should I create it ? Is there an other pretty method ?

答案1

得分: 9

使用https://github.com/go-ole/go-ole:

func makeLink(src, dst string) error {
    ole.CoInitializeEx(0, ole.COINIT_APARTMENTTHREADED|ole.COINIT_SPEED_OVER_MEMORY)
    oleShellObject, err := oleutil.CreateObject("WScript.Shell")
    if err != nil {
        return err
    }
    defer oleShellObject.Release()
    wshell, err := oleShellObject.QueryInterface(ole.IID_IDispatch)
    if err != nil {
        return err
    }
    defer wshell.Release()
    cs, err := oleutil.CallMethod(wshell, "CreateShortcut", dst)
    if err != nil {
        return err
    }
    idispatch := cs.ToIDispatch()
    oleutil.PutProperty(idispatch, "TargetPath", src)
    oleutil.CallMethod(idispatch, "Save")
    return nil
}
英文:

Using https://github.com/go-ole/go-ole:

func makeLink(src, dst string) error {
    ole.CoInitializeEx(0, ole.COINIT_APARTMENTTHREADED|ole.COINIT_SPEED_OVER_MEMORY)
    oleShellObject, err := oleutil.CreateObject("WScript.Shell")
    if err != nil {
        return err
    }
    defer oleShellObject.Release()
    wshell, err := oleShellObject.QueryInterface(ole.IID_IDispatch)
    if err != nil {
        return err
    }
    defer wshell.Release()
    cs, err := oleutil.CallMethod(wshell, "CreateShortcut", dst)
    if err != nil {
        return err
    }
    idispatch := cs.ToIDispatch()
    oleutil.PutProperty(idispatch, "TargetPath", src)
    oleutil.CallMethod(idispatch, "Save")
    return nil
}

答案2

得分: 2

通过外部程序解决方案来自这个主题

来自NirSoft的快捷方式可执行文件

shortcut "f:\winnt\system32\calc.exe" "~$folder.desktop$" "Windows Calculator"
shortcut "f:\winnt\system32\calc.exe" "~$folder.programs$\Calculators" "Windows Calculator"
shortcut "f:\Program Files\KaZaA\Kazaa.exe" "c:\temp\MyShortcuts" "Kazaa"
shortcut "f:\Program Files" "c:\temp\MyShortcuts" "Program Files Folder" "" "f:\winnt\system32\shell32.dll" 45
shortcut "f:\Program Files" "c:\temp\MyShortcuts" "Program Files Folder" "" "" "" "max"

来自Optimumx的快捷方式可执行文件

Shortcut.exe /f:"%USERPROFILE%\Desktop\sc.lnk" /a:c /t:%USERPROFILE%\Desktop\scrum.pdf

.vbs

Set oWS = WScript.CreateObject("WScript.Shell")
sLinkFile = "C:\MyShortcut.LNK"
Set oLink = oWS.CreateShortcut(sLinkFile)
    oLink.TargetPath = "C:\Program Files\MyApp\MyProgram.EXE"
 '  oLink.Arguments = ""
 '  oLink.Description = "MyProgram"   
 '  oLink.HotKey = "ALT+CTRL+F"
 '  oLink.IconLocation = "C:\Program Files\MyApp\MyProgram.EXE, 2"
 '  oLink.WindowStyle = "1"   
 '  oLink.WorkingDirectory = "C:\Program Files\MyApp"
oLink.Save

Powershell脚本

set TARGET='D:\Temp'
set SHORTCUT='C:\Temp\test.lnk'
set PWS=powershell.exe -ExecutionPolicy Bypass -NoLogo -NonInteractive -NoProfile

%PWS% -Command "$ws = New-Object -ComObject WScript.Shell; $s = $ws.CreateShortcut(%SHORTCUT%); $S.TargetPath = %TARGET%; $S.Save()"
英文:

Solution via external program from this subject:

Shortcut executable from NirSoft

shortcut "f:\winnt\system32\calc.exe" "~$folder.desktop$" "Windows Calculator" 
shortcut "f:\winnt\system32\calc.exe" "~$folder.programs$\Calculators" "Windows Calculator" 
shortcut "f:\Program Files\KaZaA\Kazaa.exe" "c:\temp\MyShortcuts" "Kazaa" 
shortcut "f:\Program Files" "c:\temp\MyShortcuts" "Program Files Folder" "" "f:\winnt\system32\shell32.dll" 45 
shortcut "f:\Program Files" "c:\temp\MyShortcuts" "Program Files Folder" "" "" "" "max"

Shortcut executable from Optimumx

Shortcut.exe /f:"%USERPROFILE%\Desktop\sc.lnk" /a:c  /t:%USERPROFILE%\Desktop\scrum.pdf

.vbs

Set oWS = WScript.CreateObject("WScript.Shell")
sLinkFile = "C:\MyShortcut.LNK"
Set oLink = oWS.CreateShortcut(sLinkFile)
    oLink.TargetPath = "C:\Program Files\MyApp\MyProgram.EXE"
 '  oLink.Arguments = ""
 '  oLink.Description = "MyProgram"   
 '  oLink.HotKey = "ALT+CTRL+F"
 '  oLink.IconLocation = "C:\Program Files\MyApp\MyProgram.EXE, 2"
 '  oLink.WindowStyle = "1"   
 '  oLink.WorkingDirectory = "C:\Program Files\MyApp"
oLink.Save

Powershell script

set TARGET='D:\Temp'
set SHORTCUT='C:\Temp\test.lnk'
set PWS=powershell.exe -ExecutionPolicy Bypass -NoLogo -NonInteractive -NoProfile

%PWS% -Command "$ws = New-Object -ComObject WScript.Shell; $s = $ws.CreateShortcut(%SHORTCUT%); $S.TargetPath = %TARGET%; $S.Save()"

答案3

得分: 2

使用VBS的可怕的工作中的golang解决方案;

package main

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
)

func createShortcut(linkName string, target string, arguments string, directory string, description string, destination string) {
	var scriptTxt bytes.Buffer
	scriptTxt.WriteString("option explicit\n\n")
	scriptTxt.WriteString("sub CreateShortCut()\n")
	scriptTxt.WriteString("dim objShell, strDesktopPath, objLink\n")
	scriptTxt.WriteString("set objShell = CreateObject(\"WScript.Shell\")\n")
	scriptTxt.WriteString("strDesktopPath = objShell.SpecialFolders(\"")
	scriptTxt.WriteString(destination)
	scriptTxt.WriteString("\")\n")
	scriptTxt.WriteString("set objLink = objShell.CreateShortcut(strDesktopPath & \"\\")
	scriptTxt.WriteString(linkName)
	scriptTxt.WriteString(".lnk\")\n")
	scriptTxt.WriteString("objLink.Arguments = \"")
	scriptTxt.WriteString(arguments)
	scriptTxt.WriteString("\"\n")
	scriptTxt.WriteString("objLink.Description = \"")
	scriptTxt.WriteString(description)
	scriptTxt.WriteString("\"\n")
	scriptTxt.WriteString("objLink.TargetPath = \"")
	scriptTxt.WriteString(target)
	scriptTxt.WriteString("\"\n")
	scriptTxt.WriteString("objLink.WindowStyle = 1\n")
	scriptTxt.WriteString("objLink.WorkingDirectory = \"")
	scriptTxt.WriteString(directory)
	scriptTxt.WriteString("\"\n")
	scriptTxt.WriteString("objLink.Save\nend sub\n\n")
	scriptTxt.WriteString("call CreateShortCut()")
	fmt.Print(scriptTxt.String())

	filename := fmt.Sprintf("lnkTo%s.vbs", destination)
	ioutil.WriteFile(filename, scriptTxt.Bytes(), 0777)
	cmd := exec.Command("wscript", filename)
	err := cmd.Run()
	if err != nil {
		fmt.Println(err)
	}
	cmd.Wait()
	os.Remove(filename)
	return
}
英文:

The AWFUL Working golang solution using VBS;

package main
import(
"bytes"
"fmt"
"io/ioutil"
"os"
"os/exec"
)
func createShortcut(linkName string, target string, arguments string, directory string, description string, destination string) {
var scriptTxt bytes.Buffer
scriptTxt.WriteString("option explicit\n\n")
scriptTxt.WriteString("sub CreateShortCut()\n")
scriptTxt.WriteString("dim objShell, strDesktopPath, objLink\n")
scriptTxt.WriteString("set objShell = CreateObject(\"WScript.Shell\")\n")
scriptTxt.WriteString("strDesktopPath = objShell.SpecialFolders(\"")
scriptTxt.WriteString(destination)
scriptTxt.WriteString("\")\n")
scriptTxt.WriteString("set objLink = objShell.CreateShortcut(strDesktopPath & \"\\")
scriptTxt.WriteString(linkName)
scriptTxt.WriteString(".lnk\")\n")
scriptTxt.WriteString("objLink.Arguments = \"")
scriptTxt.WriteString(arguments)
scriptTxt.WriteString("\"\n")
scriptTxt.WriteString("objLink.Description = \"")
scriptTxt.WriteString(description)
scriptTxt.WriteString("\"\n")
scriptTxt.WriteString("objLink.TargetPath = \"")
scriptTxt.WriteString(target)
scriptTxt.WriteString("\"\n")
scriptTxt.WriteString("objLink.WindowStyle = 1\n")
scriptTxt.WriteString("objLink.WorkingDirectory = \"")
scriptTxt.WriteString(directory)
scriptTxt.WriteString("\"\n")
scriptTxt.WriteString("objLink.Save\nend sub\n\n")
scriptTxt.WriteString("call CreateShortCut()")
fmt.Print(scriptTxt.String())
filename := fmt.Sprintf("lnkTo%s.vbs", destination)
ioutil.WriteFile(filename, scriptTxt.Bytes(), 0777)
cmd := exec.Command("wscript", filename)
err := cmd.Run()
if err != nil {
fmt.Println(err)
}
cmd.Wait()
os.Remove(filename)
return
}

答案4

得分: 1

不,Go语言中没有一种优雅的方法来创建.lnk文件。主要原因是.lnk文件是Windows特定的。

在Windows中,即使是本地程序,也需要使用OLE(对象链接和嵌入)和COM(组件对象模型)来创建快捷方式文件,如此答案所述。

在我看来,解决这个问题的一种方法是使用gowin,并尝试与OLE COM进行通信。

或者,编写一个实际创建.lnk文件的本地Windows组件,并通过你的Go程序启动它的进程。

英文:

No, there isn't any pretty method for creating .lnk file, in golang.

Primary reason is that, .lnk files are windows specific.

In Windows, even a native program need to use OLE (Object linking and embedding) and COM (component object model) to create a shortcut file, as described in this answer.

In my opinion, One way to approach this problem in golang is to use gowin, and try to communicate with OLE COM.

OR

Write a native windows component that does actual work of creating .lnk file, and just spawn its process through your go program.

答案5

得分: 1

以下是一个替代方案,如果出于任何原因您不想使用外部的go包。如Alexis Paques所提到的,您可以使用PowerShell在Windows下创建快捷方式。优点是,它已经在几乎所有的Windows环境中可用。下面是一个在shell:startup文件夹中创建快捷方式的实现,它将在启动时自动启动当前用户链接的程序:

package main

import (
	"bytes"
	"log"
	"os/exec"
	"strings"
)

type PowerShell struct {
	powerShell string
}

var WIN_CREATE_SHORTCUT = `$WshShell = New-Object -comObject WScript.Shell
$Shortcut = $WshShell.CreateShortcut("$HOME\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\MyAPP.lnk")
$Shortcut.TargetPath = "PLACEHOLDER"
$Shortcut.Save()`

// New create new session
func New() *PowerShell {
	ps, _ := exec.LookPath("powershell.exe")
	return &PowerShell{
		powerShell: ps,
	}
}

func (p *PowerShell) execute(args ...string) (stdOut string, stdErr string, err error) {
	args = append([]string{"-NoProfile", "-NonInteractive"}, args...)
	cmd := exec.Command(p.powerShell, args...)

	var stdout bytes.Buffer
	var stderr bytes.Buffer
	cmd.Stdout = &stdout
	cmd.Stderr = &stderr

	err = cmd.Run()
	stdOut, stdErr = stdout.String(), stderr.String()
	return
}

// enableAutostartWin creates a shortcut to MyAPP in the shell:startup folder
func enableAutostartWin() {
	ps := New()
	exec_path := "C:\\MyAPP.exe"
	WIN_CREATE_SHORTCUT = strings.Replace(WIN_CREATE_SHORTCUT, "PLACEHOLDER", exec_path, 1)
	stdOut, stdErr, err := ps.execute(WIN_CREATE_SHORTCUT)
	log.Printf("CreateShortcut:\nStdOut : '%s'\nStdErr: '%s'\nErr: %s",
		strings.TrimSpace(stdOut), stdErr, err)
}

这个答案基于这个SO答案和这个gist

英文:

Here is an alternative, if for any reason you don't want to use an external go package.
As mentioned by Alexis Paques you can use Powershell to create shortcuts under Windows. The advantage is, that it's already available in virtually all Windows environments. Here is an implementation for creating a shortcut in the shell:startup folder, which will auto start the linked program for the current user on startup:

package main
import (
"bytes"
"log"
"os/exec"
"strings"
)
type PowerShell struct {
powerShell string
}
var WIN_CREATE_SHORTCUT = `$WshShell = New-Object -comObject WScript.Shell
$Shortcut = $WshShell.CreateShortcut("$HOME\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\MyAPP.lnk")
$Shortcut.TargetPath = "PLACEHOLDER"
$Shortcut.Save()`
// New create new session
func New() *PowerShell {
ps, _ := exec.LookPath("powershell.exe")
return &PowerShell{
powerShell: ps,
}
}
func (p *PowerShell) execute(args ...string) (stdOut string, stdErr string, err error) {
args = append([]string{"-NoProfile", "-NonInteractive"}, args...)
cmd := exec.Command(p.powerShell, args...)
var stdout bytes.Buffer
var stderr bytes.Buffer
cmd.Stdout = &stdout
cmd.Stderr = &stderr
err = cmd.Run()
stdOut, stdErr = stdout.String(), stderr.String()
return
}
// enableAutostartWin creates a shortcut to MyAPP in the shell:startup folder
func enableAutostartWin() {
ps := New()
exec_path := "C:\\MyAPP.exe"
WIN_CREATE_SHORTCUT = strings.Replace(WIN_CREATE_SHORTCUT, "PLACEHOLDER", exec_path, 1)
stdOut, stdErr, err := ps.execute(WIN_CREATE_SHORTCUT)
log.Printf("CreateShortcut:\nStdOut : '%s'\nStdErr: '%s'\nErr: %s",
strings.TrimSpace(stdOut), stdErr, err)
}

This answer is based on this SO answer and this gist.

huangapple
  • 本文由 发表于 2015年9月7日 19:59:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/32438204.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定