Newer
Older
GoModules / WindowsShortcutFull / WindowsShortcutFull.go
root on 30 Jan 2022 5 KB Typo
/***
 * Module to manipulate windows .lnk files
 * modified from: https://github.com/nyaosorg/go-windows-shortcut
 * Typical usage:

 //import
 	shortcut "GoModules/Modules/WindowsShortcutFull"

 //main
	// read shortcut data
	Description, workingDir, targetPath, Arguments, Icon, err := shortcut.Read("C:\\Users\\User\\Desktop\\vlc.lnk")
	
	// create new OR update existing shortcut
	err := shortcut.Make("C:\\Users\\User\\Desktop\\vlc.lnk", newDescription, newWorkingDir, newTarget, newArgs, newIcon)

	// create VB script to generate/update a .lnk file (useful for debugging)
	shortcut.CreateVBS("C:\\Users\\User\\Desktop\\vlc.lnk", newTarget, newArgs, newWorkingDir, newDescription, newScriptName)
*/
package WindowsShortcutFull

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"

	"github.com/go-ole/go-ole"
	"github.com/go-ole/go-ole/oleutil"
)

// _WShell is the OLE Object for "WScript.Shell"
type _WShell struct {
	agent    *ole.IUnknown
	dispatch *ole.IDispatch
}

// _NewWShell creates OLE Object for "WScript.Shell".
func _NewWShell() (*_WShell, error) {
	agent, err := oleutil.CreateObject("WScript.Shell")
	if err != nil {
		return nil, err
	}
	dispatch, err := agent.QueryInterface(ole.IID_IDispatch)
	if err != nil {
		agent.Release()
		return nil, err
	}
	return &_WShell{agent: agent, dispatch: dispatch}, nil
}

// Close releases the OLE Object for "WScript.Shell".
func (wsh *_WShell) Close() {
	wsh.dispatch.Release()
	wsh.agent.Release()
}

// Read reads the data of shortcut file. `path` must be absolute path.
func (wsh *_WShell) Read(path string) (description string, workingdir string, targetpath string, arguments string, icon string, err error) {
	shortcut, err := oleutil.CallMethod(wsh.dispatch, "CreateShortCut", path)
	if err != nil {
		return "", "", "", "", "", err
	}
	shortcutDis := shortcut.ToIDispatch()
	defer shortcutDis.Release()
	Description, err := oleutil.GetProperty(shortcutDis, "Description")
	if err != nil {
		return "", "", "", "", "", err
	}
	workingDir, err := oleutil.GetProperty(shortcutDis, "WorkingDirectory")
	if err != nil {
		return "", "", "", "", "", err
	}
	targetPath, err := oleutil.GetProperty(shortcutDis, "TargetPath")
	if err != nil {
		return "", "", "", "", "", err
	}
	Arguments, err := oleutil.GetProperty(shortcutDis, "Arguments")
	if err != nil {
		return "", "", "", "", "", err
	}
	Icon, err := oleutil.GetProperty(shortcutDis, "IconLocation")
	if err != nil {
		return "", "", "", "", "", err
	}

	return Description.ToString(), workingDir.ToString(), targetPath.ToString(), Arguments.ToString(), Icon.ToString(), err
}

func _read(path string) (Description string, workingDir string, targetPath string, Arguments string, Icon string, err error) {
	path, err = filepath.Abs(path)
	if err != nil {
		return "", "", "", "", "", err
	}
	wsh, err := _NewWShell()
	if err != nil {
		return "", "", "", "", "", err
	}
	defer wsh.Close()

	return wsh.Read(path)
}

// Make makes a shortcut file. `to` must be absolute path.
func (wsh *_WShell) Make(to string, newDescription string, newWorkingDir string, newTarget string, newArgs string, newIcon string) error {
	shortcut, err := oleutil.CallMethod(wsh.dispatch, "CreateShortCut", to)
	if err != nil {
		return err
	}
	shortcutDis := shortcut.ToIDispatch()
	defer shortcutDis.Release()
	_ = oleutil.MustPutProperty(shortcutDis, "TargetPath", newTarget)
	if err != nil {
		return err
	}
	_, err = oleutil.PutProperty(shortcutDis, "WorkingDirectory", newWorkingDir)
	if err != nil {
		return err
	}
	_, err = oleutil.PutProperty(shortcutDis, "Arguments", newArgs)
	if err != nil {
		return err
	}
	_, err = oleutil.PutProperty(shortcutDis, "Description", newDescription)
	if err != nil {
		return err
	}
	_, err = oleutil.PutProperty(shortcutDis, "IconLocation", newIcon)
	if err != nil {
		return err
	}
	_, err = oleutil.CallMethod(shortcutDis, "Save")
	return err
}

func _make(to string, newDescription string, newWorkingDir string, newTarget string, newArgs string, newIcon string) error {
	to, err := filepath.Abs(to)
	if err != nil {
		return err
	}
	wsh, err := _NewWShell()
	if err != nil {
		return err
	}
	defer wsh.Close()

	return wsh.Make(to, newDescription, newWorkingDir, newTarget, newArgs, newIcon)
}

func CreateVBS(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("set objLink = objShell.CreateShortcut( \"")
	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
}