Installationsassistent

GUI-Programmer

Top Contributor
Hallo zusammen!

Immer wieder kommt es einmal vor, dass es sich lohnt für sein Programm einen Installationassistenten zu schreiben. Bisher habe ich mir schon 2 mal einen "Installer" für jeweils ein Programm geschreiben. Dabei ist mir aufgefallen, dass das "Grundgerüst" der GUI des Installers in beiden Fällen ziemlich ähnlich ist. Somit ist die GUI des 2. Programmes auch des Öfteren durch nerviges COPY & PAST entstanden.

Zudem bin ich hier im Forum auf diese Seite gestoßen. Allerdings gefällt mir persönlich dieser Assistent dort optisch nicht sehr. Also habe ich mir selbst einen Installationsassistenten, bzw. eine Art Vorlage für einen solchen Assistenten geschrieben.


Gleich mal vorweg:
  • Kritik und Verbesserungsvorschläge sind sehr erwünscht :)autsch: & :toll:), denn schließlich soll das Programm ja hier als Vorlage (=Entwurf) dienen
  • Das die Klasse nicht direkt von JFrame erbt ist Absicht, damit es bei der Verwendung übersichtlich bleibt und nicht jede Menge deprectated - Methoden entstehen
  • Das Programm wird selbstverständlich irgendwann später vollständig mit Kommentaren versehen, bzw. übersichtlicher gemacht, sowie eine Jar erzeugt und hier angehängt, welche dann in ein Programm einfach eingebunden werden kann

Hier der Installationsassistent, welcher nur aus einer Klasse besteht:
Java:
package com;

import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import com.jgoodies.forms.layout.ColumnSpec;
import com.jgoodies.forms.layout.FormLayout;
import com.jgoodies.forms.layout.RowSpec;

/**
 * Klasse InstallWizard
 * 
 * Diese Klasse ermöglicht es einen einfachen Installationsassistenten zu
 * erstellen.
 * 
 * @author GUI-Programmer
 * @version 27.01.2012
 */
public class InstallWizard {
	public static final int DEUTSCH = 0;
	public static final int ENGLISH = 1;
	
	private Controller controller;
	
	private String textNext, textBtnBack, textBtnNext, textBtnCancel, textBtnFinish, textFinishTitle;
	private Font fontButtons, fontHeadlines;
	
	private JFrame frame;
	
	private JPanel pnlWelcome;
	private WelcomeImage imgWelcome;
	private JLabel lblWelcomeTitle;
	private JEditorPane edtrpnWelcomeText;
	private JButton btnNextWelcome;
	private JButton btnCancelWelcome;
	
	private JPanel pnlFinish;
	private JButton btnFinish;
	private JPanel pnlInnerFinish;
	
	private List<JPanel> listPages;
	private List<JButton> listBackButtons, listNextButtons, listCancelButtons;
	
	public InstallWizard() {
		this(InstallWizard.DEUTSCH);
	}
	
	public InstallWizard(int language) {
		this("", language);
	}
	
	public InstallWizard(String title, int language) {
		switch(language) {
			case 0: {
				textNext = "Drücken Sie 'Weiter' um fortzufahren...";
				textBtnBack = "Zurück";
				textBtnNext = "Weiter";
				textBtnCancel = "Abbrechen";
				textBtnFinish = "Fertigstellen";
				textFinishTitle = "Installation abgeschlossen!";
				break;
			}
			case 1: {
				textNext = "Press 'Next' to continue...";
				textBtnBack = "Back";
				textBtnNext = "Next";
				textBtnCancel = "Cancel";
				textBtnFinish = "Finish";
				textFinishTitle = "Installation finished!";
				break;
			}
		}
		fontButtons = new Font("Tahoma", Font.BOLD, 12);
		fontHeadlines = new Font("Tahoma", Font.BOLD, 16);
		
		listPages = new ArrayList<JPanel>();
		listBackButtons = new ArrayList<JButton>();
		listNextButtons = new ArrayList<JButton>();
		listCancelButtons = new ArrayList<JButton>();
		
		controller = new Controller();
		
		frame = new JFrame(title);
		frame.getContentPane().setLayout(new CardLayout());
	}
	
	// Private methods
	private JPanel createSouthPanel() {
		JPanel pnlSouth = new JPanel();
		pnlSouth.setBorder(BorderFactory.createMatteBorder(1, 0, 0, 0, Color.BLUE));
		pnlSouth.setOpaque(false);
		pnlSouth.setPreferredSize(new Dimension(600, 45));
		pnlSouth.setLayout(new FormLayout(
			new ColumnSpec[] {
					ColumnSpec.decode("12px"),
					ColumnSpec.decode("1px:grow"),
					ColumnSpec.decode("75px"),
					ColumnSpec.decode("12px"),
					ColumnSpec.decode("75px"),
					ColumnSpec.decode("50px"),
					ColumnSpec.decode("110px"),
					ColumnSpec.decode("12px")
			},
			new RowSpec[] {
					RowSpec.decode("45px")
			}
		));
		return pnlSouth;
	}
	
	public void createWelcomePanel() {
		pnlWelcome = new JPanel();
		pnlWelcome.setOpaque(false);
		pnlWelcome.setLayout(new BorderLayout(0, 0));
		
		JPanel pnlCenter = new JPanel();
		pnlCenter.setOpaque(false);
		pnlCenter.setLayout(new FormLayout(
			new ColumnSpec[] {
				ColumnSpec.decode("5px"),
				ColumnSpec.decode("1px:grow"),
				ColumnSpec.decode("20px"),
				ColumnSpec.decode("1px:grow"),
				ColumnSpec.decode("1px:grow"),
				ColumnSpec.decode("1px:grow"),
				ColumnSpec.decode("1px:grow"),
				ColumnSpec.decode("20px")
			},
			new RowSpec[] {
				RowSpec.decode("5px"),
				RowSpec.decode("12px"),
				RowSpec.decode("20px"),
				RowSpec.decode("12px"),
				RowSpec.decode("1px:grow"),
				RowSpec.decode("12px"),
				RowSpec.decode("5px")
			}
		));
		
		imgWelcome = new WelcomeImage();
		pnlCenter.add(imgWelcome, "2, 2, 1, 5, fill, fill");
		
		lblWelcomeTitle = new JLabel();
		lblWelcomeTitle.setFont(fontHeadlines);
		pnlCenter.add(lblWelcomeTitle, "4, 3, 4, 1, fill, fill");
		
		edtrpnWelcomeText = new JEditorPane();
		edtrpnWelcomeText.setFont(new Font("Tahoma", Font.PLAIN, 14));
		edtrpnWelcomeText.setBorder(null);
		edtrpnWelcomeText.setOpaque(false);
		edtrpnWelcomeText.setForeground(Color.BLACK);
		edtrpnWelcomeText.setDisabledTextColor(Color.BLACK);
		edtrpnWelcomeText.setEnabled(false);
		edtrpnWelcomeText.setText("\n\n"+textNext);
		pnlCenter.add(edtrpnWelcomeText, "4, 5, 4, 1, fill, fill");
		
		pnlWelcome.add(pnlCenter, BorderLayout.CENTER);
		
		JPanel pnlSouth = createSouthPanel();
		
		btnCancelWelcome = new JButton(textBtnCancel);
		btnCancelWelcome.setPreferredSize(new Dimension(110, 28));
		btnCancelWelcome.setFont(fontButtons);
		btnCancelWelcome.addActionListener(controller);
		pnlSouth.add(btnCancelWelcome, "7, 1, fill, center");
		
		btnNextWelcome = new JButton(textBtnNext);
		btnNextWelcome.setPreferredSize(new Dimension(75, 28));
		btnNextWelcome.setFont(fontButtons);
		btnNextWelcome.addActionListener(controller);
		pnlSouth.add(btnNextWelcome, "5, 1, fill, center");
		
		pnlWelcome.add(pnlSouth, BorderLayout.SOUTH);
		
		frame.getContentPane().add(pnlWelcome, "Welcome");
	}
	
	public void createFinishPanel() {
		pnlFinish = new JPanel();
		pnlFinish.setOpaque(false);
		pnlFinish.setLayout(new BorderLayout(0, 0));
		
		JPanel pnlCenter = new JPanel();
		pnlCenter.setOpaque(false);
		pnlCenter.setLayout(new FormLayout(
			new ColumnSpec[] {
					ColumnSpec.decode("20px"),
					ColumnSpec.decode("1px:grow"),
					ColumnSpec.decode("20px")
			},
			new RowSpec[] {
					RowSpec.decode("17px"),
					RowSpec.decode("20px"),
					RowSpec.decode("12px"),
					RowSpec.decode("1px:grow"),
					RowSpec.decode("30px"),
			}
		));
		JLabel lblFinishTitle = new JLabel(textFinishTitle);
		lblFinishTitle.setFont(fontHeadlines);
		pnlCenter.add(lblFinishTitle, "2, 2, fill, fill");
		
		pnlInnerFinish = new JPanel();
		pnlInnerFinish.setOpaque(false);
		pnlCenter.add(pnlInnerFinish, "2, 4, fill, fill");
		
		pnlFinish.add(pnlCenter, BorderLayout.CENTER);
		
		JPanel pnlSouth = createSouthPanel();
		btnFinish = new JButton(textBtnFinish);
		btnFinish.setPreferredSize(new Dimension(110, 28));
		btnFinish.setFont(fontButtons);
		btnFinish.addActionListener(controller);
		pnlSouth.add(btnFinish, "7, 1, fill, center");
		
		pnlFinish.add(pnlSouth, BorderLayout.SOUTH);
		
		frame.getContentPane().add(pnlFinish, "Finish");
	}
	
	
	// Private Klassen
	@SuppressWarnings("serial")
	private class WelcomeImage extends JPanel {
		private Image image;
		
		public Image getImage() {
			return image;
		}
		
		public void setImage(Image image) {
			this.image = image;
			repaint();
		}
		
		protected void paintComponent(Graphics g) {
			super.paintComponent(g);
			if(image != null) {
				g.drawImage(image, 0, 0, getWidth(), getHeight(), this);
			}
		}
	}
	
	private class Controller implements ActionListener {
		@Override
		public void actionPerformed(ActionEvent evt) {
			Object src = evt.getSource();
			if(src.equals(btnNextWelcome)) {
				welcomeNextButtonActionPerformed(evt);
			} else if(src.equals(btnCancelWelcome)) {
				welcomeCancelButtonActionPerformed(evt);
			} else if(src.equals(btnFinish)) {
				finishButtonActionPerformed(evt);
			} else {
				for(int i=0; i<listBackButtons.size(); i++) {
					if(src.equals(listBackButtons.get(i))) {
						backButtonActionPerformed((i+1), evt);
					}
				}
				for(int i=0; i<listNextButtons.size(); i++) {
					if(src.equals(listNextButtons.get(i))) {
						nextButtonActionPerformed((i+1), evt);
					}
				}
				for(int i=0; i<listCancelButtons.size(); i++) {
					if(src.equals(listCancelButtons.get(i))) {
						cancelButtonActionPerformed((i+1), evt);
					}
				}
			}
		}
	}
	
	
	// Protected methods
	protected void welcomeCancelButtonActionPerformed(ActionEvent evt) {
		System.exit(0);
	}
	
	protected void welcomeNextButtonActionPerformed(ActionEvent evt) {
		try {
			showPage(1);
		} catch(Exception ex) {
			showFinishPage();
		}
	}
	
	protected void finishButtonActionPerformed(ActionEvent evt) {
		System.exit(0);
	}
	
	protected void backButtonActionPerformed(int page, ActionEvent evt) {
		try {
			showPage((page-1));
		} catch(Exception ex) {
			showWelcomePage();
		}
	}
	
	protected void nextButtonActionPerformed(int page, ActionEvent evt) {
		
		try {
			showPage((page+1));
		} catch(Exception ex) {
			showFinishPage();
		}
	}
	
	protected void cancelButtonActionPerformed(int page, ActionEvent evt) {
		System.exit(0);
	}
	
	
	// Public methods
	public void addPage(JPanel page) {
		JPanel pnlContent = new JPanel(new BorderLayout(0, 0));
		pnlContent.setOpaque(false);
		
		pnlContent.add(page, BorderLayout.CENTER);
		listPages.add(page);
		
		JPanel pnlSouth = createSouthPanel();
		
		JButton btnBack = new JButton(textBtnBack);
		btnBack.setPreferredSize(new Dimension(75, 28));
		btnBack.setFont(fontButtons);
		btnBack.addActionListener(controller);
		pnlSouth.add(btnBack, "3, 1, fill, center");
		listBackButtons.add(btnBack);
		
		JButton btnNext = new JButton(textBtnNext);
		btnNext.setPreferredSize(new Dimension(75, 28));
		btnNext.setFont(fontButtons);
		btnNext.addActionListener(controller);
		pnlSouth.add(btnNext, "5, 1, fill, center");
		listNextButtons.add(btnNext);
		
		JButton btnCancel = new JButton(textBtnCancel);
		btnCancel.setPreferredSize(new Dimension(110, 28));
		btnCancel.setFont(fontButtons);
		btnCancel.addActionListener(controller);
		pnlSouth.add(btnCancel, "7, 1, fill, center");
		listCancelButtons.add(btnCancel);
		
		pnlContent.add(pnlSouth, BorderLayout.SOUTH);
		
		frame.getContentPane().add(pnlContent, ("Page "+listPages.size()));
	}
	
	public void setBackButtonEnabled(int page, boolean enabled) {
		int index = page - 1;
		listBackButtons.get(index).setEnabled(enabled);
	}
	
	public boolean isBackButtonEnabled(int page, boolean enabled) {
		int index = page - 1;
		return listBackButtons.get(index).isEnabled();
	}

	public void setNextButtonEnabled(int page, boolean enabled) {
		int index = page - 1;
		listNextButtons.get(index).setEnabled(enabled);
	}
	
	public boolean isNextButtonEnabled(int page, boolean enabled) {
		int index = page - 1;
		return listNextButtons.get(index).isEnabled();
	}
	
	public void setCancelButtonEnabled(int page, boolean enabled) {
		int index = page - 1;
		listCancelButtons.get(index).setEnabled(enabled);
	}
	
	public Color getBackground() {
		return frame.getContentPane().getBackground();
	}
	
	public boolean isCancelButtonEnabled(int page, boolean enabled) {
		int index = page - 1;
		return listCancelButtons.get(index).isEnabled();
	}
	
	public int getDefaultCloseOperation() {
		return frame.getDefaultCloseOperation();
	}
	
	public void setDefaultCloseOperation(int operation) {
		frame.setDefaultCloseOperation(operation);
	}
	
	public void setSize(int width, int height) {
		frame.setSize(width, height);
	}
	
	public int getWidth() {
		return frame.getWidth();
	}
	
	public int getHeight() {
		return frame.getHeight();
	}
	
	public void setContentSize(int width, int height) {
		frame.getContentPane().setPreferredSize(new Dimension(width, height));
	}
	
	public int getContentWidth() {
		return frame.getContentPane().getWidth();
	}
	
	public int getContentHeight() {
		return frame.getContentPane().getHeight();
	}
	
	public void pack() {
		frame.pack();
	}
	
	public String getTitle() {
		return frame.getTitle();
	}
	
	public void setTitle(String title) {
		frame.setTitle(title);
	}
	
	public Image getWelcomeImage() {
		return imgWelcome.getImage();
	}
	
	public void setWelcomeImage(Image image) {
		imgWelcome.setImage(image);
	}
	
	public String getWelcomeTitle() {
		return lblWelcomeTitle.getText();
	}
	
	public void setWelcomeTitle(String title) {
		lblWelcomeTitle.setText(title);
	}
	
	public String getWelcomeText() {
		String text = edtrpnWelcomeText.getText();
		int length = ("\n\n"+textNext).length();
		int endIndex = text.length()-length-1;
		text = text.substring(0, endIndex);
		return text;
	}
	
	public void setWelcomeText(String text) {
		edtrpnWelcomeText.setText(text+"\n\n"+textNext);
	}
	
	public JPanel getInnerFinishPanel() {
		return pnlInnerFinish;
	}
	
	public void setInnerFinishPanel(JPanel pnlInnerFinish) {
		Container parent = this.pnlInnerFinish.getParent();
		parent.remove(this.pnlInnerFinish);
		parent.add(pnlInnerFinish, "2, 4, fill, fill");
		parent.repaint();
		parent.validate();
	}
	
	public Image getIconImage() {
		return frame.getIconImage();
	}
	
	public void setIconImage(Image image) {
		frame.setIconImage(image);
	}
	
	public void setVisible(boolean visible) {
		frame.setVisible(visible);
	}
	
	public boolean isVisible() {
		return frame.isVisible();
	}
	
	public Dimension getMaximumSize() {
		return frame.getMaximumSize();
	}
	
	public void setMaximumSize(Dimension maximumSize) {
		frame.setMaximumSize(maximumSize);
	}
	
	public Dimension getMinimumSize() {
		return frame.getMinimumSize();
	}
	
	public void setMinimumSize(Dimension minimumSize) {
		frame.setMinimumSize(minimumSize);
	}
	
	public void setLocationRelativTo(Component c) {
		frame.setLocationRelativeTo(c);
	}
	
	public void setBackground(Color c) {
		frame.getContentPane().setBackground(c);
	}
	
	public void showWelcomePage() {
		CardLayout cardLayout = (CardLayout) frame.getContentPane().getLayout();
		cardLayout.show(frame.getContentPane(), "Welcome");
	}
	
	public void showFinishPage() {
		CardLayout cardLayout = (CardLayout) frame.getContentPane().getLayout();
		cardLayout.show(frame.getContentPane(), "Finish");
	}
	
	public void showPage(int page) {
		if(page<=0) {
			throw new ArrayIndexOutOfBoundsException("page must be more than 0");
		} else if(page>listPages.size()) {
			throw new ArrayIndexOutOfBoundsException("page "+page+" does not exist");
		}
		CardLayout cardLayout = (CardLayout) frame.getContentPane().getLayout();
		cardLayout.show(frame.getContentPane(), ("Page "+page));
	}
	
}

Hier noch eine Klasse zum Testen:
Java:
package com;

import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Image;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;

/**
 * Klasse TestWizard
 * 
 * Diese Klasse dient dazu die Funktionen von InstallWizard zu testen
 * und mögliche Fehler zu finden.
 * 
 * @author GUI-Programmer
 * @version 27.01.2012
 */
public class TestWizard extends InstallWizard {
	
	public TestWizard() {
		try {
			UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
			
		} catch(Exception ex) {
			ex.printStackTrace();
		}
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setContentSize(600, 400);
		
		createWelcomePanel();
		createFinishPanel();
		
		Image image = null;
		try {
			image = ImageIO.read(TestWizard.class.getResource("Schlamm.jpg"));
		} catch(IOException ex) {
			ex.printStackTrace();
		}
		setWelcomeImage(image);
		setWelcomeTitle("Herzlich Wilkommen im Installation Assistent!");
		String text = "";
		for(int i=0; i<8; i++) {
			text = text+"Some stupid text stays here. Don't read it!!! ";
		}
		setWelcomeText(text);
		
		JPanel panel1 = new JPanel();
		panel1.setBackground(Color.RED);
		addPage(panel1);
		
		JPanel panel2 = new JPanel();
		panel2.setBackground(Color.YELLOW);
		addPage(panel2);
		
		JPanel panel3 = new JPanel();
		panel3.setBackground(Color.GREEN);
		addPage(panel3);
		
		JPanel panel4 = new JPanel();
		panel4.setBackground(Color.BLUE);
		addPage(panel4);
		
		JPanel panelFinish = new JPanel();
		panelFinish.setBackground(Color.WHITE);
		setInnerFinishPanel(panelFinish);
		
		pack();
		setLocationRelativTo(null);
		setVisible(true);
	}

	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			@Override
			public void run() {
				new TestWizard();
			}
		});
	}
}

Noch ein paar Fragen:
  • Kann man bei einer Methode irgendwie im Kommtar speziell darauf aufmerksam machen, dass hier eventuell eine Überschreibung sinnvol wäre, oder kann man das, so wie ich das hier beschreibe, einfach selbst kommentieren? Beispielmethoden:
    Code:
    welcomeCancelButtonActionPerformed(ActionEvent evt)
    ,
    Code:
    backButtonActionPerformed(int page, ActionEvent evt)
    , etc. (alle protected - Methoden)
  • Gibt es eine Möglichkeit eine LookAndFeel - Änderung zu regestrieren? Denn wenn Ja, dann wäre es sinnvoller die Methoden
    Code:
    createWelcomePanel()
    sowie
    Code:
    createFinishPanel()
    bereits im Konstruktor von InstallWizard aufzurufen.

Hier noch das dazugehörige Testbild:
 

Tobias

Top Contributor
Immer dann, wenn eine Klasse quasi nur als Schablone für konkrete Implementierungen herhalten soll, bietet sich das Template-Method-Pattern und die Verwendung von abstract an. Damit wird der Implementierer dazu _gezwungen_ deine Methoden zu überschreiben, ganz ohne KOmmentare lesen zu müssen - was die meisten eh nur im Notfall tun.

mpG
Tobias
 

GUI-Programmer

Top Contributor
Zwar ist es schon etwas her, aber ich habe den Code noch etwas angepasst und eine (ausführbare) jar erstellt, die man einfach in sein Projekt einbinden kann. Dennoch ist der Code nicht vollständig auskommentiert - aber die Methodennamen sollten eigentlich für sich sprechen.

Auserdem noch was Nützliches (gilt nur für Windows):

Die ausführbare Jar des fertigen Installtionsassistenten kann man per NSIS von einer .exe, die Admine Rechte hat, die für gewöhnlich benötigt werden, aus Aufrufen.
Test-NSI-Skript:
Code:
Name "Installation eines Programmes"   
Caption "Installtion"    
Icon "Icon.ico"    
OutFile "setup.exe"
  
RequestExecutionLevel admin

SilentInstall silent
AutoCloseWindow true
ShowInstDetails show

Section ""    
  StrCpy $0 'Java\jre7\bin\javaw.exe -jar installation.jar'      
  SetOutPath $EXEDIR    
  Exec $0    
SectionEnd

Desktopverknüpfung erstellen per VBS-Skript:
Java:
public void createDesktopShortcut(String path) {
	try {
		String programName = "Das Super-Programm";
		
		File fileVbs = new File(System.getenv("Temp")+separator+"Create Desktop Shortcut.vbs");
		fileVbs.createNewFile();
		
		BufferedWriter bw = new BufferedWriter(new FileWriter(fileVbs));
		bw.write("set WshShell = WScript.CreateObject(\"WScript.Shell\")"); bw.newLine();
		bw.write("set fso = CreateObject(\"Scripting.FileSystemObject\")"); bw.newLine();
		bw.write("set file = fso.GetFile(\""+fileVbs.getAbsolutePath()+"\")"); bw.newLine();
		bw.write("strDesktop = WshShell.SpecialFolders(\"Desktop\") "); bw.newLine();
		bw.write("set oShellLink = WshShell.CreateShortcut(strDesktop & \""+separator+programName+".lnk\")"); bw.newLine();
		bw.write("oShellLink.TargetPath = \""+path+separator+programName+".jar"+"\""); bw.newLine();
		bw.write("oShellLink.WindowStyle = 1"); bw.newLine();
		bw.write("oShellLink.IconLocation = \""+path+separator+"Icon.ico\""); bw.newLine();
		bw.write("oShellLink.Description = \""+programName+"\""); bw.newLine();
		bw.write("oShellLink.Save"); bw.newLine();
		bw.write("file.Delete");
		bw.flush();
		bw.close();
		
		Desktop.getDesktop().open(fileVbs);
	} catch(Exception ex) {
		ex.printStackTrace();
	}
}

Ebenso ähnlich einen Eintrag im Startmenü erstellen:
Java:
public void createStartMenuEntery(String path) {
	try {
		String programName = "Das Super-Programm";
	
		File fileVbs = new File(System.getenv("Temp")+separator+"Create Startmenu Entery.vbs");
		fileVbs.createNewFile();
		
		BufferedWriter bw = new BufferedWriter(new FileWriter(fileVbs));
		bw.write("set WshShell = WScript.CreateObject(\"WScript.Shell\")"); bw.newLine();
		bw.write("set fso = CreateObject(\"Scripting.FileSystemObject\")"); bw.newLine();
		bw.write("set file = fso.GetFile(\""+fileVbs.getAbsolutePath()+"\")"); bw.newLine();
		bw.write("strStartmenu = WshShell.SpecialFolders(\"StartMenu\") "); bw.newLine();
		bw.write("set oShellLink = WshShell.CreateShortcut(strStartmenu & \""+separator+programName+".lnk\")"); bw.newLine();
		bw.write("oShellLink.TargetPath = \""+path+separator+programName+".jar"+"\""); bw.newLine();
		bw.write("oShellLink.WindowStyle = 1"); bw.newLine();
		bw.write("oShellLink.IconLocation = \""+path+separator+"Icon.ico\""); bw.newLine();
		bw.write("oShellLink.Description = \""+programName+"\""); bw.newLine();
		bw.write("oShellLink.Save"); bw.newLine();
		bw.write("file.Delete");
		bw.flush();
		bw.close();
		
		Desktop.getDesktop().open(fileVbs);
	} catch(Exception ex) {
		ex.printStackTrace();
	}
}

Das anschließende ausführen des Programms kann ganz einfach per
Code:
Runtime.getRuntime().exec(...)
oder per ProcessBuilder erfüllt werden.
 

Anhänge

  • Installation Wizard.jar
    187,5 KB · Aufrufe: 25

turtle

Top Contributor
Ich habe mal, vor langer Zeit, einen Installer mit dem Tool izPack erstellt.

Damit formuliert man die Installation in einer XML-Datei, kompiliert diese zu einer installer.jar und kann diese an den Endbenutzer verteilen.

Praktisch alle Teilschritte können modifiziert werden oder neue Schritte definiert werden.

Beispielsweise gibt es das Shortcut-Panel, mit dem Desktop-Shortcuts definiert und eingerichtet werden können.

Weiterhin evaluiert hatte ich den Java Application Installer. Sah recht interessant aus, hatte aber den Nachteil, das ich nicht einen komplett neuen Schritt hinzufügen konnte.
 
Zuletzt bearbeitet:

Neue Themen


Oben