Skip to content

Commit

Permalink
QScripts v1.1.9
Browse files Browse the repository at this point in the history
+ Added package dependency support
- fixed: make_abs_path() was broken
- added support for ';' and '#' comment lines in the dependency file
- updated documentation
  • Loading branch information
0xeb committed Dec 27, 2021
1 parent cf85c1f commit dd82618
Show file tree
Hide file tree
Showing 9 changed files with 250 additions and 101 deletions.
24 changes: 16 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# What is QScripts?

`QScripts` is productivity tool and an alternative to IDA's "Recent scripts" (Alt-F9) and "Execute Scripts" (Shift-F2) facilities. `QScripts` allows you to develop and run any supported scripting language (\*.py; \*.idc, etc.) from the comfort of your own favorite text editor as soon as you save the active script or any of its dependencies.
`QScripts` is productivity tool and an alternative to IDA's "Recent scripts" (Alt-F9) and "Execute Scripts" (Shift-F2) facilities. `QScripts` allows you to develop and run any supported scripting language (\*.py; \*.idc, etc.) from the comfort of your own favorite text editor as soon as you save the active script, the trigger file or any of its dependencies.

![Quick introduction](docs/_resources/qscripts-vid-1.gif)

Expand All @@ -22,16 +22,17 @@ There are few options that can be configured in `QScripts`. Just press `Ctrl+E`
* Show file name when execution: display the name of the file that is automatically executed
* Execute the unload script function: A special function, if defined, called `__quick_unload_script` will be invoked before reloading the script. This gives your script a chance to do some cleanup (for example to unregister some hotkeys)
* Script monitor interval: controls the refresh rate of the script change monitor. Ideally 500ms is a good amount of time to pick up script changes.
* Allow QScripts execution to be undo-able: The executed script's side effects can be reverted with IDA's Undo

## Executing a script without activating it

It is possible to execute a script from `QScripts` without having to activate it. Just press `Shift-ENTER` on a script and it will be executed.

## Working with dependencies

It is possible to instruct `QScripts` to re-execute the active script if any of its dependent scripts are also modified. To use the automatic dependency system, please create a file named exactly like your active script but with the additional `.deps.qscripts` extension. In that file you put your dependent scripts full path.
It is possible to instruct `QScripts` to re-execute the active script if any of its dependent scripts are also modified. To use the automatic dependency system, please create a file named exactly like your active script but with the additional `.deps.qscripts` extension. In that file you put your dependent scripts path.

When using Python, it would be helpful if we can also `reload` the changed dependent script from the active script automatically. To do that, simply add the directive line `/reload` along with the desired reload syntax. For example, here's a complete `.deps.qscripts` file with a `reload` directive (for Python 2.x):
When using Python, it would be helpful if we can also [reload](https://docs.python.org/3/library/importlib.html#importlib.reload) the changed dependent script from the active script automatically. To do that, simply add the directive line `/reload` along with the desired reload syntax. For example, here's a complete `.deps.qscripts` file with a `reload` directive (for Python 2.x):

```
/reload reload($basename$)
Expand All @@ -43,9 +44,9 @@ t3.py
And for Python 3.x:

```
/reload import imp;imp.reload($basename$);
/reload import importlib;importlib.reload($basename$);
t2.py
// This is a comment
# This is a comment
t3.py
```

Expand All @@ -55,13 +56,18 @@ So what happens now if we have an active file `t1.py` with the dependency file a
2. If the dependency index file `t1.py.deps.qscripts` is changed, then your new dependencies will be reloaded and the active script will be executed again.
3. If any dependency script file has changed, then the active script will re-execute. If you had a `reload` directive set up, then the modified dependency files will also be reloaded.

Please note that if each dependent script file has its own dependency index file, then QScripts will recursively make all the linked dependencies as part of the active script dependencies.
Please note that if each dependent script file has its own dependency index file, then QScripts will recursively make all the linked dependencies as part of the active script dependencies. In this case, the directives (such as `reload`) are ignored.

See also:
* [Simple dependency example](test_scripts/dependency-test/README.md)
* [Package dependency example](test_scripts/pkg-dependency/README.md)

### Special variables in the dependency index file

* `$basename$`: This variable is expanded to the base name of the current dependency line
* `$env:EnvVariableName$`: `EnvVariableName` is expanded to its environment variable value if it exists or left unexpanded otherwise

* `$pkgbase$`: Specify a package base directory. Can be used as part of a dependency file path.
* `$pkgmodname$`: This is mainly used inside the `reload` directive. It replaces the path seperators with dots (which works nicely as a fully qualified module name). Please see the [package dependency](test_scripts/pkg-dependency/README.md) example file.

## Using QScripts with trigger files

Expand All @@ -72,13 +78,14 @@ One way to achieve a custom trigger is by using the `/triggerfile` directive:
/reload import imp;imp.reload($basename$);
/triggerfile createme.tmp
// Just some dependencies:
; Just some dependencies:
dep.py
```

This tells QScripts to wait until the trigger file `createme.tmp` is created before executing your script. Now, any time you want to invoke QScripts, just create the trigger file. The moment QScripts finds the trigger file, it deletes it and then always executes your active script (and reloads dependencies when applicable).

## Using QScripts programmatically

It is possible to invoke `QScripts` from a script. For instance, in IDAPython, you can execute the last selected script with:

```python
Expand All @@ -92,6 +99,7 @@ If the script monitor is deactivated, you can programmatically activate it by ru
# Installation

QScripts is written in C++ with IDA's SDK and therefore it should be deployed like a regular plugin. Copy the plugin binaries to either of those locations:

* `<IDA_install_folder>/plugins`
* `%APPDATA%\Hex-Rays/plugins`

Expand Down
Loading

0 comments on commit dd82618

Please sign in to comment.