7zip cmd extracting using ProcessBuilder in java - java

I have a problem extracting an archive to the desired category using Java 10 ProcessBuilder and 7z.exe (18.05) with command line. The exact same command works as intended when I use Windows CMD, but no longer functions when issued by my JavaFX application using ProcessBuilder:
public static void decompress7ZipEmbedded(File source, File destination) throws IOException, InterruptedException {
ProcessBuilder pb = new ProcessBuilder(
getSevenZipExecutablePath(),
EXTRACT_WITH_FULL_PATHS_COMMAND,
quotifyPath(source.getAbsolutePath()),
OUTPUT_DIRECTORY_SWITCH + quotifyPath(destination.getAbsolutePath())
);
processWithSevenZipEmbedded(pb);
}
private static void processWithSevenZipEmbedded(ProcessBuilder pb) throws IOException, InterruptedException {
LOG.info("7-zip command issued: " + String.join(" ", pb.command()));
Process p = pb.start();
new Thread(new InputConsumer(p.getInputStream())).start();
System.out.println("Exited with: " + p.waitFor());
}
public static class InputConsumer implements Runnable {
private InputStream is;
InputConsumer(InputStream is) {
this.is = is;
}
#Override
public void run() {
try {
int value = -1;
while ((value = is.read()) != -1) {
System.out.print((char) value);
}
} catch (IOException exp) {
exp.printStackTrace();
}
LOG.debug("Output stream completed");
}
}
public static String getSevenZipExecutablePath() {
return FileUtil.quotifyPath(getDirectory() + "7z" + "/" + "7z");
}
public static String quotifyPath(String path) {
return '"' + path + '"';
}
public class Commands {
public static final String EXTRACT_COMMAND = "e";
public static final String EXTRACT_WITH_FULL_PATHS_COMMAND = "x";
public static final String PACK_COMMAND = "a";
public static final String DELETE_COMMAND = "d";
public static final String BENCHMARK_COMMAND = "b";
public static final String LIST_COMMAND = "l";
}
public class Switches {
public static final String OUTPUT_DIRECTORY_SWITCH = "-o";
public static final String RECURSIVE_SWITCH = "-r";
public static final String ASSUME_YES = "y";
}
The command looks like this:
"C:/Users/blood/java_projects/AppRack/target/classes/7z/7z" x "D:\Pulpit\AppRack Sandbox\test\something\Something 2\Something2.7z" -o"D:\Pulpit\AppRack Sandbox\Something2"
And the output from ProcessBuilder:
7-Zip 18.05 (x64) : Copyright (c) 1999-2018 Igor Pavlov : 2018-04-30
Scanning the drive for archives:
1 file, 59177077 bytes (57 MiB)
Extracting archive: D:\Pulpit\AppRack Sandbox\test\Something\Something 2\Something2.7z
--
Path = D:\Pulpit\AppRack Sandbox\test\Something\Something 2\Something2.7z
Type = 7z
Physical Size = 5917Exited with: 0
7077
Headers Size = 373
Method = LZMA2:26 LZMA:20 BCJ2
Solid = +
Blocks = 2
No files to process
Everything is Ok
Files: 0
Size: 0
Compressed: 59177077
It doesn't do ANYTHING. Doesn't create a desired folder, nothing. Using CMD it works like a charm (here log from Windows 10 CMD using the same command):
7-Zip 18.05 (x64) : Copyright (c) 1999-2018 Igor Pavlov : 2018-04-30
Scanning the drive for archives:
1 file, 59177077 bytes (57 MiB)
Extracting archive: D:\Pulpit\AppRack Sandbox\test\Something\Something 2\Something2.7z
--
Path = D:\Pulpit\AppRack Sandbox\test\Something\Something 2\Something2.7z
Type = 7z
Physical Size = 59177077
Headers Size = 373
Method = LZMA2:26 LZMA:20 BCJ2
Solid = +
Blocks = 2
Everything is Ok
Folders: 1
Files: 5
Size: 64838062
Compressed: 59177077
Do you have any idea what causes a difference here and why it says "No files to process, everything is ok" without doing anything? I've tried already to create a folder first using File class but it doesn't seem to be an issue because the results are the same whether the destination folder exists prior to extracting or not.
I've already tried everything that has come to my mind and I run out of ideas at the moment. Please share with me any suggestions that you may have regarding this issue. Thanks a lot.

Thank you very much for your help.
Don’t quote your arguments. Quotes are for the command shell’s benefit. ProcessBuilder is not a command shell; it executes a command directly, so any quotes are seen as part of the argument itself (that is, the file name). Also, pb.inheritIO(); is a better way to see the output of the child process than manually consuming process streams.
Thank you #VGR it seemed to be the issue - after I remove the method to quote paths in the mentioned command it works like a charm and extracting archive without any problem! So the conclusion is I shouldn't have used quotes in paths while using Java ProcessBuilder.
I've also used pb.inheritIO() and you are right it is much better and easier to manage it this way.
public static void decompress7ZipEmbedded(File source, File destination) throws IOException {
ProcessBuilder pb = new ProcessBuilder().inheritIO().command(
getSevenZipExecutablePath(),
EXTRACT_WITH_FULL_PATHS_COMMAND,
source.getAbsolutePath(),
OUTPUT_DIRECTORY_SWITCH + destination.getAbsolutePath(),
OVERWRITE_WITHOUT_PROMPT
);
processWithSevenZipEmbedded(pb);
}
private static void processWithSevenZipEmbedded(ProcessBuilder pb) throws IOException {
LOG.info("7-zip command issued: " + String.join(" ", pb.command()));
pb.start();
}
public class Commands {
public static final String EXTRACT_WITH_FULL_PATHS_COMMAND = "x";
}
public class Switches {
public static final String OUTPUT_DIRECTORY_SWITCH = "-o";
public static final String OVERWRITE_WITHOUT_PROMPT = "-aoa";
}
Double click on file 7zip.chm or start 7-Zip and open the Help and read the help page Command Line Version - Syntax with first line 7z [...] [...]. There is clearly explained that first the command x must be specified, next should be the switches like -o with best last switch being --, then the archive file name and last further arguments like names of files/folders to extract. Switches can be also specified after archive file name, but that is not recommended although examples on help page for -o are also with -o at end.
Thank you #Mofi for the tip. I used -aoa switch instead of -y and it finally started to work as I wanted - to overwrite files without any prompt. I left the rest of the command the way it was as it works as intended, so it finally looks like this:
C:/Users/blood/java_projects/AppRack/target/classes/7z/7z" x D:\Pulpit\AppRack Sandbox\test\Test\Test 2\Test.7z -oD:\Desktop\AppRack Sandbox\Test 2 -aoa
Thanks a lot for help once again!

Related

Java - How can i request Administrator privileges during runtime? [duplicate]

A nasty problem popped out with my software. I am making a program that interacts with another existing software (a game). User has reported that he runs the game with administrator privileges and under that circumstances, my program stops working for him.
Short investigation revealed that some people really need to run the game under administrator account and some don't. It would be great if my program would be able to detect this and warn user if the game is running under administrator account:
If the user clicks "Elevate", I'd like to ask windows to elevate the java.exe running my jar file and invoke the typical UAC dialog.
Obviously, this time the question would not be about java updater but JRE
My question is: Is this possible? Can windows elevate my java.exe instance's privilege? Does java have a way to do it? Or can I use command line command?
I want to avoid restarting the program (though it wouldn't probably be such a big deal).
Edit:
If you look in the comments, you'll see that there's no avoiding the restart of an application - process can only start elevated, not become elevated. This kinda shifts the question, unfortunately. Basically, it now sounds more like: "How to restart my application with admin rights?". Unless, of course, there's a trick like two java.exe sharing one jar...
If still of interest: In Windows 7 my JavaElevator works. It elevates a running Java process when used in the main method of the Java application. Simply add -elevate as last program parameter and use the elevator in the main method.
The elevator class:
package test;
import com.sun.jna.Native;
import com.sun.jna.platform.win32.Kernel32;
import com.sun.jna.platform.win32.Kernel32Util;
import com.sun.jna.platform.win32.ShellAPI;
import com.sun.jna.platform.win32.WinDef;
/**
* Elevates a Java process to administrator rights if requested.
*/
public class JavaElevator {
/** The program argument indicating the need of being elevated */
private static final String ELEVATE_ARG = "-elevate";
/**
* If requested, elevates the Java process started with the given arguments to administrator level.
*
* #param args The Java program arguments
* #return The cleaned program arguments
*/
public static String[] elevate(String[] args) {
String[] result = args;
// Check for elevation marker.
boolean elevate = false;
if (args.length > 0) {
elevate = args[args.length - 1].equals(ELEVATE_ARG);
}
if (elevate) {
// Get the command and remove the elevation marker.
String command = System.getProperty("sun.java.command");
command = command.replace(ELEVATE_ARG, "");
// Get class path and default java home.
String classPath = System.getProperty("java.class.path");
String javaHome = System.getProperty("java.home");
String vm = javaHome + "\\bin\\java.exe";
// Check for alternate VM for elevation. Full path to the VM may be passed with: -Delevation.vm=...
if (System.getProperties().contains("elevation.vm")) {
vm = System.getProperty("elevation.vm");
}
String parameters = "-cp " + classPath;
parameters += " " + command;
Shell32.INSTANCE.ShellExecute(null, "runas", vm, parameters, null, 0);
int lastError = Kernel32.INSTANCE.GetLastError();
if (lastError != 0) {
String errorMessage = Kernel32Util.formatMessageFromLastErrorCode(lastError);
errorMessage += "\n vm: " + vm;
errorMessage += "\n parameters: " + parameters;
throw new IllegalStateException("Error performing elevation: " + lastError + ": " + errorMessage);
}
System.exit(0);
}
return result;
}
}
Usage in the main method of the Java application:
public static void main(String[] args) {
String[] args1 = JavaElevator.elevate(args);
if (args1.length > 0) {
// Continue as intended.
...
I know, this is a very basic implementation - sufficient for one of my daily hiccups: Starting an elevated process from Eclipse. But maybe it points someone in some dicrection...
As has been pointed in comments, sadly the Java (or any other process) cannot be elevated while running. While in the case of JWM, it could be theoretically possible to move whole program context from normal user java.exe to elevated one, I don't think it's possible. I hope some day someone will come and tell me I'm wrong.
Surprisingly, even with restart in place, this was a tricky task that took me a while to figure out.
The non java part
First, how do we exactly run a program elevated from command line? There's an answer and you can see it's not simple. But we can break it to this VBS script:
Set UAC = CreateObject("Shell.Application")
UAC.ShellExecute "program name", "command line parameters", "working directory", "runas", 1
Soon, it also turns out that we won't have any success running java.exe from VBS script. In the end, I decided to run a helper batch file. Finally, here (answer to question in the last link) we have a complete set of two scripts which really run the given .jar file elevated. Here's improved version that allows quick testing by drag'n'dropping the Jar file on it:
' Require first command line parameter
if WScript.Arguments.Count = 0 then
MsgBox("Jar file name required.")
WScript.Quit 1
end if
' Get the script location, the directorry where it's running
Set objShell = CreateObject("Wscript.Shell")
strPath = Wscript.ScriptFullName
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.GetFile(strPath)
strFolder = objFSO.GetParentFolderName(objFile)
'MsgBox(strFolder)
' Create the object that serves as runnable something
Set UAC = CreateObject("Shell.Application")
' Args:
' path to executable to run
' command line parameters - first parameter of this file, which is the jar file name
' working directory (this doesn't work but I use it nevertheless)
' runas command which invokes elevation
' 0 means do not show the window. Normally, you show the window, but not this console window
' which just blinks and disappears anyway
UAC.ShellExecute "run-normally.bat", WScript.Arguments(0), strFolder, "runas", 0
WScript.Quit 0
The Java part
Java part is more straightforward. What we need to do is to open new process and execute the prepared scripts in it.
/**
* Start this very jar file elevated on Windows. It is strongly recommended to close any existing IO
* before calling this method and avoid writing anything more to files. The new instance of this same
* program will be started and simultaneous write/write or read/write would cause errors.
* #throws FileNotFoundException if the helper vbs script was not found
* #throws IOException if there was another failure inboking VBS script
*/
public void StartWithAdminRights() throws FileNotFoundException, IOException {
//The path to the helper script. This scripts takes 1 argument which is a Jar file full path
File runAsAdmin = new File("run-as-admin.vbs");;
//Our
String jarPath;
//System.out.println("Current relative path is: " + s);
try {
jarPath = "\""+new File(Main.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath()).getAbsolutePath()+"\"";
} catch (URISyntaxException ex) {
throw new FileNotFoundException("Could not fetch the path to the current jar file. Got this URISyntax exception:"+ex);
}
//If the jar path was created but doesn't contain .jar, we're (most likely) not running from jar
//typically this happens when running the program from IDE
//These 4 lines just serve as a fallback in testing, should be deleted in production
//code and replaced with another FileNotFoundException
if(!jarPath.contains(".jar")) {
Path currentRelativePath = Paths.get("");
jarPath = "\""+currentRelativePath.toAbsolutePath().toString()+"\\AutoClient.jar\"";
}
//Now we check if the path to vbs script exists, if it does we execute it
if(runAsAdmin.exists()) {
String command = "cscript \""+runAsAdmin.getAbsolutePath()+"\" "+jarPath;
System.out.println("Executing '"+command+"'");
//Note that .exec is asynchronous
//After it starts, you must terminate your program ASAP, or you'll have 2 instances running
Runtime.getRuntime().exec(command);
}
else
throw new FileNotFoundException("The VBSScript used for elevation not found at "+runAsAdmin.getAbsolutePath());
}
This is my version. It creates a VBScript script, then executes it. This only works if the program that is being run is in a jar file, so you will have to run your IDE as administrator to actually test your program.
public static void relaunchAsAdmin() throws IOException {
relaunchAsAdmin(ThisClass.class); //Change ThisClass to the class that this method is in
}
public static void relaunchAsAdmin(Class<?> clazz) throws IOException {
if(isCurrentProcessElevated()) {
return;
}
final String dir = System.getProperty("java.io.tmpdir");
final File script = new File(dir, "relaunchAsAdmin" + System.nanoTime() +
".vbs");
try {
script.createNewFile();
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(script));
osw.append("Set s=CreateObject(\"Shell.Application\")" + ln + "s.ShellExecute \"" +
System.getProperty("java.home") + "\\bin\\java.exe" + "\",\"-jar \"\"" +
new File(clazz.getProtectionDomain().getCodeSource(
).getLocation().toURI()).getAbsolutePath() + "\"\"\",,\"runas\",0" +
ln + "x=createObject(\"scripting.fileSystemObject\").deleteFile(" +
"WScript.scriptfullname)");
osw.close();
if(System.getenv("processor_architecture").equals("x86")) {
Runtime.getRuntime().exec("C:\\Windows\\System32\\wscript.exe \"" +
script.getAbsolutePath() + "\"");
} else {
Runtime.getRuntime().exec("C:\\Windows\\SysWoW64\\wscript.exe \"" +
script.getAbsolutePath() + "\"");
}
} catch(URISyntaxException e) {
e.printStackTrace();
}
Runtime.getRuntime().exit(0);
}
Note that it is a bit messy. I have been using this method before, so it has been line wrapped to 100 characters (except the comment I wrote for this answer). The
isCurrentProcessElevated()
method will have to be implemented in one way or another. You could try using JNI, or you could use a pure Java method, such as writing in the Program Files or System32 directory and seeing if it failed.
Obviously, this solution will only work on Windows. I never needed to elevate on Linux or Mac systems (mainly because I don't have any Mac systems, and I don't use Linux - I just play with it).

Netbeans Platform's toolbars are black when launching from inside IntelliJ

I am currently trying to port one of my applications over to the Netbeans Platform. Since I am an IntelliJ user, I prefer to work with my favourite IDE - and luckily there are tutorials for that.
After setting up everything I need, building the first test application (empty window) I wanted to go ahead and launch my app from inside IntelliJ. As this sadly is not as easy as it might sound (or I didnt find any other way yet) I followed this tutorial and created the following "Starter" class:
/**
* Represents a starter for the Netbeans platform.
*
* The original code of this modified class can be found at
* this article.
*/
public class NetbeansStarter {
private static final String BRANDING = "swordsmith";
private static final String WORKDIR = "application" + File.separatorChar + "target";
private static final String USER = WORKDIR + File.separatorChar + "userdir";
private static final String HOME = WORKDIR + File.separatorChar + BRANDING + File.separatorChar + "platform";
public static void main(String[] args) throws Exception {
// Cleanup the user's cache (otherwise problems arise, cache seems to be not written correctly).
deleteRecursive(new File(USER, "var" + File.separatorChar + "cache"));
// Set some system properties
System.setProperty("netbeans.logger.console", "true"); // for logging on the console
System.setProperty("netbeans.user", USER); // settings are stored here
System.setProperty("netbeans.home", HOME); // Netbeans cluster
System.setProperty("sun.awt.keepWorkingSetOnMinimize", "true"); // maven sets this per default on starting
// Build new arguments list
final List<String> list = new LinkedList<String>();
list.addAll(Arrays.asList("--branding", BRANDING));
list.addAll(Arrays.asList(args));
Main.main(list.toArray(new String[list.size()]));
}
#SuppressWarnings("ResultOfMethodCallIgnored")
private static void deleteRecursive(File pPath) {
if (!pPath.exists()) {
return;
}
File[] files = pPath.listFiles();
if (files == null) {
return ;
}
for (File file : files) {
if (file.isDirectory()) deleteRecursive(file);
else file.delete();
}
}
}
However, upon launch I am being presented with this screen which clearly shows what's wrong with it:
Is there something I've missed? Much thanks in advance!
I was actually able to fix this by just upgrading to the 802 version of netbeans platform. seems like this was an issue and has been fixed!

Using displayLogs() in WLSTInterpreter NameError: displayLogs

I am attempting to get a log output from the displayLogs() command and I have trying to do this within the WLST Interpreter. I get the following error which is "NameError: displayLogs" I am able to perform other commands such as domainRuntime() and a number of others, but this one seems to be outside the realm. Do I need to run it with some sort of classes in the classpath when running it? Any help would be appreciated.
The source code that I am using below:
package wlst;
import weblogic.management.scripting.utils.WLSTInterpreter;
import org.python.util.InteractiveInterpreter;
import org.python.core.PyObject;
public class EmbeddedWLST
{
static InteractiveInterpreter interpreter = null;
EmbeddedWLST() {
interpreter = new WLSTInterpreter();
}
private static void connect() {
StringBuffer buffer = new StringBuffer();
buffer.append("connect('USERNAME','PASSWORD','t3://HOSTANAME:PORT')");
interpreter.exec(buffer.toString());
}
public static void main(String[] args) {
new EmbeddedWLST();
connect();
PyObject cmo = interpreter.get("cmo");
String command = getLogs();
System.out.println("Executing Get Logs");
interpreter.exec(command);
System.out.println("Getting Output Object");
PyObject output = interpreter.get("output");
System.out.println(output.getClass());
System.out.println(output);
}
private static String getLogs() {
StringBuffer buf = new StringBuffer();
buf.append( "output = displayLogs(returnData=1)\n" );
return buf.toString();
}
}
UPDATE
Everything you are looking for lives in:
<install dir>/oracle_common/common/wlst
A simple grep -R displayLogs * returned the python module you need:
<install dir>/oracle_common/common/wlst/oracle-logging.py
You will need to include the jars that script needs on your classpath, specifically the logging jar ojdl.jar found under <install dir>/oracle_common/modules/oracle.odl
The above information was found by comparing the scripts below (I am using 10.3.6):
This script <install dir>/wlserver_10.3/common/bin/wlst.sh fails with:
wls:/offline> listLogs()
Traceback (innermost last):
File "<console>", line 1, in ?
NameError: listLogs
This script <install dir>/oracle_common/common/bin/wlst.sh succeeds (and has many more options than the script above) :
wls:/offline> listLogs()
Not connected to a Weblogic server. Connect to a Weblogic server first.
Make sure you have all the same jars and properties set as the second script does.

How to use Apache Commons CLI to parse the property file and --help option?

I have a property file which is like this -
hostName=machineA.domain.host.com
emailFrom=tester#host.com
emailTo=world#host.com
emailCc=hello#host.com
And now I am reading the above property file from my Java program as shown below. I am parsing the above property file manual way as of now -
public class FileReaderTask {
private static String hostName;
private static String emailFrom;
private static String emailTo;
private static String emailCc;
private static final String configFileName = "config.properties";
private static final Properties prop = new Properties();
public static void main(String[] args) {
readConfig(arguments);
// use the above variables here
System.out.println(hostName);
System.out.println(emailFrom);
System.out.println(emailTo);
System.out.println(emailCc);
}
private static void readConfig(String[] args) throws FileNotFoundException, IOException {
if (!TestUtils.isEmpty(args) && args.length != 0) {
prop.load(new FileInputStream(args[0]));
} else {
prop.load(FileReaderTask.class.getClassLoader().getResourceAsStream(configFileName));
}
StringBuilder sb = new StringBuilder();
for (String arg : args) {
sb.append(arg).append("\n");
}
String commandlineProperties = sb.toString();
if (!commandlineProperties.isEmpty()) {
// read, and overwrite, properties from the commandline...
prop.load(new StringReader(commandlineProperties));
}
hostName = prop.getProperty("hostName").trim();
emailFrom = prop.getProperty("emailFrom").trim();
emailTo = prop.getProperty("emailTo").trim();
emailCc = prop.getProperty("emailCc").trim();
}
}
Most of the time, I will be running my above program through command line as a runnable jar like this -
java -jar abc.jar config.properties
java -jar abc.jar config.properties hostName=machineB.domain.host.com
My question is-
Is there any way to add --help option while running the abc.jar that can tell us more about how to run the jar file and what does each property means and how to use them? I have seen --help while running most of the C++ executable or Unix stuff so not sure how we can do the same thing in Java?
Do I need to use CommandLine parser like Commons CLI for this in Java to achieve this and instead of doing manual parsing, I should use Commons CLI to parse the file as well? If yes, then can anyone provide an example how would I do that in my scenario?
In the long run if you plan to add other options in the future then commons-cli is surely a fairly good fit as it makes it easy to add new options and manual parsing quickly becomes complicated.
Take a look at the official examples, they provide a good overview of what the library can do.
Your specific case would probably lead to something like the following:
// create Options object
Options options = new Options();
Option help = new Option( "h", "help", false, "print this message" );
options.addOption(help);
CommandLineParser parser = new PosixParser();
CommandLine cmd = parser.parse( options, args);
if(cmd.hasOption("help") || cmd.getArgList().isEmpty()) {
// automatically generate the help statement
HelpFormatter formatter = new HelpFormatter();
formatter.printHelp( "cli-test [options] <property-file>", options );
return;
}
// do your thing...
System.out.println("Had properties " + cmd.getArgList());

Need to get Start Menu Paths in Java

Using java, I would like some code that could get me the paths for:
1) Start Menu for Current User
2) Start Menu for All User
I need the answer for both WinXP and Win7. So hopefully there is a general answer that can get me both.
You have no other choice but to write a DLL and call native Windows API:
SHGetFolderPath(NULL, CSIDL_PROGRAMS, NULL, SHGFP_TYPE_CURRENT, &szPathBuffer)
SHGetFolderPath(NULL, CSIDL_COMMON_PROGRAMS, NULL, SHGFP_TYPE_CURRENT, &szPathBuffer)
If you really need the root of Start menu, use CSIDL_STARTMENU and CSIDL_COMMON_STARTMENU.
The full list of known folders: CSIDL.
If you target Windows Vista and above, use SHGetKnownFolderPath function instead of SHGetFolderPath.
You can use JNA library to call native Windows API without writing native code yourself but pure Java code.
Okay, I figured out a solution, but maybe someone else has a more eligant one.
I plan on doing something like "Runtime.getRuntime().exec(command);" and the command will be a "reg query" to query the following registry keys:
Current User can referenced by: HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders\Start Menu
All users can be referenced by: HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders\Common Start Menu
These are the same for both Win7 and WinXP. If anyone else knows of a better solution, I'll be happy to look at it too.
In my program I used a simple System.getProperty("user.home") + "/Start Menu/Programs" This gave me the user's Start Menu folder.
It worked on windows 7 and windows 10. I tried this because in order to get a user's desktop, all I had to do was call System.getProperty("user.home") + "/Desktop". SO I figured that it might work for the Start Menu as well, and seemed to have worked fine. I can delete and write files to the Start Menu just like I can with the desktop. Whether this is the right way to do something like this or not, I have no idea. But I'm just sharing what worked for me.
Another option is managing Start Menu items from vbs API.
I made a Java Wrapper for that.
// Install Start Menu
WindowsUtils.installStartMenuItem(WindowsUtils.SPECIALFOLDER_Programs,"my_start_menu", "explorer.exe", "http://www.google.es","Acceso directo a google");
// Uninstall Start Menu
WindowsUtils.uninstallStartMenuItem(WindowsUtils.SPECIALFOLDER_Programs, "my_start_menu");
i recently found this
public class VBSUtils {
public static String SF_ALLUSERSDESKTOP = "AllUsersDesktop";
public static String SF_ALLUSERSSTARTMENU = "AllUsersStartMenu";
public static String SF_ALLUSERSPROGRAMS = "AllUsersPrograms";
public static String SF_ALLUSERSSTARTUP = "AllUsersStartup";
public static String SF_DESKTOP = "Desktop";
public static String SF_FAVORITES = "Favorites";
public static String SF_MYDOCUMENT = "MyDocuments";
public static String SF_PROGRAMS = "Programs";
public static String SF_RECENT = "Recent";
public static String SF_SENDTO = "SendTo";
public static String SF_STARTMENU = "StartMenu";
private VBSUtils() { }
public static String getSpecialFolder(String folder) {
String result = "";
try {
File file = File.createTempFile("realhowto",".vbs");
file.deleteOnExit();
FileWriter fw = new java.io.FileWriter(file);
String vbs = "Set WshShell = WScript.CreateObject(\"WScript.Shell\")\n"
+ "wscript.echo WshShell.SpecialFolders(\"" + folder + "\")\n"
+ "Set WSHShell = Nothing\n";
fw.write(vbs);
fw.close();
Process p = Runtime.getRuntime().exec("cscript //NoLogo " + file.getPath());
BufferedReader input =
new BufferedReader
(new InputStreamReader(p.getInputStream()));
result = input.readLine();
input.close();
}
catch(Exception e){
e.printStackTrace();
}
return result;
}
public static void main(String[] args){
System.out.println(VBSUtils.getSpecialFolder(VBSUtils.SF_ALLUSERSSTARTMENU));
System.out.println(VBSUtils.getSpecialFolder(VBSUtils.SF_ALLUSERSDESKTOP));
System.out.println(VBSUtils.getSpecialFolder(VBSUtils.SF_DESKTOP));
System.out.println(VBSUtils.getSpecialFolder(VBSUtils.SF_PROGRAMS));
//System.out.println(VBSUtils.getSpecialFolder(VBSUtils.SF_STARTUP));
}
}

Categories