Thread overview |
---|
March 06, 2016 Create Windows "shortcut" (.lnk) with D? | ||||
---|---|---|---|---|
| ||||
I'm creating a small installation script in D, but I've been having trouble getting shortcut creation to work! I'm a linux guy, so I don't know much about Windows programming... Here are the relevant bits of code I have: import core.sys.windows.basetyps, core.sys.windows.com, core.sys.windows.objbase, core.sys.windows.objidl, core.sys.windows.shlobj, core.sys.windows.windef; import std.conv, std.exception, std.file, std.format, std.path, std.stdio, std.string, std.utf, std.zip; //Couldn't find these in core.sys.windows extern(C) const GUID CLSID_ShellLink = {0x00021401, 0x0000, 0x0000, [0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46]}; extern(C) const IID IID_IShellLinkA = {0x000214EE, 0x0000, 0x0000, [0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46]}; extern(C) const IID IID_IPersistFile = {0x0000010B, 0x0000, 0x0000, [0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46]}; void main() { string programFolder, dataFolder, desktopFolder; { char[MAX_PATH] _programFolder, _dataFolder, _desktopFolder; SHGetFolderPathA(null, CSIDL_PROGRAM_FILESX86, null, 0, _programFolder.ptr); SHGetFolderPathA(null, CSIDL_LOCAL_APPDATA, null, 0, _dataFolder.ptr); SHGetFolderPathA(null, CSIDL_DESKTOPDIRECTORY, null, 0, _desktopFolder.ptr); programFolder = _programFolder.assumeUnique().ptr.fromStringz(); dataFolder = _dataFolder.assumeUnique().ptr.fromStringz(); desktopFolder = _desktopFolder.assumeUnique().ptr.fromStringz(); } auto inputFolder = buildNormalizedPath(dataFolder, "Aker/agtoolbox/input"); auto outputFolder = buildNormalizedPath(dataFolder, "Aker/agtoolbox/output"); CoInitialize(null); scope(exit) CoUninitialize(); IShellLinkA* shellLink; IPersistFile* linkFile; CoCreateInstance(&CLSID_ShellLink, null, CLSCTX_INPROC_SERVER, &IID_IShellLinkA, cast(void**)&shellLink); auto exePath = buildNormalizedPath(programFolder, "Aker/agtoolbox/agtoolbox.exe").toStringz(); shellLink.SetPath(exePath); auto arguments = format("-i %s -o %s", inputFolder, outputFolder).toStringz(); shellLink.SetArguments(arguments); auto workingDirectory = programFolder.toStringz(); shellLink.SetWorkingDirectory(workingDirectory); shellLink.QueryInterface(&IID_IPersistFile, cast(void**)&linkFile); auto linkPath = buildNormalizedPath(desktopFolder, "agtoolbox.lnk").toUTF16z(); linkFile.Save(linkPath, TRUE); } I tried sprinkling it with print statements and it crashes on shellLink.setPath(exePath); This is the full script: https://gist.github.com/miotatsu/1cc55fe29d8a8dcccab5 I found the values for the missing windows api bits from this: http://www.dsource.org/projects/tutorials/wiki/CreateLinkUsingCom I compile with: dmd agtoolbox-installer.d ole32.lib I got the ole32.lib from the dmd install Any help would be highly appreciated as I'm new to Windows programming in D and have no idea what I'm doing wrong! |
March 06, 2016 Re: Create Windows "shortcut" (.lnk) with D? | ||||
---|---|---|---|---|
| ||||
Posted in reply to 岩倉 澪 | On Sunday, 6 March 2016 at 03:13:23 UTC, 岩倉 澪 wrote: > I'm creating a small installation script in D, but I've been having trouble getting shortcut creation to work! I'm a linux guy, so I don't know much about Windows programming... > > [...] > > Any help would be highly appreciated as I'm new to Windows programming in D and have no idea what I'm doing wrong! If you don't want to mess with the Windows API then you can dynamically create a script (I do this in CE installer): void createLnk(string exeName, string displayName) { import std.process: environment, executeShell; import std.file: remove, exists; import std.random: uniform; import std.conv: to; string vbsName; do vbsName = environment.get("TEMP") ~ r"\shcsh" ~ uniform(0,int.max).to!string ~ ".vbs"; while (vbsName.exists); string vbsCode = " set WshShell = CreateObject(\"WScript.shell\") strDesktop = WshShell.SpecialFolders(\"Desktop\") set lnk = WshShell.CreateShortcut(strDesktop + \"\\%s.lnk\") lnk.TargetPath = \"%s\" lnk.Save "; File vbs = File(vbsName, "w"); vbs.writefln(vbsCode, displayName, exeName); vbs.close; executeShell(vbsName); vbsName.remove; } |
March 06, 2016 Re: Create Windows "shortcut" (.lnk) with D? | ||||
---|---|---|---|---|
| ||||
Posted in reply to BBasile | On Sunday, 6 March 2016 at 05:00:55 UTC, BBasile wrote:
> If you don't want to mess with the Windows API then you can dynamically create a script (I do this in CE installer):
This might be an option but I'd prefer to use the Windows API directly. I don't know vb script and maintaining such a script inline would just add cognitive overhead I think.
If I can't get it working with the Windows API; I'll probably have to do it this way though. Thanks for the suggestion!
|
March 06, 2016 Re: Create Windows "shortcut" (.lnk) with D? | ||||
---|---|---|---|---|
| ||||
Posted in reply to 岩倉 澪 | On Sunday, 6 March 2016 at 03:13:23 UTC, 岩倉 澪 wrote:
> IShellLinkA* shellLink;
> IPersistFile* linkFile;
>
> Any help would be highly appreciated as I'm new to Windows programming in D and have no idea what I'm doing wrong!
In D, interfaces are references, so it should be:
IShellLinkA shellLink;
IPersistFile linkFile;
|
March 06, 2016 Re: Create Windows "shortcut" (.lnk) with D? | ||||
---|---|---|---|---|
| ||||
Posted in reply to John | On Sunday, 6 March 2016 at 11:00:35 UTC, John wrote:
> On Sunday, 6 March 2016 at 03:13:23 UTC, 岩倉 澪 wrote:
>> IShellLinkA* shellLink;
>> IPersistFile* linkFile;
>>
>> Any help would be highly appreciated as I'm new to Windows programming in D and have no idea what I'm doing wrong!
>
> In D, interfaces are references, so it should be:
>
> IShellLinkA shellLink;
> IPersistFile linkFile;
That's exactly what the problem was, thank you!!
|
March 07, 2016 Re: Create Windows "shortcut" (.lnk) with D? | ||||
---|---|---|---|---|
| ||||
Posted in reply to 岩倉 澪 | On Sunday, 6 March 2016 at 20:13:39 UTC, 岩倉 澪 wrote: > On Sunday, 6 March 2016 at 11:00:35 UTC, John wrote: >> On Sunday, 6 March 2016 at 03:13:23 UTC, 岩倉 澪 wrote: >>> IShellLinkA* shellLink; >>> IPersistFile* linkFile; >>> >>> Any help would be highly appreciated as I'm new to Windows programming in D and have no idea what I'm doing wrong! >> >> In D, interfaces are references, so it should be: >> >> IShellLinkA shellLink; >> IPersistFile linkFile; > > That's exactly what the problem was, thank you!! You can use official specs to recreate binary file: https://msdn.microsoft.com/en-us/library/dd871305.aspx Ok, not the fastest way. :) |
Copyright © 1999-2021 by the D Language Foundation