Loading icon from kit using twapi - tcl

I have a tcl script named main.tcl in a folder called App. One of the lines in the script uses a command from the twapi module (that line is actually in a proc and I'm trying to minimize the app to system tray when a user closes the app through the 'X' window button):
package require twapi
# ... code here
set hand [twapi::load_icon_from_file tclkit.ico]
# ... code here
The file tclkit.ico is in the same directory as the script (i.e. in the folder App).
When main.tcl is run through wish, the script works without any issues, but after wrapping it into an executable through command line,
> tclkit sdx.kit wrap App -runtime tclsh863.exe
the executable raises an error, notably that the icon file could not be found:
The system cannot find the file specified.
The system cannot find the file specified.
while executing
"LoadImage $hmod $path $type $opts(width) $opts(height) $flags"
(procedure "twapi::_load_image" line 18)
invoked from within
"twapi::load_icon_from_file tclkit.ico"
(procedure "min_to_tray" line 2)
invoked from within
"min_to_tray"
(command for "WM_DELETE_WINDOW" window manager protocol)
The current workaround right now is to have a copy of the tclkit.ico file in the same directory as the .exe but I want to avoid that as much as possible and only have the standalone .exe file. I tried using the full path with:
set hand [twapi::load_icon_from_file [file join [pwd] App.exe tclkit.ico]]
which normally works when I want to read a file (.txt, .png files, etc.) within the .exe, without success.
So basically, is there a way to enable the .exe to load the .ico file from within itself or another workaround that will not require some dependence on a file outside the .exe app?

The core issue is that the relevant Windows API actually takes a filename, and not something that it's more easy to wrap loading-from-archive around (such as a buffer). This means that you have to copy the file out of the archive somewhere and then pass that name to the system call. This is in fact what Tcl does internally for load when it's pulling the DLL from a source that isn't directly visible to the OS; it doesn't do it automatically for TWAPI though, as that library takes the philosophical position of being just a thin wrapper and letting the caller handle the consequences (which does mean you can easily do more tricks, provided you're inventive).
I suggest copying the file to a temporary file somewhere (i.e., the standard location for these things; Tcl 8.6 has file tempfile to help with this sort of trick) and then passing the full filename into the TWAPI call. I think everywhere in the Windows API that you could pass a simple filename in, you can also pass a full filename. (That's actually very convenient…)

Related

How to make an Octave path root folder for all subfolders

I have a folder for Octave M-files in C:\\Users\Dropbox\Octave, under which are various subfolders by function categories (normal distribution, chisq...). I just started making those subfolders and they will keep changing (adding, removing, reshuffling) as time goes on.
I would just like to set that folder as root and have Octave search for functions recursively there, just like you set a classpath in Java and JVM searches all folders there.
I used addpath(genpath('C:\\Users\Dropbox\Octave')), but the paths generated are then fixed, not reflecting subsequent subfolder changes.
Shall I add addpath(genpath('C:\\Users\Dropbox\Octave')) to the .octaverc file?
I think there is some confusion here. There are several ways to interact with the path, but for the most part these do not result in permanent changes, unless you save this somehow.
Simply adding a path for an existing octave session will not result in any permanent changes to the usual path that octave initialises at startup. Therefore when you say:
I used addpath(genpath('C:\Users\Dropbox\Octave')), but the paths generated are then fixed, not reflecting subsequent subfolder changes.
this makes no sense, because as soon as you exit your octave session, those added paths should have been gone altogether, and not appear in later octave sessions.
It is more likely that at some point you added these paths, and then used the savepath command, which resulted in your custom paths being added to your .octaverc file.
If that is the case, then yes, you can expect that octave will not "update" what was written in your .octaverc file, unless you call savepath again with an updated path definition.
If you would like the addpath(genpath('C:\Users\Dropbox\Octave')) command you mentioned to be called every time octave starts, so that the current/updated directory structure is loaded, then yes, the best way to do it would be to add that command to your .octaverc file. Make sure you remove the lines in your .octaverc that refer to the previous changes made by savepath. Note that there may be several levels of octaverc files that you need to check (see the relevant page in the manual)
Alternatively, you could simply make sure that this line appears in every script you want to call which intends to make use of those files.
While you may consider this last approach tedious, programmatically it is the most recommended one, since it makes dependencies clear in your code. This is especially important if you ever plan to share your code (and doubly so if you'd like it to be matlab compatible).
PS. All the above mostly applies to matlab too, with the exception that a) matlab's savepath saves path information in a file called pathdef.m, rather than directly in your startup files, and b) matlab uses startup.m instead of .octaverc as startup files. Also, if you don't care about doing this programmatically, matlab provides pathtool, which is a graphical interface for adding / saving directories to the matlab path.

How to use a relative program path in a PhpStorm file watcher

In PhpStorm (as well as other JetBrains IDEs, I'm sure), I'm setting up a File Watcher. In the Watcher Settings section, it asks me to specify the path to the program to be executed.
I want to use the executable file within the node_modules/.bin directory of my project. I don't want it installed globally because I may have other projects that use the same program, but may require a different version.
I could simply specify the absolute path to my project's node_modules/.bin directory, but then if I move the project, the file watcher will break.
In the Arguments and Output paths to refresh fields just below the Program field, it allows you to insert a macro, like $Projectpath$. This is exactly what I need, but it doesn't look like the Program field allows that.
Is there a way to specify a relative path for the Program field?
Here is a screenshot of the File Watcher setup window:
I could simply specify the absolute path to my project's node_modules/.bin directory, but then if I move the project, the file watcher will break.
That's not true -- at very least it does not break anything here -- got 3 projects that use local stuff.
Is there a way to specify a relative path for the Program field?
Sure. Use full path to the program :)
Internally (in config file) it will be stored using $PROJECT_DIR$ (AFAIK) special macro/variable but in actual field (in that dialog window) you will always see full path. Such conversion is done automatically.
You can read a bit more here (in comments): https://youtrack.jetbrains.com/issue/WEB-24376
If you are using the same project on different computers ... where path to the same program will be different but outside of the project (e.g. stored inside user-specific folder and user logins/names are different on such computers) ... you could use Path Variables functionality (Settings/Preferences | Appearance & Behavior | Path Variables) and specify the same variable on all of such computers that would point to correct path on that computer. IDE will automatically use that path variable to store the path.
So .. on one computer MY_TOOL_PATH will be pointing to /Users/Joe/MyTool and on another it could be /Users/Sam/AnotherTool.

Selenium ide to locate a file and store its path info from any computer

currently in my test scripts for automated file upload to browser, the paths are already defined in the value column
command type
target //input[#type='file']
value /Users/.../.../.../filename.extension
in such cases, this script is unable to run on other computers because the path would be different.
my question will be is
is there a way to locate the file in a general folder (for example file is downloaded and in the "download" folder), by using selenium ide can we get the path of the file (/Users/.../downloads/filename.extension)
store the path of the file with its extension into a notepad which i will be using it for multiple test of file uploads later on.
right now if my colleague needs to run the script from his computer, he have to manually change the value to his path.
You could use a suite file that contains a "setup" file to only change the file name in 1 place and the variable is shared across tests in the suite. You could also select an agreed up on place to store the files: c:\test_info\image.jpg.
Or you can make the file available by URL & not local, Unfortunately javascript prevents that for security: How to get the current file path in javascript
Unfortunately I can't think of any other good way unless you all have the same path in a home directory and could do something like ~/test_dir/photo.jpg

Wrapped Tcl script stops working when moved

I'm new to Tcl and I have a script that is wrapped using freewrapTCLSH.exe
At first, when started, the program complained about not finding a package
I edited the line the seems to "include" it to
lappend auto_path ../../lib/crc
This worked fine and the .exe started without issues. But then I moved the exe to another folder and it started complaining again. I thought that once the exe was created everything would be done. But it doesn't seem to handle this very well.
At first the entire path to the lib was hard coded into the script and then everything worked fine. But since we can't rely on the exe always being built in the same folder this had to be changed.
Any ideas on how to get around this annoying problem?
../../lib/crc is interpreted using the current working directory each time a package is searched. Having this thing it your ::auto_path is almost always not what you want.
I use [file dirname [info script]] to get a directory of currently sourced Tcl file, adding a relative path to some lib/crc with file join, ensuring to get a full pathname with file normalize. The result of file normalize is what I add to ::auto_path (or remember for future use in some other way):
lappend ::auto_path [file normalize [file join [file dirname [info script]] ../mylib]]
It might be obvious, but still: info script returns the path to file currently being sources, not the path somehow remembered when the file containing a call to it was sourced. If you want to get the current script location, ensure it happens at right time (e.g. do it at top level).
You should deliver the required package (and the dependencies of that package) into your exe.
usually this only involves copying the directory of the required packages to the lib folder in your vfs.

Zip the contents of a folder in SSIS

I am trying to zip the contents of a Folder in SSIS, there are files and folders in the source folder and I need to zip them all individually. I can get the files to zip fine my problem is the folders.
I have to use 7.zip to create the zipped packages.
Can anyone point me to a good tutorial. I haven't been able to implement any of the samples that I have found.
Thanks
This is how I have configured it.
Its easy to configure but the trick is in constructing the Arguments. Though you see the Arguments as static in the screenshot, its actually coming from a variable and that variable is set in the Arguments expression of Execute Process Task.
I presume you will have this Execute Process task in a For Each File Ennumerator with Traverse SubFolders checked.
Once you have this basic setup in place, all you need to do is work on building the arguments to do the zipping, how you want them. A good place to find all the command line arguments is here.
Finally, the only issue I ran into was not providing a working directory in the command line arguments for 7zip. The package used to run fine on my dev environment but used to fail when running on the server via a SQL job. This was because 7zip didn't have access to the 'Temp' folder on the SQL Server, which it uses by default as the 'working directory'. I got round this problem by specifying the 'working directory as follows at the end of the command line arguments, using the -ws switch:
For e.g:
a -t7z DestinationFile.7z SourceFile -wS:YourTempDirectoryToWhichTheSQLAgentHasRights