So I have been looking for an answer to this and have had no luck. Is it possible to send a file to the trash using JXA in Mac Automation? my simple test code looks like this:
// set startup applications that this script will use
var app = Application.currentApplication()
var finder = Application("Finder");
app.includeStandardAdditions = true
function openDocuments(droppedItems)
{
// Variables
var AllFiles = [] // array to store all files in.
for (var item of droppedItems)
{
AllFiles.push(item) // load each file into array
}
// go through each file in the list
for (var i = 0; i < AllFiles.length; i ++)
{
// move to the trash
finder.move(Path(AllFiles[i]), {
to: Path("/Users/usr/.trash"),
replacing: true
})
}
}
this is just a test I am building that should send whatever file I drop onto it to the trash, but it does not recognize .trash as a valid folder location. I have tested it with other folder and that does work so I am assuming that .trash is locked.
I think you need a reference to the trash folder via pathTo command of Standard Additions
For example, to send the currently selected file in the Finder to the Trash, something like this could work.
(() => {
const
ca = Application.currentApplication(),
sa = (ca.includeStandardAdditions = true, ca),
app = Application('Finder'),
seln = app.selection();
app.delete(seln[0])
})();
Related
I had to place videos(mp4-files) in one photoshop document. I thought it would be easier to find a solution with png/jpg, and then project it on mp4. but the fact is that photoshop saving png/jpg and mp4 in different ways. Therefore, despite the fact that there is an import solution, I have difficulties with exporting mp4 by code.
I have 2 arrays of mp4 files and each mp4 from the first array needs to be overlaid on each of the second and saved by mp4. I solved the problem by uploading a video to an open photoshop file with a simple code:
function replaceContents(newFile) {
var docRef = app.open(newFile);
return docRef;
}
function importVideos(order_number) {
var doc = app.activeDocument;
var file = new File('E:/path/' + order_number + '.mp4');
// open a new document with needed video
var docTemp = replaceContents(file);
// copy opend layer with video from new doc to my main doc
var layer = docTemp.activeLayer.duplicate(doc.layerSets.getByName(color), ElementPlacement.PLACEATEND);
// close new unnecessary doc
docTemp.close(SaveOptions.DONOTSAVECHANGES);
layer.name = order_number;
return layer;
}
Here is the code for saving videos and in doExport() doc should be saved as a video.
function Saving(color) {
var array1 = app.activeDocument.layerSets.getByName('s');
var array2 = app.activeDocument.layerSets.getByName(color);
for (i = 0; i < 5; i++) {
array1.artLayers[i].visible = true;
for (j = 0; j < 5; j++) {
array2.artLayers[i].visible = true;
doExport();
array2.artLayers[i].visible = false;
}
array1.artLayers[i].visible = false;
}
}
So a new question: how to export a video from photoshop with a code with the ability to specify the file name and the save path?
P.S. if you do this through Actions, you can't enter input parameters like the name of the saved file, it seals the Action as you did it.
If you know how to create arguments for Actions, you are welcome!
I like to write a Thunderbird AddOn that encrypts stuff. For this, I already extracted all data from the compose window. Now I have to save this into files and run a local executable for encryption. But I found no way to save the files and execute an executable on the local machine. How can I do that?
I found the File and Directory Entries API documentation, but it seems to not work. I always get undefined while trying to get the object with this code:
var filesystem = FileSystemEntry.filesystem;
console.log(filesystem); // --> undefined
At least, is there a working AddOn that I can examine to find out how this is working and maybe what permissions I have to request in the manifest.json?
NOTE: Must work cross-platform (Windows and Linux).
The answer is, that WebExtensions are currently not able to execute local files. Also, saving to some local folder on the disk is also not possible.
Instead, you need to add some WebExtension Experiment to your project and there use the legacy APIs. There you can use the IOUtils and FileUtils extensions to reach your goal:
Execute a file:
In your background JS file:
var ret = await browser.experiment.execute("/usr/bin/executable", [ "-v" ]);
In the experiment you can execute like this:
var { ExtensionCommon } = ChromeUtils.import("resource://gre/modules/ExtensionCommon.jsm");
var { FileUtils } = ChromeUtils.import("resource://gre/modules/FileUtils.jsm");
var { XPCOMUtils } = ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyGlobalGetters(this, ["IOUtils");
async execute(executable, arrParams) {
var fileExists = await IOUtils.exists(executable);
if (!fileExists) {
Services.wm.getMostRecentWindow("mail:3pane")
.alert("Executable [" + executable + "] not found!");
return false;
}
var progPath = new FileUtils.File(executable);
let process = Cc["#mozilla.org/process/util;1"].createInstance(Ci.nsIProcess);
process.init(progPath);
process.startHidden = false;
process.noShell = true;
process.run(true, arrParams, arrParams.length);
return true;
},
Save an attachment to disk:
In your backround JS file you can do like this:
var f = messenger.compose.getAttachmentFile(attachment.id)
var blob = await f.arrayBuffer();
var t = await browser.experiment.writeFileBinary(tempFile, blob);
In the experiment you can then write the file like this:
async writeFileBinary(filename, data) {
// first we need to convert the arrayBuffer to some Uint8Array
var uint8 = new Uint8Array(data);
uint8.reduce((binary, uint8) => binary + uint8.toString(2), "");
// then we can save it
var ret = await IOUtils.write(filename, uint8);
return ret;
},
IOUtils documentation:
https://searchfox.org/mozilla-central/source/dom/chrome-webidl/IOUtils.webidl
FileUtils documentation:
https://searchfox.org/mozilla-central/source/toolkit/modules/FileUtils.jsm
What I have: 50 mp3 files in a folder.
What I want to do: Create an object for every file that includes name and src.
What I don't know how to do is select and get properties from all of the files. Is it even possible? I know that you can get info from a text file via JS.
It would maybe be something like:
for (var i = 0; i < musicFolder.length; i++) {
var object = new Object (
musicFolder[i].title,
musicFolder[i].path/src
);
objectArray.push(object);
}
I would perhaps need to select an entire folder, but I dont know how to do this is JS.
Assuming that you are running this in Node.js and you only need the name and the path of the file, you can do this:
var fs = require('fs');
path = 'your path here';
const res = [];
fs.readdir(path, (err, items) => {
for (var i=0; i<items.length; i++) {
res.push({
name: items[i],
src: `${path}/${items[i]}`
});
}
console.log(res)
});
This will iterate your folder and list all the files in it. Then it will save the name of the file and its path in a object and push it to an array.
The main function file main.js has:
var nLastPingTime = 0,
nLastPingNumber = 0;
module.exports = {
compareData: function(nPingTime, nLastPingNumber){
nLastPingTime = nPingTime;
nLastPingNumber = nLastPingNumber;
}
};
Now two other files dataGenOne.js and dataGenTwo.js look something like this:
const mainDataHolder = require('./main.js');
//Gets data from some API's here
mainDataHolder.compareData(nPingTime, nLastPingNumber);
Then to start we run:
node dataGenOne.js
and
node dataGenTwo.js
The problem is that the main.js file doesn't share nLastPingTime and nLastPingNumber mutually between both sets of data.
For example when looking at nLastPingNumber, its the number from dataGenOne.js specifically and not from dataGenTwo.js at all (or vise versa).
I believe this is because they are running on two separate threads.
Is there anyway to achieve what I'm trying to do? The alternative could be to connect database or write to a file but if possible I would rather not do that.
To achieve what you are attempting to do, have two node processes communicate, you are going to have create process, lets call it spawn, that spawns both of the processes (let's call them p1 & p2) and then handles communication between p1 & p2.
So spawn would be a very simple process that would just wire the events for p1 & p2 and then forward those events to the other process. I don't have a working example of this but if you take a look here you should be able to piece that together pretty quickly.
Adam H pointed me in the right direct. The correct way to do this is in fact child_processes.
Below are the code changes:
The main function file main.js now has:
var cp = require('child_process');
var childDataOne = cp.fork('./dataGenOne.js', [process.argv[2]], { silent: true });
var childDataTwo = cp.fork('./dataGenTwo.js', [process.argv[3]], { silent: true });
childDataOne.stdout.on('data', function(data) {
console.log('parent: ' + data);
compareData(data);
//Here is where the output goes
});
childDataTwo.stdout.on('data', function(data) {
console.log('parent: ' + data);
compareData(data);
//Here is where the output goes
});
Now two other files dataGenOne.js and dataGenTwo.js changed to something like this:
process.stdin.resume();
var passingString = nPingTime + "," + nLastPingNumber;
process.stdout.write(passingString);
To start running we only have to do:
node main.js param1 param2
Instead of running dataGenOne.js and dataGenTwo.js individually.
This correctly allows the child processes to pass data back to the parent process. main.js is listening with stdout.on and the two dataGen child processes are passing the data with stdout.write.
So to avoid the complexity of storing these variables somewhere, merge the processes, but reorganize your code to make it easier to navigate.
main.js (the compare function?) - remove the variables from the top but make sure the compare function returns the latest ping values along with the comparison data i.e.
return {
data,
lastPingTime,
lastPingNumber
}
move the api stuff into separate files so you can do this
var dataSetOne = require('./dataOne');
var dataSetTwo = require('./dataTwo');
var datasets = [dataSetOne, DataSetTwo];
// initialize the values
var lastPingTime = 0;
var lastPingNumber = 0;
// loop through the datasets
for (var i = 0, len = datasets.length; i < len; i++) {
let currentDataSet = datasets[i];
const results = comparePrices(lastPingTime, lastPingumber, aAsks, aBids);
// update the ping info here
lastPingTime = results.lastPingTime;
lastPingNumber = results.lastPingNumber;
}
And if you have a lot of datasets, make an 'index.js' file that does all those requires and just returns the datasets array.
Hope that helps!
I am looking for a way of getting the process memory of any process running.
I am doing a web application. I have a server (through Nodejs), my file app.js, and an agent sending information to app.js through the server.
I would like to find a way to get the process memory of any process (in order to then sending this information to the agent) ?
Do you have any idea how I can do this ? I have searched on google but I haven't found my answer :/
Thank you
PS : I need a windows compatible solution :)
Windows
For windows, use tasklist instead of ps
In the example below, i use the ps unix program, so it's not windows compatible.
Here, the %MEM is the 4st element of each finalProcess iterations.
On Windows the %MEM is the 5th element.
var myFunction = function(processList) {
// here, your code
};
var parseProcess = function(err, process, stderr) {
var process = (process.split("\n")),
finalProcess = [];
// 1st line is a tab descriptor
// if Windows, i should start to 2
for (var i = 1; i < process.length; i++) {
finalProcess.push(cleanArray(process[i].split(" ")));
}
console.log(finalProcess);
// callback to another function
myFunction(finalProcess);
};
var getProcessList = function() {
var exec = require('child_process').exec;
exec('ps aux', parseProcess.bind(this));
}
// thx http://stackoverflow.com/questions/281264/remove-empty-elements-from-an-array-in-javascript
function cleanArray(actual){
var newArray = new Array();
for(var i = 0; i<actual.length; i++){
if (actual[i]){
newArray.push(actual[i]);
}
}
return newArray;
}
getProcessList();