英文:
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)
}
英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论