Post by Brandon Parker on Jul 26, 2020 20:16:56 GMT -5
Well, you can definitely do it this way for sure if you are using Windows. You may have to tell Windows 10 to keep using the standard scripting app the first time (uuggghhhh...annoying as usual). You can strip this down to bare-bones if you want to; I just post stuff as I have set it up for my programs in the past.
Global False : False = 0 Global True : True = 0
Dim Info$(0, 0)
lnkLocation$ = "" 'Location to create the .lnk file at lnkName$ = "" 'Name of the .lnk file to be created exeLocation$ = "" 'Location of the .exe file you want the .lnk file to point to lnkIconLoc$ = "" 'Location of the icon you want the .lnk file to use (typically just point to the .exe file as well) lnkDescription$ = "" 'Description to use in the .lnk file internal description exeWorkDir$ = "" 'Working directory of the .exe file pointed to above result = CreateLink(lnkLocation$, lnkName$, exeLocation$, lnkIconLoc$, lnkDescription$, exeWorkDir$) End
Function OpenFile$(filepath$, InOut$, data$) On Error GoTo [Error] Select Case InOut$ Case "BinaryInput" Open filepath$ For Binary As #OpenFile fileOpened = True OpenFile$ = Trim$(Input$(#OpenFile, LOF(#OpenFile))) Case "Input" Open filepath$ For Input As #OpenFile fileOpened = True OpenFile$ = Trim$(Input$(#OpenFile, LOF(#OpenFile))) Case "BinaryOutput" Open filepath$ For Binary As #OpenFile fileOpened = True Case "Output" Open filepath$ For Output As #OpenFile fileOpened = True Case "BinaryAppend" Open filepath$ For Binary As #OpenFile fileOpened = True Case "Append" Open filepath$ For Append As #OpenFile fileOpened = True End Select If (Instr(InOut$, "Output") > False) Or (Instr(InOut$, "Append") > False) Then #OpenFile data$; OpenFile$ = str$(True) End If Close #OpenFile Exit Function [Error] If (fileOpened = True) Then Close #OpenFile End Function
Post by Fabio Siciliano on Jul 27, 2020 9:50:32 GMT -5
Hi Brandon, cool, thank you. Yes, you're right, the user may have to tell Windows 10 to keep using the standard scripting app the first time (and frankly I hate it!)... if it was some kind of trick to avoid it at all, it could be great! But I still wonder if there is a quite badly undocumented way to do it directly from Windows API, without using any scripting language, I mean throughout native Windows API only. I am very disappointed by the fact that sometimes Windows does not offer straightforward ways to do some basic stuff... it seems, sometimes, that folks made things difficult on purpose.
You'd obviously use each successive deeper-level directory name rather than a synthesized one.
Note code will error out if the directories already exist so you may want to add if_dir_exists check.
You specify spaces in your filename/path. This is usually permissible if you 'quote' the string with surrounding chr$( 34) quotes- but it wouldn't work for me on my set up. ( Linuz/Wine) Underscore symbols look good and work without problems.
I definitely understand what you mean. This is just how I have done it in the past on Windows. I think I looked into it and it was going to be more trouble or possibly impossible with LB back when I came up with this solution.
Windows 7 Home Premium 64-bit Intel(R) Quad Core(TM) i5 CPU M 430 @ 2.27GHz 4GB DDR3 RAM
Post by Chris Iverson on Jul 28, 2020 23:55:42 GMT -5
Here's some sample code written by a user who came up with a very crafty solution to be able to use the COM API in LB(COM is necessary to interface with some windows shell APIs, including the ones that handle link/shortcut generation and resolution).
' Create and store a shortcut, version 1.0, 03-Nov-2013 ' Demonstrates calling COM methods from Liberty BASIC! ' (C) Richard Russell 2013
call shortcut SpecialFolder$(0) + "\Test Shortcut.lnk", _ StartupDir$ + "\lbpro.exe", _ DefaultDir$, _ "Test shortcut created by Liberty BASIC" end
' Use the IShellLink and IPersistFile COM interfaces to ' create and store a shortcut to the specified object. ' LnkFile$ - the path/filename of the shortcut (.LNK) ' Target$ - the object for which to create a shortcut ' StartIn$ - the working directory to start in ' Comment$ - the description of the shortcut sub shortcut LnkFile$, Target$, StartIn$, Comment$
open "OLE32.DLL" for DLL as #ole32 calldll #ole32, "CoInitialize", 0 as long, r as long
struct clsid, a as long, b as long, c as long, d as long struct iidsl, a as long, b as long, c as long, d as long struct iidpf, a as long, b as long, c as long, d as long
' Get a pointer to the IShellLink interface: CLSCTX.INPROC.SERVER = 1 struct temp, v as long calldll #ole32, "CoCreateInstance", clsid as struct, 0 as long, _ CLSCTX.INPROC.SERVER as long, iidsl as struct, _ temp as struct, r as long psl = temp.v.struct if psl = 0 then notice "Cannot create IShellLink interface" : end
' Set the target object, working directory and description: struct parm, psz as ptr parm.psz.struct = Target$ result = CallMethod(psl, 20, parm.struct) ' IShellLink::SetPath parm.psz.struct = StartIn$ result = CallMethod(psl, 9, parm.struct) ' IShellLink::SetWorkingDirectory parm.psz.struct = Comment$ result = CallMethod(psl, 7, parm.struct) ' IShellLink::SetDescription
' Query IShellLink for the IPersistFile interface: struct temp, v as long struct parm, iid as struct, ppv as struct parm.iid.struct = iidpf.struct parm.ppv.struct = temp.struct result = CallMethod(psl, 0, parm.struct) ' IShellLink::QueryInterface temp.struct = parm.ppv.struct ppf = temp.v.struct IF ppf = 0 then notice "Cannot create IPersistFile interface" : end
' Convert the path/filename string to Unicode: wsz$ = space$(2*len(LnkFile$) + 2) n = len(wsz$) / 2 calldll #kernel32, "MultiByteToWideChar", 0 as long, 0 as long, _ LnkFile$ as ptr, -1 as long, wsz$ as ptr, _ n as long, r as long
' Save the shortcut: struct parm, pszFilename as ptr, fRemember as long parm.pszFilename.struct = wsz$ parm.fRemember.struct = 1 result = CallMethod(ppf, 6, parm.struct) ' IPersistFile::Save
' Tidy up: result = CallMethod(ppf, 2, "") ' IPersistFile::Release result = CallMethod(psl, 2, "") ' IShellLink::Release calldll #ole32, "CoUninitialize", r as void close #ole32 end sub
' Call a COM method: ' object - a pointer to the COM object interface ' method - the zero-based index of the method to be called ' parm$ - a structure containing the parameters to be passed function CallMethod(object, method, parm$) code$ = chr$(139)+"D$"+chr$(4)+chr$(139)+"T$"+chr$(8)+chr$(139)+"L$" _ + chr$(16)+"VW"+chr$(139)+"t$"+chr$(20)+chr$(43)+chr$(225)+chr$(139) _ + chr$(252)+chr$(243)+chr$(164)+chr$(80)+chr$(139)+chr$(0)+chr$(255) _ + chr$(20)+chr$(144)+chr$(95)+chr$(94)+chr$(194)+chr$(16)+chr$(0)
p$ = parm$ n = len(p$) calldll #user32, "CallWindowProcA", code$ as ptr, object as long, _ method as long, p$ as ptr, n as long, CallMethod as long end function
' Get the location of a Special Folder: function SpecialFolder$(csidl) struct idl, pp as long calldll #shell32, "SHGetSpecialFolderLocation", _ 0 as long, csidl as long, idl as struct, r as long if r = 0 then path$ = space$(_MAX_PATH) ppidl = idl.pp.struct calldll #shell32, "SHGetPathFromIDListA", _ ppidl as long, path$ as ptr, r as long SpecialFolder$ = trim$(path$) open "OLE32.DLL" for DLL as #ole32 calldll #ole32, "CoTaskMemFree", ppidl as long, _ r as long close #ole32 end if end function