Außerdem hat er mehrere Skripte in einem (function() { … })();- Bereich eingebettet.
Ab wo hast du denn kopiert?
Slash ausgenommen. Das betrifft auch andere Button, die lassen sich auch verschieben.
Außerdem hat er mehrere Skripte in einem (function() { … })();- Bereich eingebettet.
Ab wo hast du denn kopiert?
Slash ausgenommen. Das betrifft auch andere Button, die lassen sich auch verschieben.
Auch dein Script Adressleiste_verschiebbar funktioniert hier in v152.
Das ist jetzt meine favorisierte Version, alle Profile können beliebig oft gestartet werden. Dieses Script, getestet von v150 bis
v152, funktioniert ohne Probleme. Alle Profile müssen manuell eingetragen werden, wobei Unterschiede bei installierten und portablen Versionen weiterhin bestehen. Bei den installierten Versionen wird bei profile: immer der Name des Profils eingegeben (bei about:profiles entnehmen), bei den portablen dagegen muss hier immer der genaue Pfad zum Profilordner angegeben werden.
Alle Versionen werden grundsätzlich über die firefox.exe aus dem Installationsordner gestartet (also nicht über die FirefoxLoader.exe, usw.). Dafür ist dementsprechend bei exe: der genaue Pfad zur firefox.exe anzugeben. Beispiele sind dafür im Script für alle Versionen enthalten. Dann bitte testen!
// ==UserScript==
// @name FoxStarter Auto Stable + Icons
// @description Firefox / Portable Starter mit Icons + CSS
// @author FuchsFan (KI)
// @version 1.3.1 150+
// @note -no-remote entfernt
// @include main
// ==/UserScript==
(function () {
if (!window.gBrowser) return;
const btn_id = "foxstarter_auto";
const POPUP_ID = btn_id + "-popup";
const btn_icon = "file:///C:/FoxIcons2/Bild206.png";
const ICON_BASE = "file:///C:/FoxIcons2/";
const btn_tooltiptext = "Firefox Profile starten (Auswahl)";
const { classes: Cc, interfaces: Ci } = Components;
let cssInjected = false;
// =========================================================
// CSS
// =========================================================
function injectUserCSS() {
try {
if (cssInjected) return;
const css = `
#${btn_id} image.toolbarbutton-icon {
transform: scale(1.0) !important;
padding: 6px !important;
}
#${POPUP_ID} {
max-width: 285px !important;
}
#${POPUP_ID} menuitem {
padding-inline-start: 8px !important;
padding-inline-end: 8px !important;
margin: 0 !important;
min-height: 24px !important;
}
#${POPUP_ID} menuitem.menuitem-iconic .menu-icon {
margin-inline-end: 8px !important;
margin-inline-start: -30px !important;
width: 16px !important;
height: 16px !important;
}
#${POPUP_ID} menuitem.menuitem-iconic .menu-text {
margin-left: 8px !important;
font-weight: 500 !important;
padding: 2px 0 2px 0 !important;
}
#${POPUP_ID} menuitem.menuitem-iconic:hover .menu-text {
margin-left: 8px !important;
font-weight: 600 !important;
color: red !important;
}
`;
const sss =
Cc["@mozilla.org/content/style-sheet-service;1"]
.getService(Ci.nsIStyleSheetService);
const uri =
Services.io.newURI(
"data:text/css;charset=utf-8," +
encodeURIComponent(css)
);
if (!sss.sheetRegistered(uri, sss.AUTHOR_SHEET)) {
sss.loadAndRegisterSheet(uri, sss.AUTHOR_SHEET);
}
cssInjected = true;
} catch (e) {
console.error("[FoxStarter CSS]", e);
}
}
// =========================================================
// ITEMS + ICONS
// =========================================================
const ITEMS = {
// installierte Versionen
"ArbeitsFox 🏠": {
exe: "C:\\Program Files\\Mozilla Firefox\\firefox.exe",
profile: "ArbeitsFox",
icon: "Finale.png"
},
"Reserve 1 🏠": {
exe: "C:\\Program Files\\Mozilla Firefox\\firefox.exe",
profile: "Reserve",
icon: "Finale.png"
},
"Reserve 2 🏠": {
exe: "C:\\Program Files\\Mozilla Firefox\\firefox.exe",
profile: "Reserve-Profil 2",
icon: "Finale.png"
},
// portable Versionen
"Firefox3p > portable < 🟢": {
exe: "G:\\Firefox Test\\Firefox3p\\Firefox64\\firefox.exe",
profile: "G:\\Firefox Test\\Firefox3p\\Profilordner",
icon: "Finale.png"
},
"Nightly1 > portable < 🔵": {
exe: "G:\\Firefox Test\\Nightly1\\Firefox64\\firefox.exe",
profile: "G:\\Firefox Test\\Nightly1\\Profilordner",
icon: "Nightly.png"
},
"Portable U Stable 3 🔥": {
exe: "G:\\Portable.Firefox.Updater.3\\Firefox Stable x64\\firefox.exe",
profile: "G:\\Portable.Firefox.Updater.3\\Firefox Stable x64\\profile",
icon: "Finale.png"
}
};
// =========================================================
// START
// =========================================================
function launch(item) {
try {
const file =
Cc["@mozilla.org/file/local;1"]
.createInstance(Ci.nsIFile);
file.initWithPath(item.exe);
const process =
Cc["@mozilla.org/process/util;1"]
.createInstance(Ci.nsIProcess);
process.init(file);
let args = [];
const isFirefox =
item.exe.toLowerCase().includes("firefox.exe");
const isProfilePath =
item.profile &&
(item.profile.includes("\\") || item.profile.includes("/"));
if (isFirefox && isProfilePath) {
// -no-remote entfernt
args = [
"-profile",
item.profile,
"-foreground"
];
} else if (isFirefox) {
// -no-remote entfernt
args = [
"-P",
item.profile,
"-foreground"
];
}
process.run(false, args, args.length);
} catch (e) {
console.error("[FoxStarter]", e);
}
}
// =========================================================
// MENU MIT ICONS
// =========================================================
function buildMenu() {
const btn = document.getElementById(btn_id);
if (!btn || btn.querySelector("menupopup")) return;
const popup =
document.createXULElement("menupopup");
popup.setAttribute("id", POPUP_ID);
for (const key of Object.keys(ITEMS)) {
const item = ITEMS[key];
const mi =
document.createXULElement("menuitem");
mi.setAttribute("label", key);
mi.setAttribute("class", "menuitem-iconic");
const icon =
item.icon
? ICON_BASE + item.icon
: btn_icon;
mi.setAttribute("image", icon);
mi.style.listStyleImage =
`url("${icon}")`;
mi.addEventListener("command", () => {
launch(item);
});
popup.appendChild(mi);
}
btn.appendChild(popup);
}
// =========================================================
// BUTTON
// =========================================================
try {
CustomizableUI.createWidget({
id: btn_id,
defaultArea: CustomizableUI.AREA_NAVBAR,
label: "FoxStart",
tooltiptext: btn_tooltiptext,
onCreated: (btn) => {
btn.style.listStyleImage =
`url("${btn_icon}")`;
btn.setAttribute("type", "menu");
injectUserCSS();
buildMenu();
}
});
} catch (e) {}
setTimeout(() => {
injectUserCSS();
buildMenu();
}, 500);
})();
Alles anzeigen
Ja, auf diese Idee war ich auch schon gekommen.
Mira_Belle Ich auch!![]()
Deshalb habe ich mal versucht daraus etwas Brauchbares zu schaffen, und bin damit eigentlich zufrieden. Es wird in der Navbar ein Button erstellt, über den dann das Menü mit den Profilen zur Auswahl geöffnet wird. Im Script selbst erfolgt eine besondere Einstufung für installierte und portable Versionen. Versucht habe ich bisher ergebnislos die Funktion einzubauen, sofern ein Firefox gestartet ist, dieser beim zweiten Aufruf dann ein Hinweis erfolgt (Alert), dass er bereits gestartet ist. Bisher alle Versuche erfolglos. Schau es dir an, eventuell findest du eine Lösung. So dann zum Test freigegeben:
// ==UserScript==
// @name FoxStarter.uc.js
// @description Navbar Button (verschiebbar) + Menü für Start von Profilen
// @version 1.0.1
// @author FuchsFan (KI)
// @include main
// @charset UTF-8
// ==/UserScript==
(function () {
if (!window.gBrowser) return;
// Start User Einstellungen
let btn_id = 'start_profile_btn'; // Button #id
const btn_label = 'ProfileStart';
const btn_tooltiptext = 'Firefox Profile starten (Auswahl)';
const btn_icon = 'Bild206.png';
const iconPath = 'file:///C:/FoxIcons2/'; // Icon-Ordner (für Button)
const ImagePath = iconPath + btn_icon;
// Ende User Einstellungen
const { classes: Cc, interfaces: Ci } = Components;
const BrowserPath = {
// installierte Versionen
"ArbeitsFox 🏠": {
cmd: "C:\\Program Files\\Mozilla Firefox\\firefox.exe<>$1 -P \"ArbeitsFox\"",
icon: "Finale.png"
},
"Reserve-Profil 1 🏠": {
cmd: "C:\\Program Files\\Mozilla Firefox\\firefox.exe<>$1 -P \"Reserve\"",
icon: "Finale.png"
},
"Reserve-Profil 2 🏠": {
cmd: "C:\\Program Files\\Mozilla Firefox\\firefox.exe<>$1 -P \"Reserve-Profil 2\"",
icon: "Finale.png"
},
"Reserve-Profil 3 🏠": {
cmd: "C:\\Program Files\\Mozilla Firefox\\firefox.exe<>$1 -P \"Reserve 3\"",
icon: "Finale.png"
},
// portable Versionen
"Portable.Firefox.Updater.3 Nightly 🟠 ": {
cmd: "G:\\Portable.Firefox.Updater.3\\Firefox Nightly x64 Launcher.exe",
icon: "Nightly.png"
},
"Firefox 3 portable 🔥": {
cmd: "G:\\Firefox Test\\Firefox3p\\FirefoxLoader.exe",
icon: "Finale.png"
},
"Nigtly 1 portable 🔵": {
cmd: "G:\\Firefox Test\\Nightly1\\FirefoxLoader.exe",
icon: "Nightly.png"
}
};
function menuIconUrl(pngName) {
// Direkte Bild-URL (am zuverlässigsten für PNG)
const fileUrl = "file:///C:/FoxIcons2/" + pngName;
return encodeURI(fileUrl);
}
function launch(browserPathEntry, openURL) {
// browserPathEntry ist jetzt ein Objekt: { cmd, icon }
let [path, argsRaw] = browserPathEntry.cmd.split("<>");
if (!argsRaw) argsRaw = "";
// Tokenizer respektiert "..." / '...'
const tokens = [];
const re = /"([^"]*)"|'([^']*)'|(\S+)/g;
let m;
while ((m = re.exec(argsRaw)) !== null) {
tokens.push(m[1] ?? m[2] ?? m[3]);
}
const finalArgs = tokens.map(t => t.replace(/\$1/g, openURL));
const file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
file.initWithPath(path);
const process = Cc["@mozilla.org/process/util;1"].createInstance(Ci.nsIProcess);
process.init(file);
process.run(false, finalArgs, finalArgs.length, {});
}
function ensurePopup() {
const btn = document.getElementById(btn_id);
if (!btn) return;
if (btn.querySelector('#' + btn_id + '_popup')) return;
const popup = document.createXULElement('menupopup');
popup.setAttribute('id', btn_id + '_popup');
for (const key of Object.keys(BrowserPath)) {
const itemData = BrowserPath[key];
const iconUrl = menuIconUrl(itemData.icon);
const mi = document.createXULElement('menuitem');
mi.setAttribute('label', ' ' + key);
mi.setAttribute('value', key);
// ikonisch machen + Icon setzen
mi.setAttribute('class', 'menuitem-iconic');
mi.setAttribute('image', iconUrl); // direkt als Bild-URL
mi.style.listStyleImage = 'url("' + iconUrl + '")'; // Fallback
mi.addEventListener('command', (ev) => {
const k = ev.target.getAttribute('value');
const url = (gBrowser.currentURI && gBrowser.currentURI.spec) ? gBrowser.currentURI.spec : '';
launch(BrowserPath[k], url);
}, false);
popup.appendChild(mi);
}
btn.appendChild(popup);
}
try {
CustomizableUI.createWidget({
id: btn_id,
defaultArea: CustomizableUI.AREA_NAVBAR,
label: btn_label,
tooltiptext: btn_tooltiptext,
onCreated: (this_button) => {
this_button.style.MozContextProperties = 'fill, stroke, fill-opacity, stroke-opacity';
this_button.style.listStyleImage = 'url("' + ImagePath + '")';
this_button.style.minWidth = 'fit-content';
// Dropdown
this_button.setAttribute('type', 'menu');
ensurePopup();
this_button.addEventListener('click', (event) => {
if (event.button !== 0) return;
ensurePopup();
const popup = document.getElementById(btn_id + '_popup');
if (popup && typeof popup.openPopup === 'function') {
popup.openPopup(this_button, 'after_start', 0, 0, true, false);
}
}, true);
}
});
} catch (e) {
setTimeout(() => ensurePopup(), 200);
}
if (window.readyState !== "loading") {
setTimeout(() => ensurePopup(), 500);
} else {
window.addEventListener("DOMContentLoaded", () => ensurePopup(), { once: true });
}
window.addEventListener('aftercustomization', () => {
setTimeout(() => ensurePopup(), 100);
}, false);
})();
Alles anzeigen
Ich kenne mich mit Skripten ja nicht aus, aber wozu brauchst du die Ordner überhaupt
Ja, sonst startet der Firefox nicht, und Icons werden auch nicht angezeigt. Du weißt, ich habe auch keine Ahnung, aber KI hat das nun mal so eingerichtet, und es funktioniert .
Das kann ich so nicht stehen lassen, denn die im ersten Script eingetragenen portablen Versionen sind alle mit dem FirefoxUpdater erstellt worden, der Profilordner darin heißt "profile". Damit funktioniert es so, wie sie in dem Script eingetragen sind ohne Probleme. Nun habe ich eine weitere portable Version zum Test eingebaut, und da öffnete sich bei Klick immer der Profilmanager, Firefox wurde nicht gestartet. Diese Form brauchte im Script eine andere Behandlung, und der Eintrag im Script sieht dafür anders aus, und hier heißt er "Profilordner". Hier sind die Unterschiede aufgeführt:
addProfileItem(document, popup,
"️Portable U Beta 4 🔥 ", "profile",
"G:\\Portable.Firefox.Updater.4\\Firefox Beta x64 Launcher.exe",
"file:///C:/FoxIcons/Beta.png"
);
// ✅ Firefox3p: Profilordner direkt starten (kein Profilmanager)
addProfileItem(document, popup,
"️Firefox3p 🔥 ",
"G:\\Firefox Test\\Firefox3p\\Profilordner",
"G:\\Firefox Test\\Firefox3p\\Firefox64\\firefox.exe",
"file:///C:/FoxIcons/Finale.png",
"dir"
);
Alles anzeigen
Das Script wurde deswegen neu angepasst:
// == PROFILSTARTER.UC.JS v9-test - CSS SOFORT + MULTI-FENSTER FIX ===
console.log("=== PROFILSTARTER.UC.JS v9-test - CSS SOFORT + MULTI-FENSTER FIX ===");
(function() {
if (!window.gBrowser)
return;
// User Settings
let btn_id = 'aboutprofiles-Start'; // Button #id
const btn_icon = 'p2.png'; // Symbol
const iconPath = 'file:///C:/FoxIcons/'; // Icon-Ordner
const ImagePath = iconPath + btn_icon;
const btn_label = 'Profil zusätzlich starten';
const btn_tooltiptext = 'Zusätzliche Firefox-Profile starten';
const POPUP_ID = btn_id + '-popup';
// ✅ CSS einmalig pro Fenster injizieren
let cssInjected = false;
// ============== CSS ==============
function injectUserCSS() {
try {
if (cssInjected) return;
const css = `
#${btn_id} image.toolbarbutton-icon {
transform: scale(1.0) !important;
padding: 6px !important;
}
#${POPUP_ID} {
max-width: 285px !important;
}
#${POPUP_ID} menuitem {
padding-inline-start: 8px !important;
padding-inline-end: 8px !important;
margin: 0 !important;
min-height: 24px !important;
}
#${POPUP_ID} menuitem.menuitem-iconic .menu-icon {
margin-inline-end: 8px !important;
margin-inline-start: -30px !important;
width: 16px !important;
height: 16px !important;
}
#${POPUP_ID} menuitem.menuitem-iconic .menu-text {
margin-left: 8px !important;
font-weight: 500 !important;
padding: 2px 0 2px 0 !important;
}
#${POPUP_ID} menuitem.menuitem-iconic:hover .menu-text {
margin-left: 8px !important;
font-weight: 600 !important;
color: red !important;
opacity: 1 !important;
}
`;
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;
const Services = globalThis.Services || Cu.import("resource://gre/modules/Services.jsm").Services;
const sss = Cc["@mozilla.org/content/style-sheet-service;1"]
.getService(Ci.nsIStyleSheetService);
const uri = Services.io.newURI(
"data:text/css;charset=utf-8," + encodeURIComponent(css)
);
if (!sss.sheetRegistered(uri, sss.AUTHOR_SHEET)) {
sss.loadAndRegisterSheet(uri, sss.AUTHOR_SHEET);
}
cssInjected = true;
console.log("[PROFILSTARTER] CSS injiziert.");
} catch (e) {
console.error("[PROFILSTARTER] CSS Fehler:", e);
}
}
// ============== Profil-Daten ==============
const PROFIL_NAMEN = {
"ArbeitsFox": { name: " ArbeitsFox ( >>Standard<< ) 🏠", icon: "Finale.png" },
"Einkauf": { name: " Einkaufen ( >>Shops<< ) 🏠", icon: "s4.png" },
"default": { name: " Nicht starten ( >>Default<< ) 🏠", icon: "warnung19.png" },
"Reserve": { name: " Reserve 1 ( >>Ersatz-Profil<< ) 🏠", icon: "Firefox32.png" },
"Reserve-Profil 2": { name: " Reserve 2 ( >>Ersatz-Profil<< ) 🏠", icon: "Firefox32.png" },
"Reserve 3": { name: " Reserve 3 ( >>Ersatz-Profil<< ) 🏠", icon: "Firefox32.png" }
};
// ============== START (angepasst: -profile dir) ==============
function startProfile(profileValue, exePath, mode = "name") {
try {
const Cc = Components.classes;
const Ci = Components.interfaces;
let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
let defaultPath = "C:\\Program Files\\Mozilla Firefox\\firefox.exe";
file.initWithPath(exePath || defaultPath);
let args;
if (mode === "dir") {
// Profilordner direkt starten
args = ["-no-remote", "-profile", profileValue, "-foreground"];
} else {
// Normal: Profilname (aus profiles.ini)
args = ["-no-remote", "-P", profileValue || "", "-foreground"];
}
let process = Cc["@mozilla.org/process/util;1"].createInstance(Ci.nsIProcess);
process.init(file);
process.run(false, args, args.length);
console.log(
"[PROFILSTARTER] Start:",
mode,
profileValue,
"EXE:",
exePath || defaultPath,
"ARGS:",
args.join(" ")
);
} catch (e) {
console.error("[PROFILSTARTER] Start Fehler:", e);
}
}
// ============== MENU ITEM (angepasst: mode weiterreichen) ==============
function addProfileItem(aDocument, menupopup, label, profileValue, exePath, iconURI = null, mode = "name") {
const xulNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
let item = aDocument.createElementNS(xulNS, "menuitem");
item.setAttribute("label", label);
if (iconURI) {
item.setAttribute("class", "menuitem-iconic");
item.setAttribute("image", iconURI);
}
item.addEventListener("command", () => startProfile(profileValue, exePath, mode));
menupopup.appendChild(item);
}
function loadProfilesWithNiceNames(aDocument, menupopup) {
const ICON_BASE = "file:///C:/FoxIcons/";
const INI_PATH = "C:\\Users\\Old Man\\AppData\\Roaming\\Mozilla\\Firefox\\profiles.ini";
try {
let iniFile = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsIFile);
iniFile.initWithPath(INI_PATH);
if (!iniFile.exists()) {
addProfileItem(aDocument, menupopup, "❌ profiles.ini fehlt", "", null, null);
return;
}
const iniParser = Components.classes["@mozilla.org/xpcom/ini-parser-factory;1"]
.getService(Components.interfaces.nsIINIParserFactory)
.createINIParser(iniFile);
for (let section of iniParser.getSections()) {
if (!section.startsWith("Profile")) continue;
let profileNameRaw = iniParser.getString(section, "Name") || section.replace("Profile", "");
let eintrag = PROFIL_NAMEN[profileNameRaw];
let niceName, iconURI = null;
if (eintrag && typeof eintrag === "object") {
niceName = eintrag.name;
if (eintrag.icon) iconURI = ICON_BASE + eintrag.icon;
} else {
niceName = profileNameRaw + " (unbekannt)";
}
addProfileItem(aDocument, menupopup, niceName, profileNameRaw, null, iconURI);
}
} catch (e) {
console.error("[PROFILSTARTER] INI Fehler:", e);
addProfileItem(aDocument, menupopup, "❌ profiles.ini Fehler", "", null, null);
}
}
function buildPopupIfNeeded() {
const button = document.getElementById(btn_id);
if (!button) return null;
if (button.getAttribute("profiles-menu-built") === "true") {
return document.getElementById(POPUP_ID);
}
const xulNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
let popup = document.getElementById(POPUP_ID);
if (!popup) {
popup = document.createElementNS(xulNS, "menupopup");
popup.setAttribute("id", POPUP_ID);
button.appendChild(popup);
} else {
// ggf. vorherige Einträge löschen
while (popup.firstChild) popup.removeChild(popup.firstChild);
}
// Profile aus profiles.ini
loadProfilesWithNiceNames(document, popup);
// Portable Profile (wie bisher: mode default="name")
addProfileItem(document, popup,
"Portable U Nightly 3 🔥", "profile",
"G:\\Portable.Firefox.Updater.3\\Firefox Nightly x64 Launcher.exe",
"file:///C:/FoxIcons/Nightly.png"
);
addProfileItem(document, popup,
"️Portable U Stable 3 🔥 ", "profile",
"G:\\Portable.Firefox.Updater.3\\Firefox Stable x64 Launcher.exe",
"file:///C:/FoxIcons/Finale.png"
);
addProfileItem(document, popup,
"️Portable U Beta 3 🔥 ", "profile",
"G:\\Portable.Firefox.Updater.3\\Firefox Beta x64 Launcher.exe",
"file:///C:/FoxIcons/Beta.png"
);
addProfileItem(document, popup,
"Portable U Nightly 1 🔥", "profile",
"G:\\Portable.Firefox.Updater.1\\Firefox Nightly x64 Launcher.exe",
"file:///C:/FoxIcons/Nightly.png"
);
addProfileItem(document, popup,
"️Portable U Stable 1 🔥 ", "profile",
"G:\\Portable.Firefox.Updater.1\\Firefox Stable x64 Launcher.exe",
"file:///C:/FoxIcons/Finale.png"
);
addProfileItem(document, popup,
"️Portable U Beta 1 🔥 ", "profile",
"G:\\Portable.Firefox.Updater.1\\Firefox Beta x64 Launcher.exe",
"file:///C:/FoxIcons/Beta.png"
);
addProfileItem(document, popup,
"Portable U Nightly 2 🔥", "profile",
"G:\\Portable.Firefox.Updater.2\\Firefox Nightly x64 Launcher.exe",
"file:///C:/FoxIcons/Nightly.png"
);
addProfileItem(document, popup,
"️Portable U Stable 2 🔥 ", "profile",
"G:\\Portable.Firefox.Updater.2\\Firefox Stable x64 Launcher.exe",
"file:///C:/FoxIcons/Finale.png"
);
addProfileItem(document, popup,
"️Portable U Beta 2 🔥 ", "profile",
"G:\\Portable.Firefox.Updater.2\\Firefox Beta x64 Launcher.exe",
"file:///C:/FoxIcons/Beta.png"
);
addProfileItem(document, popup,
"Portable U Nightly 4 🔥", "profile",
"G:\\Portable.Firefox.Updater.4\\Firefox Nightly x64 Launcher.exe",
"file:///C:/FoxIcons/Nightly.png"
);
addProfileItem(document, popup,
"️Portable U Stable 4 🔥 ", "profile",
"G:\\Portable.Firefox.Updater.4\\Firefox Stable x64 Launcher.exe",
"file:///C:/FoxIcons/Finale.png"
);
addProfileItem(document, popup,
"️Portable U Beta 4 🔥 ", "profile",
"G:\\Portable.Firefox.Updater.4\\Firefox Beta x64 Launcher.exe",
"file:///C:/FoxIcons/Beta.png"
);
// ✅ Firefox3p: Profilordner direkt starten (kein Profilmanager)
addProfileItem(document, popup,
"️Firefox3p 🔥 ",
"G:\\Firefox Test\\Firefox3p\\Profilordner",
"G:\\Firefox Test\\Firefox3p\\Firefox64\\firefox.exe",
"file:///C:/FoxIcons/Finale.png",
"dir"
);
button.setAttribute("profiles-menu-built", "true");
return popup;
}
function click_button() {
let button = document.getElementById(btn_id);
if (!button) return;
if (button.hasAttribute("listener-added"))
return;
button.setAttribute("listener-added", "true");
// Kontextmenü unterdrücken
button.addEventListener("contextmenu", event => {
event.preventDefault();
});
// Klick: Popup öffnen (links oder rechts)
button.addEventListener('click', event => {
event.preventDefault();
event.stopPropagation();
// CSS ist jetzt schon beim Start aktiv (injectUserCSS ist idempotent),
injectUserCSS();
let popup = buildPopupIfNeeded();
if (!popup) return;
// Popup am Button öffnen
try {
popup.openPopup(button, "after_start", 0, 0, false, false);
} catch (e) {
console.error("[PROFILSTARTER] openPopup Fehler:", e);
}
});
}
// Widget anlegen (nur einmal versuchen)
try {
CustomizableUI.createWidget({
id: btn_id,
defaultArea: CustomizableUI.AREA_NAVBAR,
label: btn_label,
tooltiptext: btn_tooltiptext,
onCreated: (this_button) => {
this_button.style.listStyleImage = 'url("' + ImagePath + '")';
this_button.style.minWidth = 'fit-content';
}
});
} catch (e) {
// Widget existiert evtl. schon -> ignorieren
}
// Listener pro Fenster setzen
function initForWindow() {
// ✅ CSS sofort verfügbar machen (damit das Icon von Anfang an stimmt)
injectUserCSS();
if (window.readyState !== "loading") {
setTimeout(click_button, 300);
} else {
window.addEventListener("DOMContentLoaded", () => setTimeout(click_button, 300));
}
}
initForWindow();
window.addEventListener('aftercustomization', () => {
injectUserCSS();
setTimeout(() => click_button(), 100);
});
})();
Alles anzeigen
In allen meinen portablen Versionen wird mit meinem Script die profiles.ini der installierten Version ausgelesen. Der Grund dafür ist der, dass dieser Pfad const INI_PATH = "C:\\Users\\Old Man\\AppData\\Roaming\\Mozilla\\Firefox\\profiles.ini"; dafür aufgerufen wird, egal ob installiert oder portable. Keine Probleme damit hier.
Entschuldige.
Keine Panik, alles ist gut, Hauptsache du hast es bekommen. Gute Reise!
Deshalb ist jetzt an dieser Stelle erst einmal Schluss.
Mira_Belle Den Link hast du gesehen?
Keine Antwort, deshalb stelle ich den Link zum Download hier ein. Es ist meine Reserve, und beinhaltet alle vier portablen Versionen im Original und startbereit. Falls jemand es laden möchte, der Download hat noch 7 Tage Gültigkeit.
Wie hast Du die portablen Versionen erstellt?
Warum hast Du verschiedene Launcher.exe?
Mira_Belle , hier gab es dieses Programm dafür, funktioniert nicht mehr, und wurde auch nicht mehr weiter entwickelt https://github.com/UndertakerBen/PorFirefoxUpd/releases. Die ich damals damit erstellt habe funktionieren immer noch. Welche Version möchtest du denn haben. Übrigens,das erste Script, welches ich gezeigt habe, funktioniert in jeder Version, installiert oder portable. Auch das zweite Script in Nightla portable.
Wenn das Skript in einer port. Version ist, dann ist das hier auch so:
Danke, Andreas, so war es hier beim Test.
Für das erzeugte Menü wird die profiles.ini ausgelesen.
Habe dein Script von v150 bis v152 getestet, Button wird erzeugt, Menü ist auch da, aber überall mit der Meldung darin "profiles.ini fehlt". Das ist natürlich nicht der Fall, funktioniert es denn bei dir, dass die *.ini ausgelesen wird?
Das andere ist die compatibility.ini im Profilordner:
Danke, hatte ich mir auch schon angesehen.
Sieht hier so aus:
Ja, genau so ist es.
Ja, auch, denn ich kann das nicht nachvollziehen. Denn in der profiles.ini steht z.B. für meinen ArbeitsFox das geschrieben:
[Profile0]
Name=ArbeitsFox
IsRelative=1
Path=Profiles/qtqwpmy7.default-release
StoreID=b2d0fa71
ShowSelector=1
[Install60EDFDC9594E2591]
Default=Profiles/qtqwpmy7.default-release
Locked=1
Ist das wirklich aus der profiles.ini ?
Und da liegt auch "mein" Problem,
denn das Profil der Nightly wird ja auch angezeigt und ist dann eben nicht nutzbar, da nicht mit der Nightly verknüpft.
In Zeile 126 ist ja der Pfad zur profiles.ini anzugeben, ich stelle mir vor, dass eine weitere Zeile zur profiles.ini von Nightly das Problem dann lösen könnte.
Das Script angepasst für mehrere Installationen (Stable/Beta/Nightly). Kann es nicht testen, weil nur Stable installiert ist.
// == PROFILSTARTER.UC.JS v11 ==
console.log("=== PROFILSTARTER.UC.JS v11 - Stable + Beta + Nightly (Widget Fix) ===");
(function() {
if (!window.gBrowser)
return;
// User Settings
let btn_id = 'aboutprofiles-Start'; // Button #id
const btn_icon = 'p2.png'; // Symbol
const iconPath = 'file:///C:/FoxIcons/'; // Icon-Ordner
const ImagePath = iconPath + btn_icon;
const btn_label = 'Profil zusätzlich starten';
const btn_tooltiptext = 'Zusätzliche Firefox-Profile starten';
const POPUP_ID = btn_id + '-popup';
// ============== CSS ==============
function injectUserCSS() {
try {
const css = `
#${btn_id} image.toolbarbutton-icon {
transform: scale(1.0) !important;
padding: 6px !important;
}
#${POPUP_ID} {
max-width: 285px !important;
}
#${POPUP_ID} menuitem {
padding-inline-start: 8px !important;
padding-inline-end: 8px !important;
margin: 0 !important;
min-height: 24px !important;
}
#${POPUP_ID} menuitem.menuitem-iconic .menu-icon {
margin-inline-end: 8px !important;
margin-inline-start: -30px !important;
width: 16px !important;
height: 16px !important;
}
#${POPUP_ID} menuitem.menuitem-iconic .menu-text {
margin-left: 8px !important;
font-weight: 500 !important;
padding: 2px 0 2px 0 !important;
}
#${POPUP_ID} menuitem.menuitem-iconic:hover .menu-text {
margin-left: 8px !important;
font-weight: 600 !important;
color: red !important;
opacity: 1 !important;
}
`;
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;
const Services = globalThis.Services || Cu.import("resource://gre/modules/Services.jsm").Services;
const sss = Cc["@mozilla.org/content/style-sheet-service;1"]
.getService(Ci.nsIStyleSheetService);
const uri = Services.io.newURI(
"data:text/css;charset=utf-8," + encodeURIComponent(css)
);
if (!sss.sheetRegistered(uri, sss.AUTHOR_SHEET)) {
sss.loadAndRegisterSheet(uri, sss.AUTHOR_SHEET);
}
} catch (e) {
console.error("[PROFILSTARTER] CSS Fehler:", e);
}
}
// ============== Profil-Daten ==============
const PROFIL_NAMEN = {
"ArbeitsFox": { name: " ArbeitsFox ( >>Standard<< ) 🏠", icon: "Finale.png" },
"Einkauf": { name: " Einkaufen ( >>Shops<< ) 🏠", icon: "s4.png" },
"default": { name: " Nicht starten ( >>Default<< ) 🏠", icon: "warnung19.png" },
"Reserve": { name: " Reserve 1 ( >>Ersatz-Profil<< ) 🏠", icon: "Firefox32.png" },
"Reserve-Profil 2": { name: " Reserve 2 ( >>Ersatz-Profil<< ) 🏠", icon: "Firefox32.png" },
"Reserve 3": { name: " Reserve 3 ( >>Ersatz-Profil<< ) 🏠", icon: "Firefox32.png" }
};
function startProfile(profileName, exePath) {
try {
const Cc = Components.classes;
const Ci = Components.interfaces;
let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
let defaultPath = "C:\\Program Files\\Mozilla Firefox\\firefox.exe";
file.initWithPath(exePath || defaultPath);
let args = ["-no-remote", "-P", profileName || "", "-foreground"];
let process = Cc["@mozilla.org/process/util;1"].createInstance(Ci.nsIProcess);
process.init(file);
process.run(false, args, args.length);
console.log("[PROFILSTARTER] Start:", profileName, "EXE:", exePath || defaultPath);
} catch (e) {
console.error("[PROFILSTARTER] Start Fehler:", e);
}
}
function addProfileItem(aDocument, menupopup, label, profileName, exePath, iconURI = null) {
const xulNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
let item = aDocument.createElementNS(xulNS, "menuitem");
item.setAttribute("label", label);
if (iconURI) {
item.setAttribute("class", "menuitem-iconic");
item.setAttribute("image", iconURI);
}
item.addEventListener("command", () => startProfile(profileName, exePath));
menupopup.appendChild(item);
}
function isPlaceholderPath(p) {
if (!p) return true;
const s = String(p);
return s.toUpperCase().includes("PUT_BETA_") ||
s.toUpperCase().includes("PUT_NIGHTLY_") ||
s.toUpperCase().includes("HIER_EINTRAGEN");
}
// ============== NEU: Kanal-Instanzen (Stable/Beta/Nightly) ==============
// iniPath: ...\profiles.ini
// exePath: ...\firefox.exe (bzw. der echte Channel-Exe-Pfad)
const FIREFOX_INSTANCES = [
{
id: "Stable",
channelLabel: "Stable",
iniPath: "C:\\Users\\Old Man\\AppData\\Roaming\\Mozilla\\Firefox\\profiles.ini",
exePath: "C:\\Program Files\\Mozilla Firefox\\firefox.exe"
},
{
id: "Beta",
channelLabel: "Beta",
iniPath: "PUT_BETA_PROFILES_INI_PATH_HIER_EINTRAGEN",
exePath: "PUT_BETA_FIREFOX_EXE_PATH_HIER_EINTRAGEN"
},
{
id: "Nightly",
channelLabel: "Nightly",
iniPath: "PUT_NIGHTLY_PROFILES_INI_PATH_HIER_EINTRAGEN",
exePath: "PUT_NIGHTLY_FIREFOX_EXE_PATH_HIER_EINTRAGEN"
}
];
function loadProfilesWithNiceNames(aDocument, menupopup, iniPath, exePath, channelLabel, addedKeys) {
const ICON_BASE = "file:///C:/FoxIcons/";
try {
if (isPlaceholderPath(iniPath) || isPlaceholderPath(exePath)) {
return; // Kanal ignorieren, solange Pfade nicht gesetzt sind
}
let iniFile = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsIFile);
iniFile.initWithPath(iniPath);
if (!iniFile.exists()) {
addProfileItem(aDocument, menupopup,
`❌ ${channelLabel}: profiles.ini fehlt`,
"",
null,
null
);
return;
}
const iniParser = Components.classes["@mozilla.org/xpcom/ini-parser-factory;1"]
.getService(Components.interfaces.nsIINIParserFactory)
.createINIParser(iniFile);
for (let section of iniParser.getSections()) {
if (!section.startsWith("Profile")) continue;
let profileNameRaw = iniParser.getString(section, "Name") || section.replace("Profile", "");
let eintrag = PROFIL_NAMEN[profileNameRaw];
let niceName, iconURI = null;
if (eintrag && typeof eintrag === "object") {
niceName = eintrag.name + ` (${channelLabel})`;
if (eintrag.icon) iconURI = ICON_BASE + eintrag.icon;
} else {
niceName = profileNameRaw + ` (unbekannt, ${channelLabel})`;
}
const key = channelLabel + "|" + iniPath + "|" + profileNameRaw;
if (addedKeys.has(key)) continue;
addedKeys.add(key);
addProfileItem(aDocument, menupopup, niceName, profileNameRaw, exePath, iconURI);
}
} catch (e) {
console.error("[PROFILSTARTER] INI Fehler (" + channelLabel + "):", e);
addProfileItem(aDocument, menupopup,
`❌ ${channelLabel}: INI Fehler`,
"",
null,
null
);
}
}
function buildPopupIfNeeded() {
const button = document.getElementById(btn_id);
if (!button) return null;
if (button.getAttribute("profiles-menu-built") === "true") {
return document.getElementById(POPUP_ID);
}
const xulNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
let popup = document.getElementById(POPUP_ID);
if (!popup) {
popup = document.createElementNS(xulNS, "menupopup");
popup.setAttribute("id", POPUP_ID);
button.appendChild(popup);
} else {
while (popup.firstChild) popup.removeChild(popup.firstChild);
}
const addedKeys = new Set();
// Stable/Beta/Nightly
for (const inst of FIREFOX_INSTANCES) {
loadProfilesWithNiceNames(
document,
popup,
inst.iniPath,
inst.exePath,
inst.channelLabel,
addedKeys
);
}
// Portable U (Originalteil)
addProfileItem(document, popup,
"Portable U Nightly 3 🔥", "profile",
"G:\\Portable.Firefox.Updater.3\\Firefox Nightly x64 Launcher.exe",
"file:///C:/FoxIcons/Nightly.png"
);
addProfileItem(document, popup,
"️Portable U Stable 3 🔥 ", "profile",
"G:\\Portable.Firefox.Updater.3\\Firefox Stable x64 Launcher.exe",
"file:///C:/FoxIcons/Finale.png"
);
addProfileItem(document, popup,
"️Portable U Beta 3 🔥 ", "profile",
"G:\\Portable.Firefox.Updater.3\\Firefox Beta x64 Launcher.exe",
"file:///C:/FoxIcons/Beta.png"
);
addProfileItem(document, popup,
"Portable U Nightly 1 🔥", "profile",
"G:\\Portable.Firefox.Updater.1\\Firefox Nightly x64 Launcher.exe",
"file:///C:/FoxIcons/Nightly.png"
);
addProfileItem(document, popup,
"️Portable U Stable 1 🔥 ", "profile",
"G:\\Portable.Firefox.Updater.1\\Firefox Stable x64 Launcher.exe",
"file:///C:/FoxIcons/Finale.png"
);
addProfileItem(document, popup,
"️Portable U Beta 1 🔥 ", "profile",
"G:\\Portable.Firefox.Updater.1\\Firefox Beta x64 Launcher.exe",
"file:///C:/FoxIcons/Beta.png"
);
addProfileItem(document, popup,
"Portable U Nightly 2 🔥", "profile",
"G:\\Portable.Firefox.Updater.2\\Firefox Nightly x64 Launcher.exe",
"file:///C:/FoxIcons/Nightly.png"
);
addProfileItem(document, popup,
"️Portable U Stable 2 🔥 ", "profile",
"G:\\Portable.Firefox.Updater.2\\Firefox Stable x64 Launcher.exe",
"file:///C:/FoxIcons/Finale.png"
);
addProfileItem(document, popup,
"️Portable U Beta 2 🔥 ", "profile",
"G:\\Portable.Firefox.Updater.2\\Firefox Beta x64 Launcher.exe",
"file:///C:/FoxIcons/Beta.png"
);
addProfileItem(document, popup,
"Portable U Nightly 4 🔥", "profile",
"G:\\Portable.Firefox.Updater.4\\Firefox Nightly x64 Launcher.exe",
"file:///C:/FoxIcons/Nightly.png"
);
addProfileItem(document, popup,
"️Portable U Stable 4 🔥 ", "profile",
"G:\\Portable.Firefox.Updater.4\\Firefox Stable x64 Launcher.exe",
"file:///C:/FoxIcons/Finale.png"
);
addProfileItem(document, popup,
"️Portable U Beta 4 🔥 ", "profile",
"G:\\Portable.Firefox.Updater.4\\Firefox Beta x64 Launcher.exe",
"file:///C:/FoxIcons/Beta.png"
);
button.setAttribute("profiles-menu-built", "true");
return popup;
}
function click_button() {
let button = document.getElementById(btn_id);
if (!button) return;
if (button.hasAttribute("listener-added"))
return;
button.setAttribute("listener-added", "true");
// Kontextmenü unterdrücken
button.addEventListener("contextmenu", event => {
event.preventDefault();
});
// Klick: Popup öffnen (links oder rechts)
button.addEventListener('click', event => {
event.preventDefault();
event.stopPropagation();
injectUserCSS();
let popup = buildPopupIfNeeded();
if (!popup) return;
try {
popup.openPopup(button, "after_start", 0, 0, false, false);
} catch (e) {
console.error("[PROFILSTARTER] openPopup Fehler:", e);
}
});
}
// Widget anlegen (mit Logging statt stummem Catch!)
function ensureWidget() {
try {
if (!window.CustomizableUI) {
console.error("[PROFILSTARTER] CustomizableUI nicht verfügbar.");
return;
}
const existing = window.CustomizableUI.getWidget
? window.CustomizableUI.getWidget(btn_id)
: null;
if (existing) {
console.log("[PROFILSTARTER] Widget existiert bereits:", btn_id);
return;
}
console.log("[PROFILSTARTER] Erstelle Widget:", btn_id);
CustomizableUI.createWidget({
id: btn_id,
defaultArea: CustomizableUI.AREA_NAVBAR,
label: btn_label,
tooltiptext: btn_tooltiptext,
onCreated: (this_button) => {
try {
this_button.style.listStyleImage = 'url("' + ImagePath + '")';
this_button.style.minWidth = 'fit-content';
} catch (e) {
console.error("[PROFILSTARTER] onCreated style Fehler:", e);
}
console.log("[PROFILSTARTER] Widget onCreated OK:", btn_id);
}
});
} catch (e) {
console.error("[PROFILSTARTER] Widget FEHLER:", e);
}
}
// Listener pro Fenster setzen
function initForWindow() {
// Erst Widget erzwingen
ensureWidget();
if (window.readyState !== "loading") {
setTimeout(click_button, 300);
} else {
window.addEventListener("DOMContentLoaded", () => setTimeout(click_button, 300));
}
}
initForWindow();
window.addEventListener('aftercustomization', () => {
setTimeout(() => click_button(), 100);
});
})();
Alles anzeigen
Was du nur noch anpassen musst•Trage in FIREFOX_INSTANCES die 3 iniPath-Pfade und 3 exePath-Pfade ein (Stable/Beta/Nightly).