Copy link to clipboard
Copied
Inspiration for the following two scripts came from these ideas/feature requests:
The scripts save and close all open files, logging their locations into a text file. Once you have finished with the unexpected task that interrupted the previous session, you can then run the second restore script to reopen all of the files from the previous session and continue. The active document from the previous session will be active when the docs are re-opened.
Window sizes and positions, pan, zoom levels and other properties are not restored, the docs will simply re-open "as is".
/*
Photoshop Session - 1 of 2 - Save.jsx
v1.0 - 11th November 2023, Stephen Marsh
https://community.adobe.com/t5/photoshop-ecosystem-ideas/please-session-saving/idc-p/14169472
https://community.adobe.com/t5/photoshop-ecosystem-ideas/restore-previous-session/idc-p/14189928
*/
#target photoshop
try {
if (app.documents.length > 0) {
if (confirm("Log all open session files and save close all documents?", false)) {
var logFile = new File(app.preferencesFolder + "/" + "Photoshop Session Document Paths.log");
if (logFile.exists)
logFile.remove();
//alert(logFile.fsName);
var actDocLogFile = new File(app.preferencesFolder + "/" + "Photoshop Session Active Document.log");
if (actDocLogFile.exists)
actDocLogFile.remove();
writeActiveDocToLog();
//alert(actDocLogFile.fsName);
while (app.documents.length > 0) {
app.activeDocument = app.documents[0]; // Force the write to log from left to right document tabs, comment out to reverse the open order
try {
activeDocument.path;
if (ExternalObject.AdobeXMPScript === undefined) ExternalObject.AdobeXMPScript = new ExternalObject('lib:AdobeXMPScript');
var xmp = new XMPMeta(activeDocument.xmpMetadata.rawData);
var crsMeta = xmp.getProperty(XMPConst.NS_CAMERA_RAW, "Version");
if ((/\.(RAF|CR2|CR3|NRW|ERF|RW2|NEF|ARW|RWZ|EIP|DNG|BAY|DCR|RAW|CRW|3FR|K25|KC2|MEF|DNG|CS1|ORF|ARI|SR2|MOS|CR3|GPR|SRW|MFW|FFF|SRF|KDC|MRW|J6I|RWL|X3F|PEF|IIQ|CXI|NKSC|MDC)$/i).test(activeDocument.fullName) === true && crsMeta !== undefined) {
saveAsDefault();
writePathToLog();
activeDocument.close(SaveOptions.DONOTSAVECHANGES);
} else if (activeDocument.path) {
writePathToLog();
activeDocument.close(SaveOptions.SAVECHANGES);
}
} catch (e) {
executeAction(stringIDToTypeID("save"), undefined, DialogModes.ALL);
writePathToLog();
activeDocument.close(SaveOptions.SAVECHANGES);
}
}
}
} else {
alert('A document must be open when running this script!');
}
} catch (e) {}
///// FUNCTIONS /////
function writePathToLog() {
var os = $.os.toLowerCase().indexOf("mac") >= 0 ? "mac" : "windows";
if (os === "mac") {
var logFileLF = "Unix";
} else {
logFileLF = "Windows";
}
logFile.open("a");
logFile.encoding = "UTF-8";
logFile.lineFeed = logFileLF;
logFile.writeln(activeDocument.path + "/" + activeDocument.name);
logFile.close();
}
function writeActiveDocToLog() {
var os = $.os.toLowerCase().indexOf("mac") >= 0 ? "mac" : "windows";
if (os === "mac") {
var logActDocLogLF = "Unix";
} else {
logActDocLogLF = "Windows";
}
actDocLogFile.open("a");
actDocLogFile.encoding = "UTF-8";
actDocLogFile.lineFeed = logActDocLogLF;
actDocLogFile.writeln(activeDocument.name);
actDocLogFile.close();
}
function saveAsDefault() {
function s2t(s) {
return app.stringIDToTypeID(s);
}
var descriptor = new ActionDescriptor();
descriptor.putObject(s2t("as"), s2t("photoshop35Format"), descriptor);
descriptor.putPath(s2t("in"), new File("~/Desktop" + "/" + activeDocument.name));
descriptor.putBoolean(s2t("lowerCase"), true);
executeAction(s2t("save"), descriptor, DialogModes.ALL);
}
/*
Photoshop Session - 2 of 2 - Restore.jsx
v1.0 - 11th November 2023, Stephen Marsh
https://community.adobe.com/t5/photoshop-ecosystem-ideas/please-session-saving/idc-p/14169472
https://community.adobe.com/t5/photoshop-ecosystem-ideas/restore-previous-session/idc-p/14189928
*/
#target photoshop
try {
var theLogFilePath = readPref(app.preferencesFolder + "/" + "Photoshop Session Document Paths.log");
if (File(app.preferencesFolder + "/" + "Photoshop Session Document Paths.log").exists && File(app.preferencesFolder + "/" + "Photoshop Session Document Paths.log").length > 0) {
//alert(app.preferencesFolder.fsName + "/" + "Photoshop Session Document Paths.log");
for (var m = 0; m < theLogFilePath.length; m++) {
open(File(theLogFilePath[m]));
}
} else {
alert("The Desktop log file 'Photoshop Session Document Paths.log' doesn't exist or is empty!");
}
} catch (e) { }
//app.runMenuItem(stringIDToTypeID('consolidateAllTabs'));
//app.runMenuItem(stringIDToTypeID('floatAllWindows'));
//app.runMenuItem(stringIDToTypeID('tileVertically'));
//app.runMenuItem(stringIDToTypeID('tileHorizontally'));
try {
if (File(app.preferencesFolder + "/" + "Photoshop Session Active Document.log").exists && File(app.preferencesFolder + "/" + "Photoshop Session Active Document.log").length > 0) {
//alert(app.preferencesFolder + "/" + "Photoshop Session Active Document.log");
var theActDocLogFile = new File(app.preferencesFolder + "/" + "Photoshop Session Active Document.log");
theActDocLogFile.open('r');
var theActiveDocName = theActDocLogFile.readln(1);
theActDocLogFile.close();
activeDocument = documents.getByName(theActiveDocName);
} else {
alert("The Desktop log file 'Photoshop Session Active Document.log' doesn't exist or is empty!");
}
} catch (e) {}
function readPref(thePath) {
/*
Based on:
https://community.adobe.com/t5/photoshop-ecosystem-discussions/script-to-open-multiple-docs-from-a-text-file/td-p/14148443
by c.pfaffenbichler
*/
if (File(thePath).exists === true) {
var logFile = File(thePath);
logFile.open("r");
logFile.encoding = "UTF-8";
var theString = new String;
for (var m = 0; m < logFile.length; m++) {
theString = theString.concat(logFile.readch());
}
logFile.close();
return theString.split("\n");
//return String(theString);
}
}
https://prepression.blogspot.com/2017/11/downloading-and-installing-adobe-scripts.html
Copy link to clipboard
Copied
This is a game changer - thank you so much for taking time to write this!
Copy link to clipboard
Copied
This is a game changer - thank you so much for taking time to write this!
By @kimikalfoto
Thank you, I'm glad that you found this useful and took the time to comment.
Copy link to clipboard
Copied
I have combined both session scripts into a single script with an interface!
* Preserves Document State: Automatically saves and closes all open documents.
* Restores Active Documents: The previously active document regains focus when the session is restored.
* Session Overview: Optionally view the list of documents from the saved session.
* Permanent Session Saving: Save and restore sessions even after quitting Photoshop.
* Multiple Version Support: Each session is linked to the Photoshop version used when the script is run. This way you can keep projects separate when using version-specific features.
At this time, only one session is saved. Looking at how Krita works with sessions, a future version may offer the ability to save and restore multiple sessions...
/*
Save & Restore Photoshop Session scriptUI GUI.jsx
v1.0 - 27th October 2024, Stephen Marsh
https://community.adobe.com/t5/photoshop-ecosystem-discussions/scripts-to-save-amp-restore-photoshop-sessions/m-p/14239969
Inspiration from:
https://community.adobe.com/t5/photoshop-ecosystem-ideas/please-session-saving/idc-p/14169472
https://community.adobe.com/t5/photoshop-ecosystem-ideas/restore-previous-session/idc-p/14189928
*/
#target photoshop
// Set the main UI window
var dlg = new Window("dialog", "Photoshop Session Manager (v1.0)");
dlg.orientation = "column";
dlg.alignChildren = ["fill", "top"];
dlg.preferredSize.width = 425;
// Radio buttons to select which script to run
var radioGroup = dlg.add("panel", undefined, "Save or Restore Session Documents");
radioGroup.orientation = "row";
radioGroup.alignChildren = ["left", "center"];
var saveRadio = radioGroup.add("radiobutton", undefined, "Save Current Session");
var restoreRadio = radioGroup.add("radiobutton", undefined, "Restore Saved Session");
saveRadio.value = true;
// Add checkbox for viewing saved sessions
var viewSessionsCheckbox = dlg.add("checkbox", undefined, "View Saved Session Document List");
viewSessionsCheckbox.enabled = false; // Initially disabled since Save Session is selected by default
// Update checkbox enabled state when radio buttons change
saveRadio.onClick = function () {
viewSessionsCheckbox.enabled = false;
viewSessionsCheckbox.value = false;
};
restoreRadio.onClick = function () {
viewSessionsCheckbox.enabled = true;
};
// Create button group
var buttonGroup = dlg.add("group");
buttonGroup.orientation = "row";
buttonGroup.alignChildren = ["right", "center"];
var cancelButton = buttonGroup.add("button", undefined, "Cancel");
var okButton = buttonGroup.add("button", undefined, "OK", { name: "ok" });
cancelButton.onClick = function () {
dlg.close();
};
okButton.onClick = function () {
if (saveRadio.value) {
// Check for open documents before proceeding with save
if (app.documents.length === 0) {
alert('A document must be open when running this script!');
return;
}
saveSession();
} else if (restoreRadio.value) {
if (viewSessionsCheckbox.value) {
showRestoreSessionWindow(); // Open the restore session window
} else {
restoreSession(); // Direct restore without showing the list
}
}
dlg.close();
};
// Function to show the restore session window
function showRestoreSessionWindow() {
// ~/Library/Preferences/Adobe Photoshop 2024 Settings/
var logFilePath = new File(app.preferencesFolder + "/" + "Photoshop Session Document Paths.log");
if (logFilePath.exists && logFilePath.length > 0) {
var logContents = readPref(logFilePath);
// Create a new window to display the log contents
var restoreWindow = new Window("dialog", "Saved Session List");
restoreWindow.orientation = "column";
restoreWindow.alignChildren = ["fill", "top"];
restoreWindow.preferredSize.width = 375;
// Add a static text area to show log contents
var logTextArea = restoreWindow.add("edittext", undefined, logContents.join("\n"), { multiline: true, scrollable: true });
logTextArea.preferredSize.height = 200;
logTextArea.enabled = false; // Make it read-only
// Create a button group for Restore and Cancel
var restoreButtonGroup = restoreWindow.add("group");
restoreButtonGroup.orientation = "row";
restoreButtonGroup.alignChildren = ["right", "center"];
var restoreCancelButton = restoreButtonGroup.add("button", undefined, "Cancel");
var restoreButton = restoreButtonGroup.add("button", undefined, "Restore", { name: "restore" });
restoreCancelButton.onClick = function () {
restoreWindow.close();
};
restoreButton.onClick = function () {
restoreSession();
restoreWindow.close();
};
restoreWindow.show(); // Show the restore session window
} else {
alert("The log file 'Photoshop Session Document Paths.log' doesn't exist or is empty!");
}
}
// Functions
function saveSession() {
try {
// ~/Library/Preferences/Adobe Photoshop 2024 Settings/
var logFile = new File(app.preferencesFolder + "/" + "Photoshop Session Document Paths.log");
if (logFile.exists) logFile.remove();
// Log the active document name on line 2
logFile.open("a");
logFile.writeln("--------------------\nActive Doc:\n" + activeDocument.name + "\n--------------------");
logFile.close();
while (app.documents.length > 0) {
app.activeDocument = app.documents[0];
try {
activeDocument.path;
if (ExternalObject.AdobeXMPScript === undefined)
ExternalObject.AdobeXMPScript = new ExternalObject('lib:AdobeXMPScript');
var xmp = new XMPMeta(activeDocument.xmpMetadata.rawData);
var crsMeta = xmp.getProperty(XMPConst.NS_CAMERA_RAW, "Version");
if ((/\.(RAF|CR2|CR3|NRW|ERF|RW2|NEF|ARW|RWZ|EIP|DNG|BAY|DCR|RAW|CRW|3FR|K25|KC2|MEF|DNG|CS1|ORF|ARI|SR2|MOS|CR3|GPR|SRW|MFW|FFF|SRF|KDC|MRW|J6I|RWL|X3F|PEF|IIQ|CXI|NKSC|MDC)$/i).test(activeDocument.fullName) === true && crsMeta !== undefined) {
saveAsDefault();
writePathToLog();
activeDocument.close(SaveOptions.DONOTSAVECHANGES);
} else if (activeDocument.path) {
writePathToLog();
activeDocument.close(SaveOptions.SAVECHANGES);
}
} catch (e) {
executeAction(stringIDToTypeID("save"), undefined, DialogModes.ALL);
writePathToLog();
activeDocument.close(SaveOptions.SAVECHANGES);
}
}
} catch (e) {
alert("Error: " + e.message);
}
}
function restoreSession() {
try {
var logFilePath = readPref(app.preferencesFolder + "/" + "Photoshop Session Document Paths.log");
var hasAlerted = false;
if (logFilePath.length > 0) {
// Restore documents from the log file
for (var m = 4; m < logFilePath.length; m++) {
var filePath = logFilePath[m].replace(/^\s+|\s+$/g, ''); // Remove leading/trailing whitespace
if (filePath !== "") { // Check if the path is not empty
var docFile = new File(filePath);
if (docFile.exists) {
open(docFile);
} else {
alert("File not found: " + filePath);
}
}
}
// Set the previously active document after the session has been restored
var theActiveDocName = logFilePath[2]; // zero indexed, third line
for (var a = 0; a < app.documents.length; a++) {
if (app.documents[a].name === theActiveDocName) {
app.activeDocument = app.documents[a];
break;
}
}
} else {
alert("The log file 'Photoshop Session Document Paths.log' doesn't exist or is empty!");
hasAlerted = true;
}
} catch (e) {
alert("Error: " + e.message);
}
}
function writePathToLog() {
var decodedPath = decodeURI(activeDocument.path);
var decodedFilename = decodeURI(activeDocument.name);
var logFile = new File(app.preferencesFolder + "/" + "Photoshop Session Document Paths.log");
var os = $.os.toLowerCase().indexOf("mac") >= 0 ? "mac" : "windows";
logFile.open("a");
logFile.encoding = "UTF-8";
logFile.lineFeed = os === "mac" ? "Unix" : "Windows";
logFile.writeln(decodedPath + "/" + decodedFilename);
logFile.close();
}
function saveAsDefault() {
function s2t(s) { return app.stringIDToTypeID(s); }
var descriptor = new ActionDescriptor();
descriptor.putObject(s2t("as"), s2t("photoshop35Format"), descriptor);
descriptor.putPath(s2t("in"), new File("~/Desktop" + "/" + activeDocument.name));
descriptor.putBoolean(s2t("lowerCase"), true);
executeAction(s2t("save"), descriptor, DialogModes.ALL);
}
function readPref(thePath) {
var logFile = new File(thePath);
var logContents = [];
if (logFile.exists) {
logFile.open("r");
while (!logFile.eof) {
logContents.push(logFile.readln());
}
logFile.close();
}
return logContents;
}
// Show the main dialog
dlg.show();
https://prepression.blogspot.com/2017/11/downloading-and-installing-adobe-scripts.html
Copy link to clipboard
Copied
I have updated the v1.0 GUI script to v2.X, now supporting multiple auto-named or custom-named sessions!
Features:
* Preserves Document State: Automatically saves and closes all open documents.
* Session Naming: Save the session log using an automatic date/time stamp or an optional custom name.
* Restore Active Document Focus: The previously active document regains focus when the session is restored.
* Session List: View and select from a list of multiple saved session logs.
* View Log: Optionally view the list of documents from the saved session logs.
* Log Management: Options to delete selected log files or open the preference folder for manual management of log files.
* Permanent Session Saving: Save and restore sessions even after quitting Photoshop.
* Multiple Version Support: Each session is linked to the Photoshop version used when running the script. This way you can keep projects separate when using version-specific features.
/*
Save & Restore Photoshop Session scriptUI GUI v2-3b.jsx
Stephen Marsh
v1.0 - 27th October 2024, Single session save/restore
v2.0 - 27th October 2024, Extended the script to work with multiple sessions
v2.1 - 2nd November 2024, Minor cosmetic layout changes, log files now listed in descending modified sort order
v2.2 - 9th November 2024, Geek update - exploring semi-structured data, the log files are written and read in .json format instead of plain .txt format
v2.3 - 13th November 2024, Added an option to prompt to save modified documents when closing a session, in addition to the previous save and close option
v2.3a - 9th August 2025, JSON error logging code updated. Note Windows users may need to set permissions for "Everyone" on the following directory:
C:\Users\<username>\AppData\Roaming\Adobe\Adobe Photoshop ####\Adobe Photoshop #### Settings
v2.3b - 11th August 2025, Log file path directory separator updated to correctly display on Windows. Minor GUI layout change.
https://community.adobe.com/t5/photoshop-ecosystem-discussions/scripts-to-save-amp-restore-photoshop-sessions/m-p/14239969
Inspiration from:
https://community.adobe.com/t5/photoshop-ecosystem-ideas/please-session-saving/idc-p/14169472
https://community.adobe.com/t5/photoshop-ecosystem-ideas/restore-previous-session/idc-p/14189928
*/
#target photoshop
// Set the main UI window
var dlg = new Window("dialog", "Photoshop Session Manager (v2.3)");
dlg.orientation = "column";
dlg.alignChildren = ["fill", "top"];
dlg.preferredSize.width = 450;
// Checkbox panel to select the save functions
var checkboxGroup = dlg.add("panel", undefined, "Save Session Documents");
checkboxGroup.orientation = "column";
checkboxGroup.alignChildren = ["left", "center"];
// Group the checkboxes in a nested panel to keep them mutually exclusive
var buttonPanel = checkboxGroup.add("group");
buttonPanel.orientation = "column";
buttonPanel.alignChildren = ["left", "center"];
// "Save Current Session" checkbox
var saveCheckbox = buttonPanel.add("checkbox", undefined, "Save Current Session Options");
saveCheckbox.value = true;
// Add radio buttons for save behavior
var saveOptionsGroup = buttonPanel.add("group");
saveOptionsGroup.orientation = "row";
saveOptionsGroup.alignChildren = ["left", "center"];
saveOptionsGroup.margins = [20, 0, 0, 0]; // Add left margin for indentation
var saveAndCloseRadio = saveOptionsGroup.add("radiobutton", undefined, "Save && Close");
var promptAndCloseRadio = saveOptionsGroup.add("radiobutton", undefined, "Prompt to Save && Close");
saveAndCloseRadio.value = true; // Default selection
// Optional session naming field label
var sessionNameHelp = buttonPanel.add("statictext", undefined, "Optional Custom Session Name:");
// Optional session naming field
var sessionNameInput = buttonPanel.add("edittext", undefined, "");
sessionNameInput.helpTip = "(Leave blank to use timestamp as session name)";
sessionNameInput.preferredSize.width = 450;
// Create restore session panel (initially inactive)
var restorePanel = dlg.add("panel", undefined, "Restore Session Documents");
restorePanel.orientation = "column";
restorePanel.alignChildren = ["fill", "top"];
restorePanel.visible = true;
// "Restore Saved Session" checkbox
var restoreCheckbox = restorePanel.add("checkbox", undefined, "Restore Saved Session Options");
// Create listbox for session logs
var logList = restorePanel.add("listbox", undefined, [], { multiselect: false });
logList.preferredSize = [450, 150];
// Add management controls checkbox
var enableManagementCheckbox = restorePanel.add("checkbox", undefined, "Session Log File Management");
enableManagementCheckbox.value = false;
// Create management buttons group
var managementButtonGroup = restorePanel.add("group");
managementButtonGroup.orientation = "row";
managementButtonGroup.alignChildren = ["fill", "center"];
var viewButton = managementButtonGroup.add("button", undefined, "View Log");
var deleteButton = managementButtonGroup.add("button", undefined, "Delete Selected Log");
var openFolderButton = managementButtonGroup.add("button", undefined, "Open Log Directory");
// Initially disable the management buttons
openFolderButton.enabled = false;
deleteButton.enabled = false;
viewButton.enabled = false;
// Create button group for main dialog
var buttonGroup = dlg.add("group");
buttonGroup.orientation = "row";
buttonGroup.alignChildren = ["right", "center"];
var cancelButton = buttonGroup.add("button", undefined, "Cancel");
var saveButton = buttonGroup.add("button", undefined, "Save", { name: "save" });
saveButton.preferredSize.width = 90;
// Checkbox handlers for radio button-like behavior
saveCheckbox.onClick = function () {
// If trying to uncheck the currently checked box
if (!saveCheckbox.value && !restoreCheckbox.value) {
// Prevent unchecking by keeping this checkbox checked
saveCheckbox.value = true;
return;
}
if (saveCheckbox.value) {
restoreCheckbox.value = false;
setPanelEnabledState(false);
saveButton.text = "Save";
saveButton.enabled = true;
}
dlg.layout.layout(true);
};
restoreCheckbox.onClick = function () {
// If trying to uncheck the currently checked box
if (!restoreCheckbox.value && !saveCheckbox.value) {
// Prevent unchecking by keeping this checkbox checked
restoreCheckbox.value = true;
return;
}
if (restoreCheckbox.value) {
saveCheckbox.value = false;
setPanelEnabledState(true);
saveButton.text = "Restore";
refreshLogListByModifed();
saveButton.enabled = logList.selection && logList.selection.file;
}
dlg.layout.layout(true);
};
// Initialize with save checkbox selected by default
saveCheckbox.value = true;
restoreCheckbox.value = false;
setPanelEnabledState(false);
// Ensure Save button state updates if logList selection changes
logList.onChange = function () {
if (restoreCheckbox.value) {
saveButton.enabled = logList.selection && logList.selection.file;
}
};
// Checkbox handler
enableManagementCheckbox.onClick = function () {
openFolderButton.enabled = this.value;
deleteButton.enabled = this.value && logList.selection && logList.selection.file;
};
// Open folder button handler
openFolderButton.onClick = function () {
// Mac: ~/Library/Preferences/Adobe Photoshop #### Settings
// Win: C:\Users\<username>\AppData\Roaming\Adobe\Adobe Photoshop ####\Adobe Photoshop #### Settings
Folder(app.preferencesFolder).execute();
};
// Delete button handler
deleteButton.onClick = function () {
if (logList.selection && logList.selection.file) {
var selectedFile = logList.selection.file;
var confirmDelete = confirm("Are you sure you want to delete the selected log file?\n" + decodeURI(selectedFile.name));
if (confirmDelete) {
try {
selectedFile.remove();
refreshLogListByModifed();
} catch (error) {
alert("Error deleting file: " + "\r" + error + "\r" + 'Line: ' + error.line);
}
}
}
};
// View button handler
viewButton.onClick = function () {
if (logList.selection && logList.selection.file) {
viewLogContents(logList.selection.file);
}
};
// Cancel button handler
cancelButton.onClick = function () {
dlg.close();
};
// Save button handler with exit/return
saveButton.onClick = function () {
if (saveCheckbox.value) {
if (app.documents.length === 0) {
alert("No documents open in the current session to save.");
dlg.close();
return;
}
saveSession();
dlg.close();
} else if (restoreCheckbox.value && logList.selection && logList.selection.file) {
restoreSession(logList.selection.file);
dlg.close();
}
};
// Show the main script dialog window
dlg.show();
// Functions
function setPanelEnabledState(state) {
try {
logList.enabled = state;
enableManagementCheckbox.enabled = state;
openFolderButton.enabled = state && enableManagementCheckbox.value;
deleteButton.enabled = state && enableManagementCheckbox.value;
viewButton.enabled = state && logList.selection && logList.selection.file;
sessionNameInput.enabled = !state; // Enable session name input only when saving
saveOptionsGroup.enabled = !state; // Enable radio buttons only when saving
// Set the text color to dimmed gray when restore is active
sessionNameHelp.graphics.foregroundColor = sessionNameHelp.graphics.newPen(
sessionNameHelp.graphics.PenType.SOLID_COLOR,
state ? [0.5, 0.5, 0.5] : [1, 1, 1],
1
);
} catch (e) {
alert("Error:\n" + e.message + "\nLine: " + e.line);
}
}
function refreshLogListByModifed() {
try {
logList.removeAll();
// Mac: ~/Library/Preferences/Adobe Photoshop #### Settings
// Win: C:\Users\<username>\AppData\Roaming\Adobe\Adobe Photoshop ####\Adobe Photoshop #### Settings
var logFilePath = Folder(app.preferencesFolder);
var logFiles = logFilePath.getFiles("Photoshop Session - *.json");
if (logFiles && logFiles.length > 0) {
// Sort the files by modified date in descending order
logFiles.sort(function (a, b) {
return b.modified - a.modified;
});
// Add each log file to the list
for (var i = 0; i < logFiles.length; i++) {
var logFile = logFiles[i];
var item = logList.add("item", decodeURI(logFile.name));
item.file = logFile;
}
logList.selection = 0;
deleteButton.enabled = enableManagementCheckbox.value;
openFolderButton.enabled = enableManagementCheckbox.value;
viewButton.enabled = true;
saveButton.enabled = true;
} else {
logList.add("item", "No session log files found");
deleteButton.enabled = false;
openFolderButton.enabled = false;
viewButton.enabled = false;
saveButton.enabled = false;
}
} catch (e) {
alert("Error:\n" + e.message + "\nLine: " + e.line);
}
}
function restoreSession(jsonFile) {
try {
// Read and parse JSON file
jsonFile.open("r");
var jsonData = jsonFile.read();
jsonFile.close();
var sessionData = JSON.parse(jsonData);
var filePaths = sessionData.filePaths;
var theActiveDocName = sessionData.activeDocumentName;
// Open each file in the session data
for (var i = 0; i < filePaths.length; i++) {
var filePath = filePaths[i];
var docFile = new File(filePath);
if (docFile.exists) {
open(docFile);
} else {
alert("File not found: " + filePath);
}
}
// Set the active document based on session data
for (var a = 0; a < app.documents.length; a++) {
if (app.documents[a].name === theActiveDocName) {
app.activeDocument = app.documents[a];
break;
}
}
} catch (error) {
alert("Error restoring session: " + "\r" + error + "\r" + 'Line: ' + error.line);
}
}
function saveSession() {
try {
var theDate = new Date();
var year = theDate.getFullYear();
var month = ('0' + (theDate.getMonth() + 1)).slice(-2);
var day = ('0' + theDate.getDate()).slice(-2);
var hours = ('0' + theDate.getHours()).slice(-2);
var minutes = ('0' + theDate.getMinutes()).slice(-2);
var seconds = ('0' + theDate.getSeconds()).slice(-2);
var formattedDate = year + '-' + month + '-' + day + '_' + hours + ':' + minutes + ':' + seconds;
var sessionName = sessionNameInput.text.replace(/^\s+|\s+$/g, ''); // remove leading and trailing whitespace
var fileName = sessionName !== "" ? sessionName : formattedDate;
fileName = fileName.replace(/[<>:"\/\\|?*]/g, "-");
// Mac: ~/Library/Preferences/Adobe Photoshop #### Settings
// Win: C:\Users\<username>\AppData\Roaming\Adobe\Adobe Photoshop ####\Adobe Photoshop #### Settings
var jsonFile = new File(app.preferencesFolder + "/" + "Photoshop Session - " + fileName + ".json");
// Add confirmation check if file exists
if (jsonFile.exists) {
var confirmOverwrite = confirm("A session file with this name already exists:\n" +
decodeURI(jsonFile.name) +
"\n\nDo you want to overwrite it?");
if (!confirmOverwrite) {
// If user cancels, return without saving
return;
}
// If confirmed, remove the existing file
jsonFile.remove();
}
// Create JSON structure for the session data
var sessionData = {
sessionName: fileName,
activeDocumentName: activeDocument.name,
filePaths: []
};
// Collect file paths from open documents
while (app.documents.length > 0) {
app.activeDocument = app.documents[0];
try {
var filePath = activeDocument.fullName.fsName;
sessionData.filePaths.push(filePath);
} catch (error) { alert("Unexpected Error: " + "\r" + error + "\r" + 'Line: ' + error.line); }
// Use the selected save option
var saveOption = saveAndCloseRadio.value ? SaveOptions.SAVECHANGES : SaveOptions.PROMPTTOSAVECHANGES;
activeDocument.close(saveOption);
}
// Write JSON data to file
jsonFile.open("w");
jsonFile.write(JSON.stringify(sessionData, null, 4)); // Beautify output with 4 space indent/tab
jsonFile.close();
} catch (error) {
alert("Error saving session: " + "\r" + error + "\r" + 'Line: ' + error.line);
}
}
function viewLogContents(logFile) {
try {
// Read the log file contents and join lines with a newline character
var logContents = readPref(logFile).join("\n");
// Remove unwanted characters and replace specific terms
logContents = logContents
.replace(/[\{\"\[\],]|\\(?!")/g, "")
.replace(/sessionName:/g, "Session Name:")
.replace(/activeDocumentName:/g, "Active Document Name:")
.replace(/filePaths:/g, "Session File Paths:");
// Create a view window to display the log contents
var viewWindow = new Window("dialog", "Log Contents: " + decodeURI(logFile.name));
viewWindow.orientation = "column";
viewWindow.alignChildren = ["fill", "top"];
// Add a scrollable text area to display the log contents
var logTextArea = viewWindow.add("edittext", undefined, logContents, {
multiline: true,
scrollable: true
});
logTextArea.preferredSize.width = 550;
logTextArea.preferredSize.height = 300;
// Intercept key events to prevent modifications
logTextArea.addEventListener('keydown', function (event) {
event.preventDefault();
});
// Add a close button
var closeButtonGroup = viewWindow.add("group");
closeButtonGroup.orientation = "row";
closeButtonGroup.alignChildren = ["right", "center"];
var closeButton = closeButtonGroup.add("button", undefined, "Close");
closeButton.onClick = function () {
viewWindow.close();
};
// Show the log view window
viewWindow.show();
} catch (e) {
alert("Error:\n" + e.message + "\nLine: " + e.line);
}
}
function writePref(logFile, string) {
try {
logFile.open("e");
logFile.seek(0, 2);
logFile.writeln(string);
logFile.close();
} catch (e) {
alert("Error:\n" + e.message + "\nLine: " + e.line);
}
}
function readPref(logFile) {
try {
if (!logFile.exists) return [];
logFile.open("r");
var logContents = [];
while (!logFile.eof) {
logContents.push(logFile.readln());
}
logFile.close();
return logContents;
} catch (e) {
alert("Error:\n" + e.message + "\nLine: " + e.line);
}
}
https://prepression.blogspot.com/2017/11/downloading-and-installing-adobe-scripts.html
Copy link to clipboard
Copied
Hello and thank you for this script! I'm getting an error, are there any troubleshooting steps to take? When either Saving the current session or Restoring a session, the error is JSON is undefined. However I can see a session saved in the list of sessions, but restoring from it doesn't do anything other than pop up the error message.
Is there a specific filename I should use for this script?
The Presets/Scripts folder has 2 subfolders, Event Scripts Only and Stack Scripts Only; I assume this script should not be placed in either of those folders?
Thanks!
Copy link to clipboard
Copied
@lucyi2 Please post a screenshot of the error message.
Copy link to clipboard
Copied
@Stephen Marsh I can't believe I didn't know about this! You are a certified genius! I haven't had Photoshop crash for years, but some people I work with haven't been so lucky, and have lost important progress. I feel so humbled...
Copy link to clipboard
Copied
Save process:
Restore process:
Copy link to clipboard
Copied
Thanks, I was a little lazy when writing the error logging, I have updated the previous code to a 3.2a version with the error logging now listing the line of code where the error occurred. Please let me know on which lines the errors are reported so that I can try to debug.
P.S. I'm wondering if this is a permissions error, perhaps your system can't write the .json log file to the required location.
You could try changing the following three entries of:
app.preferencesFolder
To this:
"~/Desktop"
Copy link to clipboard
Copied
OK, this appears to be a Windows issue, it works on the Mac without needing to jump through extra hoops (that being said, Apple may change this in later OS versions).
On Windows, it is creating and saving the .json log file to the correct path:
C:\Users\<username>\AppData\Roaming\Adobe\Adobe Photoshop 2025\Adobe Photoshop 2025 Settings
However, the file is zer0 KB and has no data.
UPDATE:
The AppData folder is hidden by default, so you will either need to change your folder viewing settings to show hidden files and folders, or you can use the script's "Session Log File Management: Open Log Directory" to get the folder, then go up/back one directory level.
I resolved this issue by setting permissions to a new user "Everyone" on the folder listed above. Get Properties on the folder, go the Security tab, press Edit and then Add and type in Everyone and press OK. Ensure that you check the Full Control and Modiy allow permissions check boxes and press OK.
Copy link to clipboard
Copied
Thanks @Stephen Marsh . I tried adding "Everyone" to the permissions as you outlined and still no luck. At least this time we have a line number for the error code, hope that's helpful. I'm still getting empty session files. I tried using Desktop as the folder and that didn't work either.
Copy link to clipboard
Copied
I'm puzzled, did you search and replace all 3 entries of app.preferencesFolder to "~/Desktop" including the quotes?
This worked for me, as did setting permissions on the containing folder. I tested and confirmed both fixes before posting.
Copy link to clipboard
Copied
Great work, as usual! This reminds. E if a script that wrote for work, many years ago. The other photographers wanted to be able to stop my s ript that formats an image, make some editing changes, then run the script and pickup where they left off. I did sort of the same thing, in that I had the script write a temp XML file that matched the file's name and the place in my original script where it stopped. This way, if the temp XML was detected, it would not show the UI, but just pick up the script, where it left off. It was all just one script.
Find more inspiration, events, and resources on the new Adobe Community
Explore Now